diff --git a/stock_available/__manifest__.py b/stock_available/__manifest__.py index aa40dd404..a42fde78d 100644 --- a/stock_available/__manifest__.py +++ b/stock_available/__manifest__.py @@ -5,7 +5,7 @@ { 'name': 'Stock available to promise', - 'version': '10.0.1.0.0', + 'version': '10.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 fdce30316..196dff121 100644 --- a/stock_available/models/product_product.py +++ b/stock_available/models/product_product.py @@ -5,6 +5,16 @@ from odoo import models, fields, api from odoo.addons import decimal_precision as dp +import operator as py_operator + +OPERATORS = { + '<': py_operator.lt, + '>': py_operator.gt, + '<=': py_operator.le, + '>=': py_operator.ge, + '=': py_operator.eq, + '!=': py_operator.ne +} class ProductProduct(models.Model): @@ -37,6 +47,7 @@ class ProductProduct(models.Model): immediately_usable_qty = fields.Float( digits=dp.get_precision('Product Unit of Measure'), compute='_compute_available_quantities', + search="_search_immediately_usable_qty", string='Available to promise', help="Stock for this Product that can be safely proposed " "for sale to Customers.\n" @@ -48,3 +59,22 @@ class ProductProduct(models.Model): string='Potential', help="Quantity of this Product that could be produced using " "the materials already at hand.") + + @api.model + def _search_immediately_usable_qty(self, operator, value): + """ + Search function for the immediately_usable_qty field. + The search is quite similar to the Odoo search about quantity available + (addons/stock/models/product.py,253; _search_product_quantity function) + :param operator: str + :param value: str + :return: list of tuple (domain) + """ + products = self.search([]) + # Force prefetch + products.mapped("immediately_usable_qty") + product_ids = [] + for product in products: + if OPERATORS[operator](product.immediately_usable_qty, value): + product_ids.append(product.id) + return [('id', 'in', product_ids)] diff --git a/stock_available/models/product_template.py b/stock_available/models/product_template.py index 55be51f92..53be5c904 100644 --- a/stock_available/models/product_template.py +++ b/stock_available/models/product_template.py @@ -5,6 +5,16 @@ from odoo import models, fields, api from odoo.addons import decimal_precision as dp +import operator as py_operator + +OPERATORS = { + '<': py_operator.lt, + '>': py_operator.gt, + '<=': py_operator.le, + '>=': py_operator.ge, + '=': py_operator.eq, + '!=': py_operator.ne +} class ProductTemplate(models.Model): @@ -41,6 +51,7 @@ class ProductTemplate(models.Model): immediately_usable_qty = fields.Float( digits=dp.get_precision('Product Unit of Measure'), compute='_compute_available_quantities', + search="_search_immediately_usable_qty", string='Available to promise', help="Stock for this Product that can be safely proposed " "for sale to Customers.\n" @@ -54,3 +65,22 @@ class ProductTemplate(models.Model): "the materials already at hand. " "If the product has several variants, this will be the biggest " "quantity that can be made for a any single variant.") + + @api.model + def _search_immediately_usable_qty(self, operator, value): + """ + Search function for the immediately_usable_qty field. + The search is quite similar to the Odoo search about quantity available + (addons/stock/models/product.py,253; _search_product_quantity function) + :param operator: str + :param value: str + :return: list of tuple (domain) + """ + products = self.search([]) + # Force prefetch + products.mapped("immediately_usable_qty") + product_ids = [] + for product in products: + if OPERATORS[operator](product.immediately_usable_qty, value): + product_ids.append(product.id) + return [('id', 'in', product_ids)] diff --git a/stock_available/tests/test_stock_available.py b/stock_available/tests/test_stock_available.py index 23025500f..0d05e786c 100644 --- a/stock_available/tests/test_stock_available.py +++ b/stock_available/tests/test_stock_available.py @@ -76,10 +76,30 @@ class TestStockLogisticsWarehouse(TransactionCase): }) def compare_product_usable_qty(product, value): + """ + Compare the immediately_usable_qty with the given value + Check also the search function for the immediately_usable_qty field + :param product: product (template/product) recordset + :param value: int + :return: + """ # Refresh, because the function field is not recalculated between # transactions product.refresh() self.assertEqual(product.immediately_usable_qty, value) + # Now check search function + domain = [('immediately_usable_qty', '=', value)] + results = self.env[product._name].search(domain) + self.assertIn(product.id, results.ids) + domain = [('immediately_usable_qty', '!=', value)] + results = self.env[product._name].search(domain) + self.assertNotIn(product.id, results.ids) + domain = [('immediately_usable_qty', '>', value-1)] + results = self.env[product._name].search(domain) + self.assertIn(product.id, results.ids) + domain = [('immediately_usable_qty', '<', value+1)] + results = self.env[product._name].search(domain) + self.assertIn(product.id, results.ids) compare_product_usable_qty(productA, 0) compare_product_usable_qty(templateAB, 0)