[FIX] mrp: prevent traceback on WO scheduling during MO planning

Use Case 1
Steps to reproduce :
    Create a MO without BOM, schedule a WO (OP1), save and confirm.
    Add a second WO (OP2) scheduled before OP1 and save

Expected behavior:
    Workorders are correctly planned and MO is ready to be processed
Actual Behavior
    TypeError due to the default `duration_expected` value of 0.0 being interpreted as False at
    https://github.com/odoo/odoo/blob/3e49e533892f94eeb094a436fa34cbac3ed7ad6d/addons/mrp/models/mrp_workorder.py#L419
    which results in `date_planned_finished = False`.
    This causes a traceback at https://github.com/odoo/odoo/blob/3e49e533892f94eeb094a436fa34cbac3ed7ad6d/addons/mrp/models/mrp_workorder.py#L502
    due to trying to compare a date and a boolean.

-----------
Use Case 2
Steps to reproduce :
    Create a new MO without BoM and with 2 workorders
    Set a `date_planned_start` value for the 2nd workorder
    Confirm MO + Plan MO
    Set a 'date_planned_start' value for the 1st workorder
    Save MO

Expected behavior:
    Workorders are correctly planned and MO is ready to be processed

Actual behavior:
    TyperError due to 'leave_id.date_from' set to False at https://github.com/odoo/odoo/blob/3e49e533892f94eeb094a436fa34cbac3ed7ad6d/addons/mrp/models/mrp_production.py#L1324
    It was caused by a bad condition at https://github.com/odoo/odoo/blob/3e49e533892f94eeb094a436fa34cbac3ed7ad6d/addons/mrp/models/mrp_workorder.py#L506
    leading to an exit of the method at https://github.com/odoo/odoo/blob/3e49e533892f94eeb094a436fa34cbac3ed7ad6d/addons/mrp/models/mrp_workorder.py#L510
    before creation of the aforementioned 'leave_id' at https://github.com/odoo/odoo/blob/3e49e533892f94eeb094a436fa34cbac3ed7ad6d/addons/mrp/models/mrp_workorder.py#L537-L547

closes odoo/odoo#105878

Task: 2985735
X-original-commit: 45ae7a459672bf130296b541a015db461845a051
Signed-off-by: Arnold Moyaux (arm) <arm@odoo.com>
This commit is contained in:
Mathias Mathy (MAMA)
2022-11-16 16:24:53 +01:00
parent b345e1963b
commit 15b22aac2a
2 changed files with 78 additions and 2 deletions
+2 -2
View File
@@ -416,7 +416,7 @@ class MrpWorkorder(models.Model):
@api.onchange('date_planned_start', 'duration_expected', 'workcenter_id')
def _onchange_date_planned_start(self):
if self.date_planned_start and self.duration_expected and self.workcenter_id:
if self.date_planned_start and self.workcenter_id:
self.date_planned_finished = self._calculate_date_planned_finished()
def _calculate_date_planned_finished(self, date_planned_start=False):
@@ -503,7 +503,7 @@ class MrpWorkorder(models.Model):
# Plan only suitable workorders
if self.state not in ['pending', 'waiting', 'ready']:
return
if self.date_planned_start:
if self.leave_id:
if replan:
self.leave_id.unlink()
else:
+76
View File
@@ -3014,6 +3014,82 @@ class TestMrpOrder(TestMrpCommon):
self.assertFalse(wo_02.show_json_popover)
self.assertEqual(wo_01.date_planned_finished, wo_02.date_planned_start)
@freeze_time('2022-10-05 12:00')
def test_replan_mo_without_bom(self):
"""
Create 2 MOs without BoM
just set the product and a component
For first MO :
Add 2 WO (with different WC)
Don't schedule first WO
Schedule second WO
Confirm => MO is Confirmed and Planned
Schedule first WO before second WO
Confirm => MO should Replan without Error
For second MO :
Add 1 Scheduled WO
Confirm => MO is Confirmed and Planned
Add a second WO scheduled before the other one (with different WC)
Confirm => MO should Replan without Error
"""
# Required for `workorder_ids` to be visible in the view
self.env.user.groups_id += self.env.ref('mrp.group_mrp_routings')
mos = self.env['mrp.production']
for _ in range(2):
mo_form = Form(self.env['mrp.production'])
mo_form.product_id = self.product_8
with mo_form.move_raw_ids.new() as component:
component.product_id = self.product_6
mos += mo_form.save()
mo_01, mo_02 = mos
#First MO
with Form(mo_01) as mo_01_form:
with mo_01_form.workorder_ids.new() as workorder:
workorder.name = "OP1"
workorder.workcenter_id = self.workcenter_2
with mo_01_form.workorder_ids.new() as workorder:
workorder.name = "OP2"
workorder.workcenter_id = self.workcenter_3
workorder.date_planned_start = datetime(2022, 10, 23, 12)
mo_01 = mo_01_form.save()
mo_01.action_confirm()
op_1, op_2 = mo_01.workorder_ids
self.assertEqual(op_2.date_planned_start, datetime(2022, 10, 23, 12))
with Form(mo_01) as mo_01_form:
with mo_01_form.workorder_ids.edit(0) as workorder:
workorder.date_planned_start = datetime(2022, 10, 18, 12)
mo_01 = mo_01_form.save()
self.assertEqual(op_1.date_planned_start, datetime(2022, 10, 18, 12))
self.assertEqual(op_1.date_planned_finished, op_2.date_planned_start)
#Second MO
with Form(mo_02) as mo_02_form:
with mo_02_form.workorder_ids.new() as workorder:
workorder.name = "OP1"
workorder.workcenter_id = self.workcenter_2
workorder.date_planned_start = datetime(2022, 10, 20, 12)
mo_02 = mo_02_form.save()
mo_02.action_confirm()
with Form(mo_02) as mo_02_form:
with mo_02_form.workorder_ids.new() as workorder:
workorder.name = "OP2"
workorder.workcenter_id = self.workcenter_3
workorder.date_planned_start = datetime(2022, 10, 18, 12)
mo_02 = mo_02_form.save()
op_1, op_2 = mo_02.workorder_ids
self.assertEqual(op_1.date_planned_start, datetime(2022, 10, 20, 12))
self.assertTrue(op_2.show_json_popover)
def test_compute_product_id(self):
"""
Tests the creation of a production order automatically sets the product when the bom is provided,