[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:
@@ -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:
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user