From baea953d248471e8aef60e02c1216f77941f1951 Mon Sep 17 00:00:00 2001 From: "Touati Djamel (otd)" Date: Mon, 17 Oct 2022 15:07:59 +0000 Subject: [PATCH] [FIX] mrp: incorrect computation of the on-hand qty of a kit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Steps to reproduce the bug: - Create a storable product “P1” with BOM: - Type: Kit - Quantity: 3 - Components: - product “C1”, QTY: 5 - Update the quantity of “C1” to have 10 in stock - Go to “P1” product form Problem: - The on-hand quantity is 2 instead of 6 → 10 (available qty of c1) / (5 / 3) = 6 In the `_compute_quantities_dict` function, the `explode` function is called to have the qty of the component necessary: https://github.com/odoo/odoo/blob/ef4ae7f62d6b690b4745b4145ce25ff02b6b29f6/addons/mrp/models/product.py#L151 but it is the qty necessary for 3 kit according to what is indicated in the BOM, so we will have 5 qty needed of “C1” as a result: https://github.com/odoo/odoo/blob/49234be3418169c8f3c928493b86a1a67ab55914/addons/mrp/models/mrp_bom.py#L289 Then the quantity available in stock of the “C1” (10) is reduced by the quantity needed (5), so 2: https://github.com/odoo/odoo/blob/ef4ae7f62d6b690b4745b4145ce25ff02b6b29f6/addons/mrp/models/product.py#L188 But this result must be multiplied at the end by the quantity set in the BOM (3), to get the quantity per kit → (10/5)* 3 = 6 opw-3010175 closes odoo/odoo#103584 X-original-commit: 8ede8a758a92c4b61fe48d820464783e21ee7847 Signed-off-by: William Henrotin (whe) Signed-off-by: Djamel Touati (otd) --- addons/mrp/models/product.py | 10 +++++----- addons/mrp/tests/test_bom.py | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/addons/mrp/models/product.py b/addons/mrp/models/product.py index 18f93a6050f..b6a221815b9 100644 --- a/addons/mrp/models/product.py +++ b/addons/mrp/models/product.py @@ -240,11 +240,11 @@ class ProductProduct(models.Model): ratios_free_qty.append(component_res["free_qty"] / qty_per_kit) if bom_sub_lines and ratios_virtual_available: # Guard against all cnsumable bom: at least one ratio should be present. res[product.id] = { - 'virtual_available': min(ratios_virtual_available) // 1, - 'qty_available': min(ratios_qty_available) // 1, - 'incoming_qty': min(ratios_incoming_qty) // 1, - 'outgoing_qty': min(ratios_outgoing_qty) // 1, - 'free_qty': min(ratios_free_qty) // 1, + 'virtual_available': min(ratios_virtual_available) * bom_kits[product].product_qty // 1, + 'qty_available': min(ratios_qty_available) * bom_kits[product].product_qty // 1, + 'incoming_qty': min(ratios_incoming_qty) * bom_kits[product].product_qty // 1, + 'outgoing_qty': min(ratios_outgoing_qty) * bom_kits[product].product_qty // 1, + 'free_qty': min(ratios_free_qty) * bom_kits[product].product_qty // 1, } else: res[product.id] = { diff --git a/addons/mrp/tests/test_bom.py b/addons/mrp/tests/test_bom.py index 49c80b93109..317fe8c05f1 100644 --- a/addons/mrp/tests/test_bom.py +++ b/addons/mrp/tests/test_bom.py @@ -366,7 +366,7 @@ class TestBoM(TestMrpCommon): # ending the recurse call to not call the compute method and just left the Falsy value `0.0` # for the components available qty. kit_product_qty, _, _ = (self.product_7_3 + self.product_2 + self.product_3).mapped("qty_available") - self.assertEqual(kit_product_qty, 2) + self.assertEqual(kit_product_qty, 8) def test_14_bom_kit_qty_multi_uom(self): uom_dozens = self.env.ref('uom.product_uom_dozen')