From 9eaca1db83a077cfdaac0e2128e159b65a591083 Mon Sep 17 00:00:00 2001 From: gfcapalbo Date: Tue, 18 Nov 2014 16:48:13 +0100 Subject: [PATCH 01/26] [UPD] move out from unported to 8 for update [UPG] Upgraded to version 8, fixed references to new 8.0 views and moved fields that were in product.product to product.template [fix] remove duplicate view and correct view name [UPG][FIX] added outgoing field XML, that was in the base stock field in 7.0. [UPG] stock available immediately, corrected the calculation method of immediately_usable_qty to take in accountthe sign change in outgoing_qty (from negative to positive) in version 8. [FLAKE8] [FIX] renaming of a class, comment removing, useless code. [UPD] move out from unported to 8 for update [fix] remove duplicate view and correct view name [UPG][FIX] added outgoing field XML, that was in the base stock field in 7.0. [FIX] renaming of a class, comment removing, useless code. [fix] remove duplicate view and correct view name [UPG][FIX] added outgoing field XML, that was in the base stock field in 7.0. [UPD] move out from unported to 8 for update [fix] remove duplicate view and correct view name [UPG][FIX] added outgoing field XML, that was in the base stock field in 7.0. [FIX] renaming of a class, comment removing, useless code. [UPD] move out from unported to 8 for update [fix] remove duplicate view and correct view name [UPG][FIX] added outgoing field XML, that was in the base stock field in 7.0. [FIX] renaming of a class, comment removing, useless code. [UPD] move out from unported to 8 for update [fix] remove duplicate view and correct view name [UPG][FIX] added outgoing field XML, that was in the base stock field in 7.0. [FIX] renaming of a class, comment removing, useless code. [fix] remove duplicate view and correct view name [UPG][FIX] added outgoing field XML, that was in the base stock field in 7.0. [UPD] move out from unported to 8 for update [fix] remove duplicate view and correct view name [UPG][FIX] added outgoing field XML, that was in the base stock field in 7.0. [FIX] renaming of a class, comment removing, useless code. --- .../__init__.py | 0 .../__openerp__.py | 2 +- .../product.py | 22 ++++--------------- .../product_view.xml | 16 +++++++++----- stock_reserve/view/product.xml | 17 +------------- 5 files changed, 16 insertions(+), 41 deletions(-) rename {__unported__/stock_available_immediately => stock_available_immediately}/__init__.py (100%) rename {__unported__/stock_available_immediately => stock_available_immediately}/__openerp__.py (98%) rename {__unported__/stock_available_immediately => stock_available_immediately}/product.py (87%) rename {__unported__/stock_available_immediately => stock_available_immediately}/product_view.xml (75%) diff --git a/__unported__/stock_available_immediately/__init__.py b/stock_available_immediately/__init__.py similarity index 100% rename from __unported__/stock_available_immediately/__init__.py rename to stock_available_immediately/__init__.py diff --git a/__unported__/stock_available_immediately/__openerp__.py b/stock_available_immediately/__openerp__.py similarity index 98% rename from __unported__/stock_available_immediately/__openerp__.py rename to stock_available_immediately/__openerp__.py index 080dbe620..1cedaa84f 100644 --- a/__unported__/stock_available_immediately/__openerp__.py +++ b/stock_available_immediately/__openerp__.py @@ -36,5 +36,5 @@ Immediately usable is computed : Quantity on Hand - Outgoing Stock. "data": ["product_view.xml", ], "active": False, - 'installable': False + 'installable': True } diff --git a/__unported__/stock_available_immediately/product.py b/stock_available_immediately/product.py similarity index 87% rename from __unported__/stock_available_immediately/product.py rename to stock_available_immediately/product.py index cbc3a3639..fc3d1bd1a 100644 --- a/__unported__/stock_available_immediately/product.py +++ b/stock_available_immediately/product.py @@ -24,38 +24,24 @@ from openerp.addons import decimal_precision as dp from openerp.osv import orm, fields -class product_immediately_usable(orm.Model): +class ProductTemplate(orm.Model): """ - Inherit Product in order to add an "immediately usable quantity" - stock field Immediately usable quantity is : real stock - outgoing qty """ - _inherit = 'product.product' + _inherit = 'product.template' def _product_available(self, cr, uid, ids, field_names=None, arg=False, context=None): """ Get super() _product_available and compute immediately_usable_qty """ - # We need available and outgoing quantities to compute - # immediately usable quantity. - # When immediately_usable_qty is displayed but - # not qty_available and outgoing_qty, - # they are not computed in the super method so we cannot - # compute immediately_usable_qty. - # To avoid this issue, we add the 2 fields in - # field_names to compute them. - if 'immediately_usable_qty' in field_names: - field_names.append('qty_available') - field_names.append('outgoing_qty') - - res = super(product_immediately_usable, self)._product_available( + res = super(ProductTemplate, self)._product_available( cr, uid, ids, field_names, arg, context) if 'immediately_usable_qty' in field_names: for product_id, stock_qty in res.iteritems(): res[product_id]['immediately_usable_qty'] = \ - stock_qty['qty_available'] + stock_qty['outgoing_qty'] + stock_qty['qty_available'] - stock_qty['outgoing_qty'] return res diff --git a/__unported__/stock_available_immediately/product_view.xml b/stock_available_immediately/product_view.xml similarity index 75% rename from __unported__/stock_available_immediately/product_view.xml rename to stock_available_immediately/product_view.xml index 058da3d14..bdd7873f9 100644 --- a/__unported__/stock_available_immediately/product_view.xml +++ b/stock_available_immediately/product_view.xml @@ -11,20 +11,24 @@ product.normal.stock.active.qty.form.inherit - product.product - + product.template + + + + + - + - + product_immediately_usable.product_product_tree_view - product.product - + product.template + diff --git a/stock_reserve/view/product.xml b/stock_reserve/view/product.xml index e4e1dc3fb..09ff9a2fe 100644 --- a/stock_reserve/view/product.xml +++ b/stock_reserve/view/product.xml @@ -1,25 +1,10 @@ - - - product.template.reservation.button - product.template - - - - - - - - product.template.reservation.button product.product - + - - - - product.template.reservation.button product.product - + + + + + + + + + product.template.reservation.button product.product From f7270112753c0b19a1e626ea1cc64c6225d0c758 Mon Sep 17 00:00:00 2001 From: gfcapalbo Date: Wed, 18 Feb 2015 16:29:31 +0100 Subject: [PATCH 04/26] [FLAKE8] plus small fix --- stock_available_immediately/product.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/stock_available_immediately/product.py b/stock_available_immediately/product.py index 6ee673a9c..8e6a7dc95 100644 --- a/stock_available_immediately/product.py +++ b/stock_available_immediately/product.py @@ -23,7 +23,6 @@ from openerp.addons import decimal_precision as dp from openerp.osv import orm, fields -<<<<<<< HEAD:stock_available_immediately/product.py class ProductTemplate(orm.Model): """ Immediately usable quantity is : real stock - outgoing qty @@ -32,7 +31,7 @@ class ProductTemplate(orm.Model): def _product_available(self, cr, uid, ids, field_names=None, arg=False, context=None): - res = super(Product, self)._product_available( + res = super(ProductTemplate, self)._product_available( cr, uid, ids, field_names, arg, context) if 'immediately_usable_qty' in field_names: From f8038294dab85813897fb0d5aad6b4df344dd02a Mon Sep 17 00:00:00 2001 From: gfcapalbo Date: Wed, 25 Feb 2015 10:31:23 +0100 Subject: [PATCH 05/26] [FIX] Stock_reserve change revert --- stock_reserve/view/product.xml | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/stock_reserve/view/product.xml b/stock_reserve/view/product.xml index 76c979362..ca427c8e1 100644 --- a/stock_reserve/view/product.xml +++ b/stock_reserve/view/product.xml @@ -1,19 +1,19 @@ - - product.template.reservation.button - product.template - - - - - - - + + product.template.reservation.button + product.template + + + + + + + From 820f8d4c0b85f6dff131fa38163f783caa6cb8dc Mon Sep 17 00:00:00 2001 From: "Giovanni Capalbo (Therp)" Date: Wed, 25 Feb 2015 11:35:18 +0100 Subject: [PATCH 06/26] Update product.xml --- stock_reserve/view/product.xml | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/stock_reserve/view/product.xml b/stock_reserve/view/product.xml index ca427c8e1..6f1177b95 100644 --- a/stock_reserve/view/product.xml +++ b/stock_reserve/view/product.xml @@ -1,8 +1,9 @@ + - product.template.reservation.button + product.template.reservation.button product.template @@ -15,10 +16,6 @@ - - - - product.template.reservation.button product.product From 3bde29529d9171f4d331a3ffd14738b6a4f8936c Mon Sep 17 00:00:00 2001 From: "Giovanni Capalbo (Therp)" Date: Wed, 25 Feb 2015 11:41:30 +0100 Subject: [PATCH 07/26] Update product.xml --- stock_reserve/view/product.xml | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/stock_reserve/view/product.xml b/stock_reserve/view/product.xml index 6f1177b95..66a679665 100644 --- a/stock_reserve/view/product.xml +++ b/stock_reserve/view/product.xml @@ -2,19 +2,19 @@ - - product.template.reservation.button - product.template - - - - - - - + + product.template.reservation.button + product.template + + + + + + + product.template.reservation.button From cb186fe1790fdb322ca14e3aa1f144e9bf78df44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lionel=20Sausin=20=28Num=C3=A9rigraphe=29?= Date: Fri, 27 Feb 2015 13:43:56 +0100 Subject: [PATCH 08/26] [ADD] stock_available Generic module to compute the stock quantity available to promise using several implementations. stock_available_immediatly is changed to become the first optional implementation. Cherry pick of commit 0b060f619fa5d60f9fb343afe1154acd5c730148 from the v7 branch --- stock_available/__init__.py | 24 ++++ stock_available/__openerp__.py | 42 ++++++ stock_available/i18n/fr.po | 98 ++++++++++++++ stock_available/i18n/stock_available.pot | 92 +++++++++++++ stock_available/product.py | 100 ++++++++++++++ .../product_view.xml | 34 +++-- stock_available/res_config.py | 34 +++++ stock_available/res_config_view.xml | 25 ++++ stock_available_immediately/__openerp__.py | 30 +++-- stock_available_immediately/product.py | 123 +++++------------- 10 files changed, 478 insertions(+), 124 deletions(-) create mode 100644 stock_available/__init__.py create mode 100644 stock_available/__openerp__.py create mode 100644 stock_available/i18n/fr.po create mode 100644 stock_available/i18n/stock_available.pot create mode 100644 stock_available/product.py rename {stock_available_immediately => stock_available}/product_view.xml (54%) create mode 100644 stock_available/res_config.py create mode 100644 stock_available/res_config_view.xml diff --git a/stock_available/__init__.py b/stock_available/__init__.py new file mode 100644 index 000000000..6755b49d2 --- /dev/null +++ b/stock_available/__init__.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# This module is copyright (C) 2014 Numérigraphe SARL. All Rights Reserved. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from . import product +from . import res_config + +from .product import _product_available_fnct diff --git a/stock_available/__openerp__.py b/stock_available/__openerp__.py new file mode 100644 index 000000000..16ea5f8ab --- /dev/null +++ b/stock_available/__openerp__.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# This module is copyright (C) 2014 Numérigraphe SARL. All Rights Reserved. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +{ + 'name': 'Stock available to promise', + 'version': '2.0', + 'author': u'Numérigraphe', + 'category': 'Warehouse', + 'depends': ['stock'], + 'description': """ +Stock available to promise +========================== +This module proposes several options to compute the quantity available to +promise for each product. +This quantity is based on the projected stock and, depending on the +configuration, it can account for various data such as sales quotations or +immediate production capacity. +This can be configured in the menu Settings > Configuration > Warehouse. +""", + 'license': 'AGPL-3', + 'data': [ + 'product_view.xml', + 'res_config_view.xml', + ] +} diff --git a/stock_available/i18n/fr.po b/stock_available/i18n/fr.po new file mode 100644 index 000000000..6c8e4c244 --- /dev/null +++ b/stock_available/i18n/fr.po @@ -0,0 +1,98 @@ +# Translation of OpenERP Server. +# This file contains the translation of the following modules: +# * stock_available +# +msgid "" +msgstr "" +"Project-Id-Version: OpenERP Server 7.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-07-30 16:42+0000\n" +"PO-Revision-Date: 2014-07-30 16:42+0000\n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: stock_available +#: field:product.product,immediately_usable_qty:0 +msgid "Available to promise" +msgstr "Disponible à la vente" + +#. module: stock_available +#: view:product.product:0 +msgid "Available to promise:" +msgstr "Disponible à la vente:" + +#. module: stock_available +#: field:stock.config.settings,module_stock_available_sale:0 +msgid "Exclude goods already in sale quotations" +msgstr "Exclure les marchandises qui sont déjà dans les devis" + +#. module: stock_available +#: field:stock.config.settings,module_stock_available_immediately:0 +msgid "Exclude incoming goods" +msgstr "Exclure les receptions attendues" + +#. module: stock_available +#: field:stock.config.settings,module_stock_available_mrp:0 +msgid "Include the production potential" +msgstr "Inclure la production potentielle" + +#. module: stock_available +#: code:_description:0 +#: model:ir.model,name:stock_available.model_product_product +#, python-format +msgid "Product" +msgstr "Article" + +#. module: stock_available +#: view:stock.config.settings:0 +msgid "Stock available to promise" +msgstr "Stock disponible à la vente" + +#. module: stock_available +#: help:product.product,immediately_usable_qty:0 +msgid "Stock for this Product that can be safely proposed for sale to Customers.\n" +"The definition of this value can be configured to suit your needs" +msgstr "Stock de cet article qui peut sans risque être proposé à la vente aux clients.\n" +"La définition de cette valeur est paramétrable selon vos besoins" + +#. module: stock_available +#: help:stock.config.settings,module_stock_available_mrp:0 +msgid "This will add the quantities of goods that can be immediately manufactured, to the quantities available to promise.\n" +"This installs the module stock_available_mrp.\n" +"If the module mrp is not installed, this will install it too" +msgstr "Ceci ajoute les quantités de marchandises qui peuvent être immédiatement fabriquées, aux quantitiés disponibles à la vente.\n" +"Ceci installe le module stock_available_mrp.\n" +"Si le module mrp n'est pas encore installé, il le sera aussi" + +#. module: stock_available +#: help:stock.config.settings,module_stock_available_immediately:0 +msgid "This will subtract incoming quantities from the quantities available to promise.\n" +"This installs the module stock_available_immediately." +msgstr "Ceci soustrait les réceptions attendues des quantitiés disponibles à la vente.\n" +"Ceci installe le module stock_available_immediately." + +#. module: stock_available +#: help:stock.config.settings,module_stock_available_sale:0 +msgid "This will subtract quantities from the sale quotations from the quantities available to promise.\n" +"This installs the modules stock_available_sale.\n" +"If the modules sale and sale_delivery_date are not installed, this will install them too" +msgstr "Ceci soustrait les quantités des devis de vente des quantitiés disponibles à la vente.\n" +"Ceci installe le modules stock_available_sale.\n" +"Si les modules sale et sale_delivery_date ne sont pas encore installés, ils le seront également" + +#. module: stock_available +#: view:product.product:0 +msgid "red:immediately_usable_qty<0;blue:immediately_usable_qty>=0 and state in ('draft', 'end', 'obsolete');black:immediately_usable_qty>=0 and state not in ('draft', 'end', 'obsolete')" +msgstr "red:immediately_usable_qty<0;blue:immediately_usable_qty>=0 and state in ('draft', 'end', 'obsolete');black:immediately_usable_qty>=0 and state not in ('draft', 'end', 'obsolete')" + +#. module: stock_available +#: code:_description:0 +#: model:ir.model,name:stock_available.model_stock_config_settings +#, python-format +msgid "stock.config.settings" +msgstr "stock.config.settings" + diff --git a/stock_available/i18n/stock_available.pot b/stock_available/i18n/stock_available.pot new file mode 100644 index 000000000..6eed1c952 --- /dev/null +++ b/stock_available/i18n/stock_available.pot @@ -0,0 +1,92 @@ +# Translation of OpenERP Server. +# This file contains the translation of the following modules: +# * stock_available +# +msgid "" +msgstr "" +"Project-Id-Version: OpenERP Server 7.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-07-30 16:48+0000\n" +"PO-Revision-Date: 2014-07-30 16:48+0000\n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: stock_available +#: field:product.product,immediately_usable_qty:0 +msgid "Available to promise" +msgstr "" + +#. module: stock_available +#: view:product.product:0 +msgid "Available to promise:" +msgstr "" + +#. module: stock_available +#: field:stock.config.settings,module_stock_available_sale:0 +msgid "Exclude goods already in sale quotations" +msgstr "" + +#. module: stock_available +#: field:stock.config.settings,module_stock_available_immediately:0 +msgid "Exclude incoming goods" +msgstr "" + +#. module: stock_available +#: field:stock.config.settings,module_stock_available_mrp:0 +msgid "Include the production potential" +msgstr "" + +#. module: stock_available +#: code:_description:0 +#: model:ir.model,name:stock_available.model_product_product +#, python-format +msgid "Product" +msgstr "" + +#. module: stock_available +#: view:stock.config.settings:0 +msgid "Stock available to promise" +msgstr "" + +#. module: stock_available +#: help:product.product,immediately_usable_qty:0 +msgid "Stock for this Product that can be safely proposed for sale to Customers.\n" +"The definition of this value can be configured to suit your needs" +msgstr "" + +#. module: stock_available +#: help:stock.config.settings,module_stock_available_mrp:0 +msgid "This will add the quantities of goods that can be immediately manufactured, to the quantities available to promise.\n" +"This installs the module stock_available_mrp.\n" +"If the module mrp is not installed, this will install it too" +msgstr "" + +#. module: stock_available +#: help:stock.config.settings,module_stock_available_immediately:0 +msgid "This will subtract incoming quantities from the quantities available to promise.\n" +"This installs the module stock_available_immediately." +msgstr "" + +#. module: stock_available +#: help:stock.config.settings,module_stock_available_sale:0 +msgid "This will subtract quantities from the sale quotations from the quantities available to promise.\n" +"This installs the modules stock_available_sale.\n" +"If the modules sale and sale_delivery_date are not installed, this will install them too" +msgstr "" + +#. module: stock_available +#: view:product.product:0 +msgid "red:immediately_usable_qty<0;blue:immediately_usable_qty>=0 and state in ('draft', 'end', 'obsolete');black:immediately_usable_qty>=0 and state not in ('draft', 'end', 'obsolete')" +msgstr "" + +#. module: stock_available +#: code:_description:0 +#: model:ir.model,name:stock_available.model_stock_config_settings +#, python-format +msgid "stock.config.settings" +msgstr "" + diff --git a/stock_available/product.py b/stock_available/product.py new file mode 100644 index 000000000..a4a528eb7 --- /dev/null +++ b/stock_available/product.py @@ -0,0 +1,100 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# This module is copyright (C) 2014 Numérigraphe SARL. All Rights Reserved. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from openerp.osv import orm, fields +import openerp.addons.decimal_precision as dp + + +# Expose the method as a function, like when the fields are defined, +# and use the pool to call the method from the other modules too. +def _product_available_fnct(self, cr, uid, ids, field_names=None, arg=False, + context=None): + return self.pool['product.product']._product_available( + cr, uid, ids, field_names=field_names, arg=arg, context=context) + + +class ProductProduct(orm.Model): + """Add a field for the stock available to promise. + + Useful implementations need to be installed through the Settings menu or by + installing one of the modules stock_available_* + """ + _inherit = 'product.product' + + def __init__(self, pool, cr): + """Use _product_available_fnct to compute all the quantities.""" + # Doing this lets us change the function and not redefine fields + super(ProductProduct, self).__init__(pool, cr) + for coldef in self._columns.values(): + if (isinstance(coldef, fields.function) + and coldef._multi == 'qty_available'): + coldef._fnct = _product_available_fnct + + def _product_available(self, cr, uid, ids, field_names=None, arg=False, + context=None): + """No-op implementation of the stock available to promise. + + Must be overridden by another module that actually implement + computations. + The sub-modules MUST call super()._product_available BEFORE their own + computations + + Side-effect warning: This method may change the list passed as the + field_names parameter, which will then alter the caller's state.""" + # If we didn't get a field_names list, there's nothing to do + if field_names is None: + return super(ProductProduct, self)._product_available( + cr, uid, ids, field_names=field_names, arg=arg, + context=context) + + if context is None: + context = {} + + # Load virtual_available if it's not already asked for + # We need it to compute immediately_usable_qty + # We DO want to change the caller's list so we're NOT going to + # work on a copy of field_names. + if ('virtual_available' not in field_names + and 'immediately_usable_qty' in field_names): + field_names.append('virtual_available') + + # Compute the core quantities + res = super(ProductProduct, self)._product_available( + cr, uid, ids, field_names=field_names, arg=arg, context=context) + + # By default, available to promise = forecasted quantity + if ('immediately_usable_qty' in field_names): + for stock_qty in res.itervalues(): + stock_qty['immediately_usable_qty'] = \ + stock_qty['virtual_available'] + + return res + + _columns = { + 'immediately_usable_qty': fields.function( + _product_available_fnct, multi='qty_available', + type='float', + digits_compute=dp.get_precision('Product Unit of Measure'), + string='Available to promise', + help="Stock for this Product that can be safely proposed " + "for sale to Customers.\n" + "The definition of this value can be configured to suit " + "your needs"), + } diff --git a/stock_available_immediately/product_view.xml b/stock_available/product_view.xml similarity index 54% rename from stock_available_immediately/product_view.xml rename to stock_available/product_view.xml index bdd7873f9..d05270f75 100644 --- a/stock_available_immediately/product_view.xml +++ b/stock_available/product_view.xml @@ -1,32 +1,20 @@ - - - - - product.normal.stock.active.qty.form.inherit + + Quantity available to promise (form) product.template - - - - - - - product_immediately_usable.product_product_tree_view + + + Quantity available to promise (tree) product.template @@ -34,12 +22,22 @@ red:immediately_usable_qty<0;blue:immediately_usable_qty>=0 and state in ('draft', 'end', 'obsolete');black:immediately_usable_qty>=0 and state not in ('draft', 'end', 'obsolete') - + + + Quantity available to promise (kanban) + product.template + + + +
  • Available to promise:
  • +
    +
    +
    diff --git a/stock_available/res_config.py b/stock_available/res_config.py new file mode 100644 index 000000000..535f58460 --- /dev/null +++ b/stock_available/res_config.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# This module is copyright (C) 2014 Numérigraphe SARL. All Rights Reserved. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +############################################################################## + +from openerp.osv import orm, fields + + +class StockConfig(orm.TransientModel): + """Add options to easily install the submodules""" + _inherit = 'stock.config.settings' + + _columns = { + 'module_stock_available_immediately': fields.boolean( + 'Exclude incoming goods', + help="This will subtract incoming quantities from the quantities " + "available to promise.\n" + "This installs the module stock_available_immediately."), + } diff --git a/stock_available/res_config_view.xml b/stock_available/res_config_view.xml new file mode 100644 index 000000000..15e45c031 --- /dev/null +++ b/stock_available/res_config_view.xml @@ -0,0 +1,25 @@ + + + + + Stock settings: quantity available to promise + stock.config.settings + + + + + + + + + + + + \ No newline at end of file diff --git a/stock_available_immediately/__openerp__.py b/stock_available_immediately/__openerp__.py index 1cedaa84f..838f9db4c 100644 --- a/stock_available_immediately/__openerp__.py +++ b/stock_available_immediately/__openerp__.py @@ -20,21 +20,27 @@ # # - { - "name": "Immediately Usable Stock Quantity", - "version": "1.0", - "depends": ["product", "stock", ], + "name": "Ignore planned receptions in quantity available to promise", + "version": "2.0", + "depends": ["stock_available"], "author": "Camptocamp", "license": "AGPL-3", - "description": """ -Compute the immediately usable stock. -Immediately usable is computed : Quantity on Hand - Outgoing Stock. + "description": u""" +Ignore planned receptions in quantity available to promise +---------------------------------------------------------- + +Normally the quantity available to promise is based on the virtual stock, +which includes both planned outgoing and incoming goods. +This module will subtract the planned receptions from the quantity available to +promise. + +Contributors +------------ + * Author: Guewen Baconnier (Camptocamp SA) + * Sébastien BEAU (Akretion) + * Lionel Sausin (Numérigraphe) """, - "website": "http://tinyerp.com/module_account.html", - "category": "Generic Modules/Stock", - "data": ["product_view.xml", - ], - "active": False, + "category": "Hidden", 'installable': True } diff --git a/stock_available_immediately/product.py b/stock_available_immediately/product.py index 8e6a7dc95..939bbbb9d 100644 --- a/stock_available_immediately/product.py +++ b/stock_available_immediately/product.py @@ -19,106 +19,41 @@ # ############################################################################## -from openerp.addons import decimal_precision as dp +from openerp.osv import orm + from openerp.osv import orm, fields +class product_immediately_usable(orm.Model): + """Subtract incoming qty from immediately_usable_qty -class ProductTemplate(orm.Model): - """ - Immediately usable quantity is : real stock - outgoing qty - """ - _inherit = 'product.template' + We don't need to override the function fields, the module stock_available + takes of it for us. + + Side-effect warning: This method may change the list passed as the + field_names parameter, which will then alter the caller's state.""" + _inherit = 'product.product' def _product_available(self, cr, uid, ids, field_names=None, arg=False, context=None): - res = super(ProductTemplate, self)._product_available( - cr, uid, ids, field_names, arg, context) + """Ignore the incoming goods in the quantity available to promise""" + # If we didn't get a field_names list, there's nothing to do + if field_names is None or 'immediately_usable_qty' not in field_names: + return super(product_immediately_usable, self)._product_available( + cr, uid, ids, field_names=field_names, arg=arg, + context=context) - if 'immediately_usable_qty' in field_names: - for product_id, stock_qty in res.iteritems(): - res[product_id]['immediately_usable_qty'] = \ - stock_qty['qty_available'] - stock_qty['outgoing_qty'] + # We need available and incoming quantities to compute + # immediately usable quantity. + # We DO want to change the caller's list so we're NOT going to + # work on a copy of field_names. + field_names.append('qty_available') + field_names.append('incoming_qty') + + res = super(product_immediately_usable, self)._product_available( + cr, uid, ids, field_names=field_names, arg=arg, context=context) + + for stock_qty in res.itervalues(): + stock_qty['immediately_usable_qty'] -= \ + stock_qty['incoming_qty'] return res - - _columns = { - 'qty_available': fields.function( - _product_available, - multi='qty_available', - type='float', - digits_compute=dp.get_precision('Product UoM'), - string='Quantity On Hand', - help="Current quantity of products.\n" - "In a context with a single Stock Location, this includes " - "goods stored at this Location, or any of its children.\n" - "In a context with a single Warehouse, this includes " - "goods stored in the Stock Location of this Warehouse, " - "or any " - "of its children.\n" - "In a context with a single Shop, this includes goods " - "stored in the Stock Location of the Warehouse of this Shop, " - "or any of its children.\n" - "Otherwise, this includes goods stored in any Stock Location " - "typed as 'internal'."), - 'virtual_available': fields.function( - _product_available, - multi='qty_available', - type='float', - digits_compute=dp.get_precision('Product UoM'), - string='Quantity Available', - help="Forecast quantity (computed as Quantity On Hand " - "- Outgoing + Incoming)\n" - "In a context with a single Stock Location, this includes " - "goods stored at this Location, or any of its children.\n" - "In a context with a single Warehouse, this includes " - "goods stored in the Stock Location of this Warehouse, " - "or any " - "of its children.\n" - "In a context with a single Shop, this includes goods " - "stored in the Stock Location of the Warehouse of this Shop, " - "or any of its children.\n" - "Otherwise, this includes goods stored in any Stock Location " - "typed as 'internal'."), - 'incoming_qty': fields.function( - _product_available, - multi='qty_available', - type='float', - digits_compute=dp.get_precision('Product UoM'), - string='Incoming', - help="Quantity of products that are planned to arrive.\n" - "In a context with a single Stock Location, this includes " - "goods arriving to this Location, or any of its children.\n" - "In a context with a single Warehouse, this includes " - "goods arriving to the Stock Location of this Warehouse, or " - "any of its children.\n" - "In a context with a single Shop, this includes goods " - "arriving to the Stock Location of the Warehouse of this " - "Shop, or any of its children.\n" - "Otherwise, this includes goods arriving to any Stock " - "Location typed as 'internal'."), - 'outgoing_qty': fields.function( - _product_available, - multi='qty_available', - type='float', - digits_compute=dp.get_precision('Product UoM'), - string='Outgoing', - help="Quantity of products that are planned to leave.\n" - "In a context with a single Stock Location, this includes " - "goods leaving from this Location, or any of its children.\n" - "In a context with a single Warehouse, this includes " - "goods leaving from the Stock Location of this Warehouse, or " - "any of its children.\n" - "In a context with a single Shop, this includes goods " - "leaving from the Stock Location of the Warehouse of this " - "Shop, or any of its children.\n" - "Otherwise, this includes goods leaving from any Stock " - "Location typed as 'internal'."), - 'immediately_usable_qty': fields.function( - _product_available, - digits_compute=dp.get_precision('Product UoM'), - type='float', - string='Immediately Usable', - multi='qty_available', - help="Quantity of products really available for sale." - "Computed as: Quantity On Hand - Outgoing."), - } From 8504307c7b3e83036935f0a14a9e2c9e3b6368c0 Mon Sep 17 00:00:00 2001 From: Lionel Sausin Date: Fri, 27 Feb 2015 16:39:03 +0100 Subject: [PATCH 09/26] [IMP] stock_available* uses new API --- stock_available/__init__.py | 2 - stock_available/__openerp__.py | 10 --- stock_available/product.py | 88 +++++----------------- stock_available/res_config.py | 16 ++-- stock_available_immediately/__openerp__.py | 15 ---- stock_available_immediately/product.py | 43 +++-------- 6 files changed, 37 insertions(+), 137 deletions(-) diff --git a/stock_available/__init__.py b/stock_available/__init__.py index 6755b49d2..6dff1269a 100644 --- a/stock_available/__init__.py +++ b/stock_available/__init__.py @@ -20,5 +20,3 @@ from . import product from . import res_config - -from .product import _product_available_fnct diff --git a/stock_available/__openerp__.py b/stock_available/__openerp__.py index 16ea5f8ab..28a6a7fde 100644 --- a/stock_available/__openerp__.py +++ b/stock_available/__openerp__.py @@ -24,16 +24,6 @@ 'author': u'Numérigraphe', 'category': 'Warehouse', 'depends': ['stock'], - 'description': """ -Stock available to promise -========================== -This module proposes several options to compute the quantity available to -promise for each product. -This quantity is based on the projected stock and, depending on the -configuration, it can account for various data such as sales quotations or -immediate production capacity. -This can be configured in the menu Settings > Configuration > Warehouse. -""", 'license': 'AGPL-3', 'data': [ 'product_view.xml', diff --git a/stock_available/product.py b/stock_available/product.py index a4a528eb7..08a8aa277 100644 --- a/stock_available/product.py +++ b/stock_available/product.py @@ -18,83 +18,35 @@ # ############################################################################## -from openerp.osv import orm, fields -import openerp.addons.decimal_precision as dp +from openerp import models, fields, api +#from openerp.addons import decimal_precision as dp -# Expose the method as a function, like when the fields are defined, -# and use the pool to call the method from the other modules too. -def _product_available_fnct(self, cr, uid, ids, field_names=None, arg=False, - context=None): - return self.pool['product.product']._product_available( - cr, uid, ids, field_names=field_names, arg=arg, context=context) - - -class ProductProduct(orm.Model): +class ProductTemplate(models.Model): """Add a field for the stock available to promise. Useful implementations need to be installed through the Settings menu or by installing one of the modules stock_available_* """ - _inherit = 'product.product' + _inherit = 'product.template' - def __init__(self, pool, cr): - """Use _product_available_fnct to compute all the quantities.""" - # Doing this lets us change the function and not redefine fields - super(ProductProduct, self).__init__(pool, cr) - for coldef in self._columns.values(): - if (isinstance(coldef, fields.function) - and coldef._multi == 'qty_available'): - coldef._fnct = _product_available_fnct - - def _product_available(self, cr, uid, ids, field_names=None, arg=False, - context=None): + @api.depends('virtual_available') + def _product_available(self): """No-op implementation of the stock available to promise. + By default, available to promise = forecasted quantity. + Must be overridden by another module that actually implement - computations. - The sub-modules MUST call super()._product_available BEFORE their own - computations + computations.""" + for product in self: + product.immediately_usable_qty = product.virtual_available - Side-effect warning: This method may change the list passed as the - field_names parameter, which will then alter the caller's state.""" - # If we didn't get a field_names list, there's nothing to do - if field_names is None: - return super(ProductProduct, self)._product_available( - cr, uid, ids, field_names=field_names, arg=arg, - context=context) - - if context is None: - context = {} - - # Load virtual_available if it's not already asked for - # We need it to compute immediately_usable_qty - # We DO want to change the caller's list so we're NOT going to - # work on a copy of field_names. - if ('virtual_available' not in field_names - and 'immediately_usable_qty' in field_names): - field_names.append('virtual_available') - - # Compute the core quantities - res = super(ProductProduct, self)._product_available( - cr, uid, ids, field_names=field_names, arg=arg, context=context) - - # By default, available to promise = forecasted quantity - if ('immediately_usable_qty' in field_names): - for stock_qty in res.itervalues(): - stock_qty['immediately_usable_qty'] = \ - stock_qty['virtual_available'] - - return res - - _columns = { - 'immediately_usable_qty': fields.function( - _product_available_fnct, multi='qty_available', - type='float', - digits_compute=dp.get_precision('Product Unit of Measure'), - string='Available to promise', - help="Stock for this Product that can be safely proposed " - "for sale to Customers.\n" - "The definition of this value can be configured to suit " - "your needs"), - } + immediately_usable_qty = fields.Float( + compute='_product_available', + string='Available to promise', + help="Stock for this Product that can be safely proposed " + "for sale to Customers.\n" + "The definition of this value can be configured to suit " + "your needs") + # XXX the standard doesn't honor the UoM decimal precision. Should we? + # digits=dp.get_precision('Product Unit of Measure'), diff --git a/stock_available/res_config.py b/stock_available/res_config.py index 535f58460..bf78bcb3b 100644 --- a/stock_available/res_config.py +++ b/stock_available/res_config.py @@ -18,17 +18,15 @@ # ############################################################################## -from openerp.osv import orm, fields +from openerp import models, fields -class StockConfig(orm.TransientModel): +class StockConfig(models.TransientModel): """Add options to easily install the submodules""" _inherit = 'stock.config.settings' - _columns = { - 'module_stock_available_immediately': fields.boolean( - 'Exclude incoming goods', - help="This will subtract incoming quantities from the quantities " - "available to promise.\n" - "This installs the module stock_available_immediately."), - } + module_stock_available_immediately = fields.Boolean( + string='Exclude incoming goods', + help="This will subtract incoming quantities from the quantities " + "available to promise.\n" + "This installs the module stock_available_immediately.") diff --git a/stock_available_immediately/__openerp__.py b/stock_available_immediately/__openerp__.py index 838f9db4c..197288c9b 100644 --- a/stock_available_immediately/__openerp__.py +++ b/stock_available_immediately/__openerp__.py @@ -26,21 +26,6 @@ "depends": ["stock_available"], "author": "Camptocamp", "license": "AGPL-3", - "description": u""" -Ignore planned receptions in quantity available to promise ----------------------------------------------------------- - -Normally the quantity available to promise is based on the virtual stock, -which includes both planned outgoing and incoming goods. -This module will subtract the planned receptions from the quantity available to -promise. - -Contributors ------------- - * Author: Guewen Baconnier (Camptocamp SA) - * Sébastien BEAU (Akretion) - * Lionel Sausin (Numérigraphe) -""", "category": "Hidden", 'installable': True } diff --git a/stock_available_immediately/product.py b/stock_available_immediately/product.py index 939bbbb9d..05d8ad2e7 100644 --- a/stock_available_immediately/product.py +++ b/stock_available_immediately/product.py @@ -19,41 +19,18 @@ # ############################################################################## -from openerp.osv import orm +from openerp import models, fields, api -from openerp.osv import orm, fields -class product_immediately_usable(orm.Model): - """Subtract incoming qty from immediately_usable_qty +class ProductTemplate(models.Model): + """Subtract incoming qty from immediately_usable_qty""" + _inherit = 'product.template' - We don't need to override the function fields, the module stock_available - takes of it for us. - - Side-effect warning: This method may change the list passed as the - field_names parameter, which will then alter the caller's state.""" - _inherit = 'product.product' - - def _product_available(self, cr, uid, ids, field_names=None, - arg=False, context=None): + @api.depends('virtual_available') + def _product_available(self): """Ignore the incoming goods in the quantity available to promise""" - # If we didn't get a field_names list, there's nothing to do - if field_names is None or 'immediately_usable_qty' not in field_names: - return super(product_immediately_usable, self)._product_available( - cr, uid, ids, field_names=field_names, arg=arg, - context=context) + super(ProductTemplate, self)._product_available() + for product in self: + product.immediately_usable_qty -= product.incoming_qty - # We need available and incoming quantities to compute - # immediately usable quantity. - # We DO want to change the caller's list so we're NOT going to - # work on a copy of field_names. - field_names.append('qty_available') - field_names.append('incoming_qty') - - res = super(product_immediately_usable, self)._product_available( - cr, uid, ids, field_names=field_names, arg=arg, context=context) - - for stock_qty in res.itervalues(): - stock_qty['immediately_usable_qty'] -= \ - stock_qty['incoming_qty'] - - return res + immediately_usable_qty = fields.Float(compute='_product_available') From 13c845fae7b99a0fdfe1c6cb792e33314641851d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lionel=20Sausin=20=28Num=C3=A9rigraphe=29?= Date: Fri, 28 Nov 2014 17:40:27 +0100 Subject: [PATCH 10/26] [ADD] stock_available_mrp Module to take immediate manufaturing capability into account in the stock quantity available to promise. Conflicts: stock_available/res_config.py --- stock_available/res_config.py | 9 ++ stock_available/res_config_view.xml | 4 + stock_available_mrp/__init__.py | 21 +++ stock_available_mrp/__openerp__.py | 39 ++++++ stock_available_mrp/i18n/fr.po | 34 +++++ .../i18n/stock_available_mrp.pot | 34 +++++ stock_available_mrp/product.py | 124 ++++++++++++++++++ stock_available_mrp/product_view.xml | 19 +++ stock_available_mrp/test/potential_qty.yml | 70 ++++++++++ 9 files changed, 354 insertions(+) create mode 100644 stock_available_mrp/__init__.py create mode 100644 stock_available_mrp/__openerp__.py create mode 100644 stock_available_mrp/i18n/fr.po create mode 100644 stock_available_mrp/i18n/stock_available_mrp.pot create mode 100644 stock_available_mrp/product.py create mode 100644 stock_available_mrp/product_view.xml create mode 100644 stock_available_mrp/test/potential_qty.yml diff --git a/stock_available/res_config.py b/stock_available/res_config.py index bf78bcb3b..7d4355df7 100644 --- a/stock_available/res_config.py +++ b/stock_available/res_config.py @@ -30,3 +30,12 @@ class StockConfig(models.TransientModel): help="This will subtract incoming quantities from the quantities " "available to promise.\n" "This installs the module stock_available_immediately.") + + module_stock_available_mrp = fields.Boolean( + string='Include the production potential', + help="This will add the quantities of goods that can be " + "immediately manufactured, to the quantities available to " + "promise.\n" + "This installs the module stock_available_mrp.\n" + "If the module mrp is not installed, this will install it " + "too") diff --git a/stock_available/res_config_view.xml b/stock_available/res_config_view.xml index 15e45c031..d4f378fb8 100644 --- a/stock_available/res_config_view.xml +++ b/stock_available/res_config_view.xml @@ -15,6 +15,10 @@