From d05a79dcbc372dbbf304f947f90c1914757548aa Mon Sep 17 00:00:00 2001 From: "Touati Djamel (otd)" Date: Fri, 16 Jun 2023 17:29:23 +0000 Subject: [PATCH] [FIX] mrp:avoid traceback when confirming MO with OP blocked by other OP Steps to reproduce the bug: - Create a storable product "P1" - Add 2 variants: - Color: Red and Blue - Size: XS and M - Create a Bill of Materials (BoM): - Add any components - Create operation "OP1": - Apply only to: Red XS - Create operation "OP2": - Blocked by "OP1" - Apply to all variants - Create a MO with the variant "P1 (Blue and M)" - Try to confirm the MO Problem: a traceback is triggered, the issue has been fixed in: https://github.com/odoo/odoo/commit/0f21fde26fa4387d93722092ebf21d294fcfcd4f Solution: Link only if an operation is blocked by another operation with the same attribute values. OPW-3329263 closes odoo/odoo#131727 X-original-commit: 2fa8e2f64292483c0aa27141fe59eb4a6ff8effb Signed-off-by: Djamel Touati (otd) --- addons/mrp/tests/test_bom.py | 70 ++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/addons/mrp/tests/test_bom.py b/addons/mrp/tests/test_bom.py index 57802339d5d..a4b3375e957 100644 --- a/addons/mrp/tests/test_bom.py +++ b/addons/mrp/tests/test_bom.py @@ -1624,3 +1624,73 @@ class TestBoM(TestMrpCommon): {'product_id': self.product_1.id, 'product_uom_qty': 4}, {'product_id': self.product_3.id, 'product_uom_qty': 2}, ]) + + def test_operation_blocked_by_another_operation(self): + """ Test that an operation is not blocked by another operation if the variant is different + Product with 4 variants (red big, red medium, blue big, blue medium) + BoM: + - OP1 (apply on Red) + - OP2 (blocked by OP1) + Create a MO for Red big, OP1 is started, OP2 should be blocked + Create a Mo for Blue big, OP1 is not applied, OP2 should not be blocked + """ + ProductAttribute = self.env['product.attribute'] + ProductAttributeValue = self.env['product.attribute.value'] + + # Product Attribute + att_color = ProductAttribute.create({'name': 'Color', 'sequence': 1}) + att_size = ProductAttribute.create({'name': 'size', 'sequence': 2}) + + # Product Attribute color Value + att_color_red = ProductAttributeValue.create({'name': 'red', 'attribute_id': att_color.id, 'sequence': 1}) + att_color_blue = ProductAttributeValue.create({'name': 'blue', 'attribute_id': att_color.id, 'sequence': 2}) + # Product Attribute size Value + att_size_big = ProductAttributeValue.create({'name': 'big', 'attribute_id': att_size.id, 'sequence': 1}) + att_size_medium = ProductAttributeValue.create({'name': 'medium', 'attribute_id': att_size.id, 'sequence': 2}) + + # Create create a product with 4 variants + product_template = self.env['product.template'].create({ + 'name': 'Sofa', + 'attribute_line_ids': [ + (0, 0, { + 'attribute_id': att_color.id, + 'value_ids': [(6, 0, [att_color_red.id, att_color_blue.id])] + }), + (0, 0, { + 'attribute_id': att_size.id, + 'value_ids': [(6, 0, [att_size_big.id, att_size_medium.id])] + }) + ] + }) + bom = self.env['mrp.bom'].create({ + 'product_tmpl_id': product_template.id, + 'product_uom_id': self.uom_unit.id, + 'product_qty': 1.0, + 'allow_operation_dependencies': True, + 'operation_ids': [(0, 0, {'name': 'op1', 'workcenter_id': self.workcenter_1.id, 'time_cycle': 1.0, 'bom_product_template_attribute_value_ids': [(4, att_color_blue.pav_attribute_line_ids.product_template_value_ids[0].id)]}), + (0, 0, {'name': 'op2', 'workcenter_id': self.workcenter_1.id, 'time_cycle': 1.0})], + }) + # Make 1st workorder depend on 2nd + bom.operation_ids[1].blocked_by_operation_ids = [Command.link(bom.operation_ids[0].id)] + + # Make MO for red big + mo_form = Form(self.env['mrp.production']) + mo_form.product_id = product_template.product_variant_ids[0] + mo_form.bom_id = bom + mo_form.product_qty = 1.0 + mo = mo_form.save() + mo.action_confirm() + self.assertEqual(mo.state, 'confirmed') + # Make MO for blue big + mo_form = Form(self.env['mrp.production']) + mo_form.product_id = product_template.product_variant_ids[2] + mo_form.bom_id = bom + mo_form.product_qty = 1.0 + mo = mo_form.save() + mo.action_confirm() + self.assertEqual(mo.state, 'confirmed') + mo.qty_producing = 1.0 + mo.action_assign() + mo.button_plan() + mo.button_mark_done() + self.assertEqual(mo.state, 'done')