From e4f5be29810a97b9fb893424bd6e4d21969a22e4 Mon Sep 17 00:00:00 2001 From: ilru-odoo Date: Mon, 18 Dec 2023 12:07:10 +0100 Subject: [PATCH] [FIX] mrp: preserve custom expected duration on completion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Issue Description: ================== The system currently resets the expected duration in the Work Order tab of a Manufacturing Order (MO) to the default Bill of Materials (BOM) value after 'Produce All' is used. This occurs despite any manual duration adjustments. This issue can be traced back to the dependencies of the compute method involved in this process. Specifically: 1. The `qty_production` field in `mrp_workorder.py` is a related field (see [here](https://github.com/odoo/odoo/blob/2e5da1130f4a7056f746a4cce6ba75bf699dbe62/addons/mrp/models/mrp_workorder.py#L44)). 2. When marking the MO as done, we write on this related field (refer to [this code](https://github.com/odoo/odoo/blob/780dded71cc725d75a0739e6c7bf4ceab5850581/addons/mrp/models/mrp_production.py#L1886)). 3. This action triggers a call to the compute method (defined [here](https://github.com/odoo/odoo/blob/2e5da1130f4a7056f746a4cce6ba75bf699dbe62/addons/mrp/models/mrp_workorder.py#L324)), leading to the unexpected change in the expected duration value. Steps to Reproduce: =================== 1. Create a Manufacturing Order (MO) with a product that has a BOM. 2. In the Work Order tab of the MO, input a custom expected duration different from the BOM's default duration. 3. Сomplete all product validation steps. 3. Click 'Produce All' on the MO. 4. Observe the reset of the expected duration to the default BOM value in the Work Order tab. Proposed Solution: ================== Implement a change to prevent the re-calculation of `duration_expected` in the Work Order tab once the work order's state is set to 'done' or 'cancel', ensuring that any custom duration set prior to executing 'Produce All' is maintained. opw-3608185 closes odoo/odoo#148269 X-original-commit: 00876107734c2d5bcf3f057ead55e345493bb6e2 Signed-off-by: Adrien Widart (awt) Signed-off-by: Ilya Rudy (ilru) --- addons/mrp/models/mrp_workorder.py | 3 ++- addons/mrp/tests/test_order.py | 28 ++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/addons/mrp/models/mrp_workorder.py b/addons/mrp/models/mrp_workorder.py index ab2d159f078..ec8756d543f 100644 --- a/addons/mrp/models/mrp_workorder.py +++ b/addons/mrp/models/mrp_workorder.py @@ -297,7 +297,8 @@ class MrpWorkorder(models.Model): @api.depends('operation_id', 'workcenter_id', 'qty_production') def _compute_duration_expected(self): for workorder in self: - workorder.duration_expected = workorder._get_duration_expected() + if workorder.state not in ['done', 'cancel']: + workorder.duration_expected = workorder._get_duration_expected() @api.depends('time_ids.duration', 'qty_produced') def _compute_duration(self): diff --git a/addons/mrp/tests/test_order.py b/addons/mrp/tests/test_order.py index d35a2cca166..f1256ae93b9 100644 --- a/addons/mrp/tests/test_order.py +++ b/addons/mrp/tests/test_order.py @@ -3798,3 +3798,31 @@ class TestMrpOrder(TestMrpCommon): mo_form.product_id = self.product_7_template.product_variant_ids[0] mo = mo_form.save() self.assertEqual(mo.move_raw_ids.product_id, c3) + + def test_mo_duration_expected(self): + """ + Test to verify that the 'duration_expected' on a work order in a manufacturing order + correctly remains as manually set after completion. This test involves creating a product + with a Bill of Materials (BOM) and an operation with an initial expected duration. + A manufacturing order is then created for this product, the expected duration of the + work order is manually changed, and the order is completed. The test checks that + the expected duration remains as manually set and does not revert to the original value. + """ + production_form = Form(self.env['mrp.production']) + production_form.product_id = self.product_5 + production_form.bom_id = self.bom_2 + production_form.product_qty = 1.0 + production = production_form.save() + production.action_confirm() + + init_duration_expected = production.workorder_ids.duration_expected + + production.workorder_ids.duration_expected = init_duration_expected + 5 + + production_form = Form(production) + production_form.qty_producing = 1.0 + production = production_form.save() + + production.button_mark_done() + + self.assertEqual(production.workorder_ids.duration_expected, init_duration_expected + 5)