From cf2d37ecd31e75124e0056e149e45605b682873b Mon Sep 17 00:00:00 2001 From: Djamel Touati Date: Tue, 24 Oct 2023 09:19:18 +0000 Subject: [PATCH] [FIX] mrp: allow use kit as component in MO without BoM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Steps to reproduce the bug: - Create a kit product - Create a storable product without BoM “P1” - Create a MO to produce one unit of “P1” - Add the kit product as component - confirm the MO Problem: The Manufacturing Order is cancelled. This is because the MO contains a kit product, and we need to generate moves based on its Bill of Materials. However, at the same time, we cancel and remove the move associated with the original product, which is no longer relevant. But We remove it before creating the moves generated from the phantom product. Consequently, since we cancel the move, the 'compute_state' of the MO is triggered, and as there is only one 'move_finished' status in 'cancel,' the status of the MO is set to 'cancel: https://github.com/odoo/odoo/blob/5c238bbb18c682ff2d25f740aad604feb7bb5bbc/addons/mrp/models/mrp_production.py#L462-L463 Opw-3548464 closes odoo/odoo#140016 X-original-commit: baa0924974fee0115a0bce117141a8096455b88d Signed-off-by: William Henrotin (whe) Signed-off-by: Djamel Touati (otd) --- addons/mrp/models/stock_move.py | 8 ++++---- addons/mrp/tests/test_order.py | 28 ++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/addons/mrp/models/stock_move.py b/addons/mrp/models/stock_move.py index ff5777651b1..ee11d7dd6e5 100644 --- a/addons/mrp/models/stock_move.py +++ b/addons/mrp/models/stock_move.py @@ -374,14 +374,14 @@ class StockMove(models.Model): # delete the move with original product which is not relevant anymore moves_ids_to_unlink.add(move.id) - move_to_unlink = self.env['stock.move'].browse(moves_ids_to_unlink).sudo() - move_to_unlink.quantity = 0 - move_to_unlink._action_cancel() - move_to_unlink.unlink() if phantom_moves_vals_list: phantom_moves = self.env['stock.move'].create(phantom_moves_vals_list) phantom_moves._adjust_procure_method() moves_ids_to_return |= phantom_moves.action_explode().ids + move_to_unlink = self.env['stock.move'].browse(moves_ids_to_unlink).sudo() + move_to_unlink.quantity = 0 + move_to_unlink._action_cancel() + move_to_unlink.unlink() return self.env['stock.move'].browse(moves_ids_to_return) def action_show_details(self): diff --git a/addons/mrp/tests/test_order.py b/addons/mrp/tests/test_order.py index a3a98b1b546..ead343bbe04 100644 --- a/addons/mrp/tests/test_order.py +++ b/addons/mrp/tests/test_order.py @@ -3616,3 +3616,31 @@ class TestMrpOrder(TestMrpCommon): warehouse.pbm_route_id.rule_ids.delay = 100 delays, _ = rule._get_lead_days(self.bom_1.product_id, bom=self.bom_1) self.assertEqual(delays['total_delay'], self.env.company.manufacturing_lead + self.bom_1.days_to_prepare_mo + self.bom_1.produce_delay + 100 * 2) + + def test_use_kit_as_component_in_production_without_bom(self): + """ + Test that a MO is not cancelled when a kit is added in a MO without a BoM. + """ + finished, component, kit = self.env['product.product'].create([{ + 'name': 'Product %s' % (i + 1), + 'type': 'product', + } for i in range(3)]) + self.env['mrp.bom'].create({ + 'product_id': kit.id, + 'product_tmpl_id': kit.product_tmpl_id.id, + 'type': 'phantom', + 'bom_line_ids': [(0, 0, { + 'product_id': component.id, + 'product_qty': 1, + })], + }) + + mo_form = Form(self.env['mrp.production']) + mo_form.product_id = finished + mo_form.product_qty = 1 + with mo_form.move_raw_ids.new() as line: + line.product_id = kit + mo = mo_form.save() + mo.action_confirm() + self.assertEqual(mo.state, 'confirmed') + self.assertEqual(mo.move_raw_ids.product_id, component)