From 6fcd31cc21ba35034e4f0835b499ff8db9749cff Mon Sep 17 00:00:00 2001 From: "lase@odoo.com" Date: Thu, 1 Feb 2024 09:00:16 +0100 Subject: [PATCH] [FIX] mrp_subcontracting : generates BOM for dynamic attributes Current Behavior: Traceback when printing the BOM overview. Expected behavior: Generates a PDF of the BOM overview even if the information displayed is entirely relevant. Steps to reproduce: Inventory > Configuration > Products > Attributes Create an attribute with Variants Creation Mode set to "Dynamically". Create a new product with this single attribute and multiple values. Create a BOM for this product with BOM Type set to "Subcontracting". Print the BOM overview. Cause of the issue: Creating such a product generates a 'product.template' that is not associated to any variant and hence does not correspond to any 'product.product'. As a result the function_get_bom_data made can not apply the method _select_seller properly in that case. Notes: - There is no error if a variant was manually created for that product. - If the Variants Creation Mode set to "Dynamically" a variant is still automatically created to be associated to the product tempalte so that the erro does not rise. Fix: As the _select_seller method is only defined for product.product and not for product.template, we can not not apply it here. Furhtermore, since the additional informations provided by the override of the method get_bom_data in the the BOM overview will not be relevant without the existence of a variant, we skip this part of the code when the argument of _select_seller is not valid. opw-3698050 closes odoo/odoo#156346 X-original-commit: b983026f004d4958d2a47a0dac9b1b54e24ab04c Signed-off-by: Arnold Moyaux (arm) Signed-off-by: Lancelot Semal (lase) --- .../report/mrp_report_bom_structure.py | 5 ++- .../tests/test_subcontracting.py | 35 +++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/addons/mrp_subcontracting/report/mrp_report_bom_structure.py b/addons/mrp_subcontracting/report/mrp_report_bom_structure.py index 6d3addf39d6..9aa4a550593 100644 --- a/addons/mrp_subcontracting/report/mrp_report_bom_structure.py +++ b/addons/mrp_subcontracting/report/mrp_report_bom_structure.py @@ -22,7 +22,10 @@ class ReportBomStructure(models.AbstractModel): def _get_bom_data(self, bom, warehouse, product=False, line_qty=False, bom_line=False, level=0, parent_bom=False, parent_product=False, index=0, product_info=False, ignore_stock=False): res = super()._get_bom_data(bom, warehouse, product, line_qty, bom_line, level, parent_bom, parent_product, index, product_info, ignore_stock) if bom.type == 'subcontract' and not self.env.context.get('minimized', False): - seller = res['product']._select_seller(quantity=res['quantity'], uom_id=bom.product_uom_id, params={'subcontractor_ids': bom.subcontractor_ids}) + if not res['product']: + seller = bom.product_tmpl_id.seller_ids.filtered(lambda s: s.partner_id in bom.subcontractor_ids)[:1] + else: + seller = res['product']._select_seller(quantity=res['quantity'], uom_id=bom.product_uom_id, params={'subcontractor_ids': bom.subcontractor_ids}) if seller: res['subcontracting'] = self._get_subcontracting_line(bom, seller, level + 1, res['quantity']) if not self.env.context.get('minimized', False): diff --git a/addons/mrp_subcontracting/tests/test_subcontracting.py b/addons/mrp_subcontracting/tests/test_subcontracting.py index 3c159c96f9a..878288b54d6 100644 --- a/addons/mrp_subcontracting/tests/test_subcontracting.py +++ b/addons/mrp_subcontracting/tests/test_subcontracting.py @@ -1572,3 +1572,38 @@ class TestSubcontractingSerialMassReceipt(TransactionCase): self.assertEqual(picking_receipt.state, 'done') self.assertEqual(self.env['stock.quant']._get_available_quantity(self.raw_material, self.env.ref('stock.stock_location_stock')), 0) self.assertEqual(self.env['stock.quant']._get_available_quantity(self.raw_material, self.subcontractor.property_stock_subcontractor, allow_negative=True), -quantity) + + def test_bom_subcontracting_product_dynamic_attribute(self): + """ + Test that the report BOM data is available for a product with an dynamic attribute + but without variant. + """ + dynamic_attribute = self.env['product.attribute'].create({ + 'name': 'flavour', + 'create_variant': 'dynamic', + }) + value_1 = self.env['product.attribute.value'].create({ + 'name': 'Vanilla', + 'attribute_id': dynamic_attribute.id, + }) + value_2 = self.env['product.attribute.value'].create({ + 'name': 'Chocolate', + 'attribute_id': dynamic_attribute.id, + }) + product_template = self.env['product.template'].create({ + 'name': 'Cake', + 'uom_id': self.env.ref('uom.product_uom_unit').id, + 'detailed_type': 'product', + }) + self.env['product.template.attribute.line'].create({ + 'product_tmpl_id': product_template.id, + 'attribute_id': dynamic_attribute.id, + 'value_ids': [Command.set([value_1.id, value_2.id])], + }) + bom = self.env['mrp.bom'].create({ + 'product_tmpl_id': product_template.id, + 'type': 'subcontract', + 'subcontractor_ids': [Command.set([self.subcontractor.id])], + }) + report_values = self.env['report.mrp.report_bom_structure']._get_report_data(bom_id=bom.id, searchVariant=False) + self.assertTrue(report_values)