From e59f37999ace7dc739476b7fa7d6180d4a97648c Mon Sep 17 00:00:00 2001 From: Djamel Touati Date: Wed, 27 Mar 2024 15:55:18 +0100 Subject: [PATCH] [FIX] mrp: split the MO into the correct quantity Steps to Reproduce the Bug: - Create a BoM: - Product: P1, Quantity: 1 unit - Component: - C1, Quantity: 1 unit - Create a MO to produce 10 units of P1: - This requires 10 units of C1 - In draft state, split the quantity into 10 **Problem:** The created MOs have component quantities of 0.1 instead of 1. When the MO is split, we update the product quantity of the original MO to 1, which triggers the `_compute_move_raw_ids` because it depends on the product_qty of the MO. Therefore, the move will be updated to 1. https://github.com/odoo/odoo/blob/17.0/addons/mrp/models/mrp_production.py#L1793 Subsequently, the factor is calculated based on the `move_qty` and the `qty_initial` of the MO. https://github.com/odoo/odoo/blob/17.0/addons/mrp/models/mrp_production.py#L1828 Factor = 1 / 10 = 0.1 Afterwards, this quantity is set on the original move and the backorder moves: https://github.com/odoo/odoo/blob/17.0/addons/mrp/models/mrp_production.py#L1830 https://github.com/odoo/odoo/blob/17.0/addons/mrp/models/mrp_production.py#L1835 opw-3825708 closes odoo/odoo#159713 X-original-commit: 10554f3a3e28374c460a475a4908015aeb8a81cc Signed-off-by: William Henrotin (whe) Signed-off-by: Djamel Touati (otd) --- addons/mrp/models/mrp_production.py | 4 ++-- addons/mrp/tests/test_backorder.py | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/addons/mrp/models/mrp_production.py b/addons/mrp/models/mrp_production.py index e736336b897..a6faf782f70 100644 --- a/addons/mrp/models/mrp_production.py +++ b/addons/mrp/models/mrp_production.py @@ -746,7 +746,7 @@ class MrpProduction(models.Model): @api.depends('company_id', 'bom_id', 'product_id', 'product_qty', 'product_uom_id', 'location_src_id') def _compute_move_raw_ids(self): for production in self: - if production.state != 'draft': + if production.state != 'draft' or self.env.context.get('skip_compute_move_raw_ids'): continue list_move_raw = [Command.link(move.id) for move in production.move_raw_ids.filtered(lambda m: not m.bom_line_id)] if not production.bom_id and not production._origin.product_id: @@ -1790,7 +1790,7 @@ class MrpProduction(models.Model): (production.move_raw_ids | production.move_finished_ids).origin = production._get_origin() backorder_vals = production.copy_data(default=production._get_backorder_mo_vals())[0] backorder_qtys = amounts[production][1:] - production.product_qty = amounts[production][0] + production.with_context(skip_compute_move_raw_ids=True).product_qty = amounts[production][0] next_seq = max(production.procurement_group_id.mrp_production_ids.mapped("backorder_sequence"), default=1) diff --git a/addons/mrp/tests/test_backorder.py b/addons/mrp/tests/test_backorder.py index 890a074f827..8bfc295716c 100644 --- a/addons/mrp/tests/test_backorder.py +++ b/addons/mrp/tests/test_backorder.py @@ -607,6 +607,26 @@ class TestMrpProductionBackorder(TestMrpCommon): # The backorder is re reserved depending on the picking type self.assertEqual(backorder.reserve_visible, False) + def test_split_mo(self): + """ + Test that an MO is split correctly. + BoM: 1 finished product = 0.5 comp1 + 1 comp2 + """ + mo = self.env['mrp.production'].create({ + 'product_qty': 10, + 'bom_id': self.bom_1.id, + }) + self.assertEqual(mo.move_raw_ids.mapped('product_uom_qty'), [5, 10]) + self.assertEqual(mo.state, 'draft') + action = mo.action_split() + wizard = Form(self.env[action['res_model']].with_context(action['context'])) + wizard.counter = 10 + action = wizard.save().action_split() + # check that the MO is split in 10 and the components are split accordingly + self.assertEqual(len(mo.procurement_group_id.mrp_production_ids), 10) + self.assertEqual(mo.product_qty, 1) + self.assertEqual(mo.move_raw_ids.mapped('product_uom_qty'), [0.5, 1]) + class TestMrpWorkorderBackorder(TransactionCase): @classmethod