[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) <whe@odoo.com>
This commit is contained in:
Ivàn Todorovich
2022-06-22 09:58:40 +02:00
parent 2e14772036
commit 0822e8c867
+18 -3
View File
@@ -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