From 7cc0b2beab528ef3921fe9bd8e72b7943b874925 Mon Sep 17 00:00:00 2001 From: Alexandre Fayolle Date: Mon, 26 Oct 2015 13:56:24 +0100 Subject: [PATCH 1/2] product_available improvements * fix the dependencies for the computed field * use api.multi instead of api.one to avoid calling super()._immediately_usable_qty in a loop (this improves perfs on a tree view display) --- stock_available/models/product_product.py | 5 +++-- stock_available/models/product_template.py | 11 +++++++---- stock_available_immediately/models/product_product.py | 6 ++++-- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/stock_available/models/product_product.py b/stock_available/models/product_product.py index e9fe960e4..a22951f92 100644 --- a/stock_available/models/product_product.py +++ b/stock_available/models/product_product.py @@ -14,7 +14,7 @@ class ProductProduct(models.Model): """ _inherit = 'product.product' - @api.one + @api.multi @api.depends('virtual_available') def _immediately_usable_qty(self): """No-op implementation of the stock available to promise. @@ -23,7 +23,8 @@ class ProductProduct(models.Model): Must be overridden by another module that actually implement computations.""" - self.immediately_usable_qty = self.virtual_available + for prod in self: + prod.immediately_usable_qty = prod.virtual_available immediately_usable_qty = fields.Float( digits=dp.get_precision('Product Unit of Measure'), diff --git a/stock_available/models/product_template.py b/stock_available/models/product_template.py index cdff1f35e..a7f1fcc4b 100644 --- a/stock_available/models/product_template.py +++ b/stock_available/models/product_template.py @@ -9,12 +9,15 @@ from openerp.addons import decimal_precision as dp class ProductTemplate(models.Model): _inherit = 'product.template' - @api.one - @api.depends('virtual_available') + @api.multi + @api.depends('product_variant_ids.immediately_usable_qty') def _immediately_usable_qty(self): """Compute the quantity using all the variants""" - self.immediately_usable_qty = sum( - [v.immediately_usable_qty for v in self.product_variant_ids]) + for tmpl in self: + tmpl.immediately_usable_qty = sum( + v.immediately_usable_qty + for v in tmpl.product_variant_ids + ) immediately_usable_qty = fields.Float( digits=dp.get_precision('Product Unit of Measure'), diff --git a/stock_available_immediately/models/product_product.py b/stock_available_immediately/models/product_product.py index fdf196104..be202f9ad 100644 --- a/stock_available_immediately/models/product_product.py +++ b/stock_available_immediately/models/product_product.py @@ -8,8 +8,10 @@ from openerp import models, api class ProductProduct(models.Model): _inherit = 'product.product' - @api.one + @api.multi + @api.depends('virtual_available', 'incoming_qty') def _immediately_usable_qty(self): """Ignore the incoming goods in the quantity available to promise""" super(ProductProduct, self)._immediately_usable_qty() - self.immediately_usable_qty -= self.incoming_qty + for prod in self: + prod.immediately_usable_qty -= prod.incoming_qty From 749f69e6694e75848d80422457b49342f8a48a5e Mon Sep 17 00:00:00 2001 From: Lionel Sausin Date: Fri, 6 Nov 2015 17:19:14 +0100 Subject: [PATCH 2/2] [IMP] Decouple the quantity for templates and variants There are cases where we dot NOT want to simply sum the quantities of all the variants. For example when dealing with manufacturing capacities, we may have to chose between variants because we can't make ALL of them with the same components. So instead of a simple non-modular implementation, we'll let each module define his own implementation of how to compute the product template's quantity available for sale. Conflicts: stock_available/__openerp__.py stock_available_immediately/__openerp__.py --- stock_available/__openerp__.py | 2 +- stock_available/models/product_product.py | 7 ++-- stock_available/models/product_template.py | 15 +++++--- stock_available_immediately/__openerp__.py | 2 +- .../models/__init__.py | 1 + .../models/product_product.py | 4 ++- .../models/product_template.py | 35 +++++++++++++++++++ 7 files changed, 56 insertions(+), 10 deletions(-) create mode 100644 stock_available_immediately/models/product_template.py diff --git a/stock_available/__openerp__.py b/stock_available/__openerp__.py index 14dcb7397..f5748a838 100644 --- a/stock_available/__openerp__.py +++ b/stock_available/__openerp__.py @@ -4,7 +4,7 @@ { 'name': 'Stock available to promise', - 'version': '9.0.1.0.0', + 'version': '9.0.1.0.1', "author": "Numérigraphe, Sodexis, Odoo Community Association (OCA)", 'category': 'Warehouse', 'depends': ['stock'], diff --git a/stock_available/models/product_product.py b/stock_available/models/product_product.py index a22951f92..e76a67ee6 100644 --- a/stock_available/models/product_product.py +++ b/stock_available/models/product_product.py @@ -21,8 +21,11 @@ class ProductProduct(models.Model): By default, available to promise = forecasted quantity. - Must be overridden by another module that actually implement - computations.""" + **Each** sub-module **must** override this method in **both** + `product.product` **and** `product.template`, because we can't + decide in advance how to compute the template's quantity from the + variants. + """ for prod in self: prod.immediately_usable_qty = prod.virtual_available diff --git a/stock_available/models/product_template.py b/stock_available/models/product_template.py index a7f1fcc4b..96db9b15f 100644 --- a/stock_available/models/product_template.py +++ b/stock_available/models/product_template.py @@ -12,12 +12,17 @@ class ProductTemplate(models.Model): @api.multi @api.depends('product_variant_ids.immediately_usable_qty') def _immediately_usable_qty(self): - """Compute the quantity using all the variants""" + """No-op implementation of the stock available to promise. + + By default, available to promise = forecasted quantity. + + **Each** sub-module **must** override this method in **both** + `product.product` **and** `product.template`, because we can't + decide in advance how to compute the template's quantity from the + variants. + """ for tmpl in self: - tmpl.immediately_usable_qty = sum( - v.immediately_usable_qty - for v in tmpl.product_variant_ids - ) + tmpl.immediately_usable_qty = tmpl.virtual_available immediately_usable_qty = fields.Float( digits=dp.get_precision('Product Unit of Measure'), diff --git a/stock_available_immediately/__openerp__.py b/stock_available_immediately/__openerp__.py index 5894ba55c..f246cad5a 100644 --- a/stock_available_immediately/__openerp__.py +++ b/stock_available_immediately/__openerp__.py @@ -4,7 +4,7 @@ { "name": "Ignore planned receptions in quantity available to promise", - "version": "9.0.1.0.0", + "version": "9.0.1.1.0", "depends": ["stock_available"], "author": "Camptocamp,Sodexis,Odoo Community Association (OCA)", "license": "AGPL-3", diff --git a/stock_available_immediately/models/__init__.py b/stock_available_immediately/models/__init__.py index 73c7d8277..4fce57c9b 100644 --- a/stock_available_immediately/models/__init__.py +++ b/stock_available_immediately/models/__init__.py @@ -3,3 +3,4 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from . import product_product +from . import product_template diff --git a/stock_available_immediately/models/product_product.py b/stock_available_immediately/models/product_product.py index be202f9ad..12e973ed8 100644 --- a/stock_available_immediately/models/product_product.py +++ b/stock_available_immediately/models/product_product.py @@ -11,7 +11,9 @@ class ProductProduct(models.Model): @api.multi @api.depends('virtual_available', 'incoming_qty') def _immediately_usable_qty(self): - """Ignore the incoming goods in the quantity available to promise""" + """Ignore the incoming goods in the quantity available to promise + + This is the same implementation as for templates.""" super(ProductProduct, self)._immediately_usable_qty() for prod in self: prod.immediately_usable_qty -= prod.incoming_qty diff --git a/stock_available_immediately/models/product_template.py b/stock_available_immediately/models/product_template.py new file mode 100644 index 000000000..d8cd5ed34 --- /dev/null +++ b/stock_available_immediately/models/product_template.py @@ -0,0 +1,35 @@ +# -*- 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 import models, api + + +class ProductTemplate(models.Model): + _inherit = 'product.template' + + @api.multi + @api.depends('virtual_available', 'incoming_qty') + def _immediately_usable_qty(self): + """Ignore the incoming goods in the quantity available to promise + + This is the same implementation as for variants.""" + super(ProductTemplate, self)._immediately_usable_qty() + for tmpl in self: + tmpl.immediately_usable_qty -= tmpl.incoming_qty