From 0822e8c8677472ced75afe98ab5fe597ff30086b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A0n=20Todorovich?= Date: Mon, 13 Jun 2022 17:36:39 +0000 Subject: [PATCH] [IMP] mrp: use prefetch for recursive quantities computation This commit achieves two things: 1) Avoid calling super() on an empty recordset, in case all products are kits. Even on an empty recordset, some queries would be fired. This commit avoids them. 2) Use prefetch to read kit components quantity fields, to make use of the recorset optimizations that ends up saving sql queries. Otherwise, component quantities were computed on-demand one by one. closes odoo/odoo#94225 X-original-commit: ef4ae7f62d6b690b4745b4145ce25ff02b6b29f6 Signed-off-by: William Henrotin (whe) --- addons/mrp/models/product.py | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/addons/mrp/models/product.py b/addons/mrp/models/product.py index 48e6ac068b5..663e6da0aef 100644 --- a/addons/mrp/models/product.py +++ b/addons/mrp/models/product.py @@ -181,18 +181,33 @@ class ProductProduct(models.Model): """ bom_kits = self.env['mrp.bom']._bom_find(self, bom_type='phantom') kits = self.filtered(lambda p: bom_kits.get(p)) - res = super(ProductProduct, self - kits)._compute_quantities_dict(lot_id, owner_id, package_id, from_date=from_date, to_date=to_date) + regular_products = self - kits + res = ( + super(ProductProduct, regular_products)._compute_quantities_dict(lot_id, owner_id, package_id, from_date=from_date, to_date=to_date) + if regular_products + else {} + ) qties = self.env.context.get("mrp_compute_quantities", {}) qties.update(res) + # pre-compute bom lines and identify missing kit components to prefetch + bom_sub_lines_per_kit = {} + prefetch_component_ids = set() for product in bom_kits: - boms, bom_sub_lines = bom_kits[product].explode(product, 1) + __, bom_sub_lines = bom_kits[product].explode(product, 1) + bom_sub_lines_per_kit[product] = bom_sub_lines + for bom_line, __ in bom_sub_lines: + if bom_line.product_id.id not in qties: + prefetch_component_ids.add(bom_line.product_id.id) + # compute kit quantities + for product in bom_kits: + bom_sub_lines = bom_sub_lines_per_kit[product] ratios_virtual_available = [] ratios_qty_available = [] ratios_incoming_qty = [] ratios_outgoing_qty = [] ratios_free_qty = [] for bom_line, bom_line_data in bom_sub_lines: - component = bom_line.product_id.with_context(mrp_compute_quantities=qties) + component = bom_line.product_id.with_context(mrp_compute_quantities=qties).with_prefetch(prefetch_component_ids) if component.type != 'product' or float_is_zero(bom_line_data['qty'], precision_rounding=bom_line.product_uom_id.rounding): # As BoMs allow components with 0 qty, a.k.a. optionnal components, we simply skip those # to avoid a division by zero. The same logic is applied to non-storable products as those