[FIX] mrp: keep end time and duration consistent when moving work order
When drag and dropping a work order in the Work Orders Planning, the end time wasn't recomputed. This can make the end time inconsistent with the duration when the work order spans across a non-working time. Steps to reproduce: 1. Install Manufacturing 2. Go to Settings > Manufacturing > Operations and enable Work Orders 3. Go to Manufacturing > Master Data > Routings and edit routing 'Primary Assembly' to last 120:00 minutes 4. Go to Manufacturing > Operations > Manufacturing Orders and create one with values: - Product: Table Top - Plan From: today's date at 11:00:00 5. Save, mark as todo and plan the manufacturing order 6. Go to Manufacturing > Planning > Planning by Workcenter and trigger the day view 7. Move the work order to 8 am 8. The work order still lasts for 3 hours (according to its start and finish time) even though its expected duration is 2 hours Solution: Recompute `date_planned_finished` when we move a work order in the planning (`date_planned_start` and `date_planned_finished` are passed in values), and recompute `expected_duration` when we extend it (only one of them is passed depending on the way we extend the work order). (`duration_expected` is never passed in values when we manipulate a work order through the planning) Problem: `date_planned_finished` wasn't recomputed when moving the work order in the planning opw-2893622 closes odoo/odoo#100988 X-original-commit: 2515482d5a706c65a7d8e27028f43987f17e6e67 Related: odoo/enterprise#31720 Signed-off-by: William Henrotin (whe) <whe@odoo.com> Signed-off-by: Guillaume Merlin (megu) <megu@odoo.com>
This commit is contained in:
@@ -408,15 +408,6 @@ class MrpWorkorder(models.Model):
|
||||
for workorder in self:
|
||||
workorder.scrap_count = count_data.get(workorder.id, 0)
|
||||
|
||||
@api.onchange('date_planned_finished')
|
||||
def _onchange_date_planned_finished(self):
|
||||
if self.date_planned_start and self.date_planned_finished:
|
||||
interval = self.workcenter_id.resource_calendar_id.get_work_duration_data(
|
||||
self.date_planned_start, self.date_planned_finished,
|
||||
domain=[('time_type', 'in', ['leave', 'other'])]
|
||||
)
|
||||
self.duration_expected = interval['hours'] * 60
|
||||
|
||||
@api.onchange('operation_id')
|
||||
def _onchange_operation_id(self):
|
||||
if self.operation_id:
|
||||
@@ -426,10 +417,25 @@ 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:
|
||||
self.date_planned_finished = self.workcenter_id.resource_calendar_id.plan_hours(
|
||||
self.duration_expected / 60.0, self.date_planned_start,
|
||||
compute_leaves=True, domain=[('time_type', 'in', ['leave', 'other'])]
|
||||
)
|
||||
self.date_planned_finished = self._calculate_date_planned_finished()
|
||||
|
||||
def _calculate_date_planned_finished(self, date_planned_start=False):
|
||||
return self.workcenter_id.resource_calendar_id.plan_hours(
|
||||
self.duration_expected / 60.0, date_planned_start or self.date_planned_start,
|
||||
compute_leaves=True, domain=[('time_type', 'in', ['leave', 'other'])]
|
||||
)
|
||||
|
||||
@api.onchange('date_planned_finished')
|
||||
def _onchange_date_planned_finished(self):
|
||||
if self.date_planned_start and self.date_planned_finished:
|
||||
self.duration_expected = self._calculate_duration_expected()
|
||||
|
||||
def _calculate_duration_expected(self, date_planned_start=False, date_planned_finished=False):
|
||||
interval = self.workcenter_id.resource_calendar_id.get_work_duration_data(
|
||||
date_planned_start or self.date_planned_start, date_planned_finished or self.date_planned_finished,
|
||||
domain=[('time_type', 'in', ['leave', 'other'])]
|
||||
)
|
||||
return interval['hours'] * 60
|
||||
|
||||
def write(self, values):
|
||||
if 'production_id' in values and any(values['production_id'] != w.production_id.id for w in self):
|
||||
@@ -446,6 +452,16 @@ class MrpWorkorder(models.Model):
|
||||
end_date = fields.Datetime.to_datetime(values.get('date_planned_finished')) or workorder.date_planned_finished
|
||||
if start_date and end_date and start_date > end_date:
|
||||
raise UserError(_('The planned end date of the work order cannot be prior to the planned start date, please correct this to save the work order.'))
|
||||
if 'duration_expected' not in values and not self.env.context.get('bypass_duration_calculation'):
|
||||
if values.get('date_planned_start') and values.get('date_planned_finished'):
|
||||
computed_finished_time = self._calculate_date_planned_finished(start_date)
|
||||
values['date_planned_finished'] = computed_finished_time
|
||||
elif values.get('date_planned_start'):
|
||||
computed_duration = self._calculate_duration_expected(date_planned_start=start_date)
|
||||
values['duration_expected'] = computed_duration
|
||||
elif values.get('date_planned_finished'):
|
||||
computed_duration = self._calculate_duration_expected(date_planned_finished=end_date)
|
||||
values['duration_expected'] = computed_duration
|
||||
# Update MO dates if the start date of the first WO or the
|
||||
# finished date of the last WO is update.
|
||||
if workorder == workorder.production_id.workorder_ids[0] and 'date_planned_start' in values:
|
||||
@@ -613,7 +629,7 @@ class MrpWorkorder(models.Model):
|
||||
vals['date_planned_start'] = start_date
|
||||
if self.date_planned_finished and self.date_planned_finished < start_date:
|
||||
vals['date_planned_finished'] = start_date
|
||||
return self.write(vals)
|
||||
return self.with_context(bypass_duration_calculation=True).write(vals)
|
||||
|
||||
def button_finish(self):
|
||||
end_date = datetime.now()
|
||||
|
||||
Reference in New Issue
Block a user