diff --git a/addons/mrp/data/mrp_demo.xml b/addons/mrp/data/mrp_demo.xml index 374a68d90c0..d4ffe15becd 100644 --- a/addons/mrp/data/mrp_demo.xml +++ b/addons/mrp/data/mrp_demo.xml @@ -283,7 +283,7 @@ 1 - + diff --git a/addons/mrp/models/mrp_production.py b/addons/mrp/models/mrp_production.py index 71144857538..3c9eb1cd267 100644 --- a/addons/mrp/models/mrp_production.py +++ b/addons/mrp/models/mrp_production.py @@ -24,15 +24,25 @@ class MrpProduction(models.Model): """ Manufacturing Orders """ _name = 'mrp.production' _description = 'Production Order' - _date_name = 'date_planned_start' + _date_name = 'date_start' _inherit = ['mail.thread', 'mail.activity.mixin'] - _order = 'priority desc, date_planned_start asc,id' + _order = 'priority desc, date_start asc,id' @api.model - def _get_default_date_planned_start(self): + def _get_default_date_start(self): + if self.env.context.get('default_date_deadline'): + date_finished = fields.Datetime.to_datetime(self.env.context.get('default_date_deadline')) + date_start = date_finished - relativedelta(hours=1) + return date_start + return fields.Datetime.now() + + @api.model + def _get_default_date_finished(self): if self.env.context.get('default_date_deadline'): return fields.Datetime.to_datetime(self.env.context.get('default_date_deadline')) - return fields.Datetime.now() + date_start = fields.Datetime.now() + date_finished = date_start + relativedelta(hours=1) + return date_finished @api.model def _get_default_is_locked(self): @@ -98,23 +108,19 @@ class MrpProduction(models.Model): readonly=False, required=True, precompute=True, domain="[('usage','=','internal'), '|', ('company_id', '=', False), ('company_id', '=', company_id)]", help="Location where the system will stock the finished products.") - date_planned_start = fields.Datetime( - 'Scheduled Date', copy=False, default=_get_default_date_planned_start, - help="Date at which you plan to start the production.", - index=True, required=True) - date_planned_finished = fields.Datetime( - 'Scheduled End Date', - compute='_compute_date_planned_finished', store=True, - help="Date at which you plan to finish the production.", - copy=False) date_deadline = fields.Datetime( 'Deadline', copy=False, store=True, readonly=True, compute='_compute_date_deadline', help="Informative date allowing to define when the manufacturing order should be processed at the latest to fulfill delivery on time.") - date_start = fields.Datetime('Start Date', copy=False, readonly=True) - date_finished = fields.Datetime('End Date', copy=False, readonly=True) - - production_duration_expected = fields.Float("Expected Duration", help="Total expected duration (in minutes)", compute='_compute_production_duration_expected') - production_real_duration = fields.Float("Real Duration", help="Total real duration (in minutes)", compute='_compute_production_real_duration') + date_start = fields.Datetime( + 'Start', copy=False, default=_get_default_date_start, + help="Date you plan to start production or date you actually started production.", + index=True, required=True) + date_finished = fields.Datetime( + 'End', copy=False, default=_get_default_date_finished, + compute='_compute_date_finished', store=True, + help="Date you expect to finish production or actual date you finished production.") + duration_expected = fields.Float("Expected Duration", help="Total expected duration (in minutes)", compute='_compute_duration_expected') + duration = fields.Float("Real Duration", help="Total real duration (in minutes)", compute='_compute_duration') bom_id = fields.Many2one( 'mrp.bom', 'Bill of Material', readonly=False, @@ -305,7 +311,7 @@ class MrpProduction(models.Model): production.location_src_id = production.picking_type_id.default_location_src_id.id or fallback_loc.id production.location_dest_id = production.picking_type_id.default_location_dest_id.id or fallback_loc.id - @api.depends('state', 'reservation_state', 'date_planned_start', 'move_raw_ids', 'move_raw_ids.forecast_availability', 'move_raw_ids.forecast_expected_date') + @api.depends('state', 'reservation_state', 'date_start', 'move_raw_ids', 'move_raw_ids.forecast_availability', 'move_raw_ids.forecast_expected_date') def _compute_components_availability(self): productions = self.filtered(lambda mo: mo.state not in ('cancel', 'done', 'draft')) productions.components_availability_state = 'available' @@ -326,8 +332,8 @@ class MrpProduction(models.Model): forecast_date = max(production.move_raw_ids.filtered('forecast_expected_date').mapped('forecast_expected_date'), default=False) if forecast_date: production.components_availability = _('Exp %s', format_date(self.env, forecast_date)) - if production.date_planned_start: - production.components_availability_state = 'late' if forecast_date > production.date_planned_start else 'expected' + if production.date_start: + production.components_availability_state = 'late' if forecast_date > production.date_start else 'expected' @api.depends('bom_id') def _compute_product_id(self): @@ -378,20 +384,20 @@ class MrpProduction(models.Model): production.date_deadline = min(production.move_finished_ids.filtered('date_deadline').mapped('date_deadline'), default=production.date_deadline or False) @api.depends('workorder_ids.duration_expected') - def _compute_production_duration_expected(self): + def _compute_duration_expected(self): for production in self: - production.production_duration_expected = sum(production.workorder_ids.mapped('duration_expected')) + production.duration_expected = sum(production.workorder_ids.mapped('duration_expected')) @api.depends('workorder_ids.duration') - def _compute_production_real_duration(self): + def _compute_duration(self): for production in self: - production.production_real_duration = sum(production.workorder_ids.mapped('duration')) + production.duration = sum(production.workorder_ids.mapped('duration')) - @api.depends("workorder_ids.date_planned_start", "workorder_ids.date_planned_finished") + @api.depends("workorder_ids.date_start", "workorder_ids.date_finished") def _compute_is_planned(self): for production in self: if production.workorder_ids: - production.is_planned = any(wo.date_planned_start and wo.date_planned_finished for wo in production.workorder_ids) + production.is_planned = any(wo.date_start and wo.date_finished for wo in production.workorder_ids) else: production.is_planned = False @@ -661,13 +667,13 @@ class MrpProduction(models.Model): ('move_orig_ids', 'in', lines.ids)], limit=1): mo.show_allocation = True - @api.depends('product_uom_qty', 'date_planned_start') + @api.depends('product_uom_qty', 'date_start') def _compute_forecasted_issue(self): for order in self: warehouse = order.location_dest_id.warehouse_id order.forecasted_issue = False if order.product_id: - virtual_available = order.product_id.with_context(warehouse=warehouse.id, to_date=order.date_planned_start).virtual_available + virtual_available = order.product_id.with_context(warehouse=warehouse.id, to_date=order.date_start).virtual_available if order.state == 'draft': virtual_available += order.product_uom_qty if virtual_available < 0: @@ -678,18 +684,18 @@ class MrpProduction(models.Model): late_stock_moves = self.env['stock.move'].search([('delay_alert_date', operator, value)]) return ['|', ('move_raw_ids', 'in', late_stock_moves.ids), ('move_finished_ids', 'in', late_stock_moves.ids)] - @api.depends('company_id', 'date_planned_start', 'is_planned', 'product_id') - def _compute_date_planned_finished(self): + @api.depends('company_id', 'date_start', 'is_planned', 'product_id') + def _compute_date_finished(self): for production in self: - if not production.date_planned_start or production.is_planned: + if not production.date_start or production.is_planned: continue days_delay = production.bom_id.produce_delay - date_planned_finished = production.date_planned_start + relativedelta(days=days_delay) - if date_planned_finished == production.date_planned_start: - date_planned_finished = date_planned_finished + relativedelta(hours=1) - production.date_planned_finished = date_planned_finished + date_finished = production.date_start + relativedelta(days=days_delay) + if date_finished == production.date_start: + date_finished = date_finished + relativedelta(hours=1) + production.date_finished = date_finished - @api.depends('company_id', 'bom_id', 'product_id', 'product_qty', 'product_uom_id', 'location_src_id', 'date_planned_start') + @api.depends('company_id', 'bom_id', 'product_id', 'product_qty', 'product_uom_id', 'location_src_id', 'date_start') def _compute_move_raw_ids(self): for production in self: if production.state != 'draft': @@ -714,13 +720,13 @@ class MrpProduction(models.Model): else: production.move_raw_ids = [Command.delete(move.id) for move in production.move_raw_ids.filtered(lambda m: m.bom_line_id)] - @api.depends('product_id', 'bom_id', 'product_qty', 'product_uom_id', 'location_dest_id', 'date_planned_finished') + @api.depends('product_id', 'bom_id', 'product_qty', 'product_uom_id', 'location_dest_id', 'date_finished') def _compute_move_finished_ids(self): for production in self: if production.state != 'draft': updated_values = {} - if production.date_planned_finished: - updated_values['date'] = production.date_planned_finished + if production.date_finished: + updated_values['date'] = production.date_finished if production.date_deadline: updated_values['date_deadline'] = production.date_deadline if 'date' in updated_values or 'date_deadline' in updated_values: @@ -800,15 +806,15 @@ class MrpProduction(models.Model): res = super(MrpProduction, self).write(vals) for production in self: - if 'date_planned_start' in vals and not self.env.context.get('force_date', False): + if 'date_start' in vals and not self.env.context.get('force_date', False): if production.state in ['done', 'cancel']: raise UserError(_('You cannot move a manufacturing order once it is cancelled or done.')) if production.is_planned: production.button_unplan() - if vals.get('date_planned_start'): - production.move_raw_ids.write({'date': production.date_planned_start, 'date_deadline': production.date_planned_start}) - if vals.get('date_planned_finished'): - production.move_finished_ids.write({'date': production.date_planned_finished}) + if vals.get('date_start'): + production.move_raw_ids.write({'date': production.date_start, 'date_deadline': production.date_start}) + if vals.get('date_finished'): + production.move_finished_ids.write({'date': production.date_finished}) if any(field in ['move_raw_ids', 'move_finished_ids', 'workorder_ids'] for field in vals) and production.state != 'draft': production._autoconfirm_production() if production in production_to_replan: @@ -820,10 +826,10 @@ class MrpProduction(models.Model): finished_move_lines.write({'lot_id': vals.get('lot_producing_id')}) if 'qty_producing' in vals: finished_move_lines.write({'qty_done': vals.get('qty_producing')}) - if self._has_workorders() and not production.workorder_ids.operation_id and vals.get('date_planned_start') and not vals.get('date_planned_finished'): - new_date_planned_start = fields.Datetime.to_datetime(vals.get('date_planned_start')) - if not production.date_planned_finished or new_date_planned_start >= production.date_planned_finished: - production.date_planned_finished = new_date_planned_start + datetime.timedelta(hours=1) + if self._has_workorders() and not production.workorder_ids.operation_id and vals.get('date_start') and not vals.get('date_finished'): + new_date_start = fields.Datetime.to_datetime(vals.get('date_start')) + if not production.date_finished or new_date_start >= production.date_finished: + production.date_finished = new_date_start + datetime.timedelta(hours=1) return res @api.model_create_multi @@ -934,7 +940,7 @@ class MrpProduction(models.Model): 'operation_id': operation_id, 'byproduct_id': byproduct_id, 'name': _('New'), - 'date': self._get_date_planned_finished(), + 'date': self.date_finished, 'date_deadline': self.date_deadline, 'picking_type_id': self.picking_type_id.id, 'location_id': self.product_id.with_company(self.company_id).property_stock_production.id, @@ -949,12 +955,6 @@ class MrpProduction(models.Model): 'cost_share': cost_share, } - def _get_date_planned_finished(self): - date_planned_finished = self.date_planned_start + relativedelta(days=self.bom_id.produce_delay) - if date_planned_finished == self.date_planned_start: - date_planned_finished = date_planned_finished + relativedelta(hours=1) - return date_planned_finished - def _get_moves_finished_values(self): moves = [] for production in self: @@ -1021,8 +1021,8 @@ class MrpProduction(models.Model): data = { 'sequence': bom_line.sequence if bom_line else 10, 'name': _('New'), - 'date': self.date_planned_start, - 'date_deadline': self.date_planned_start, + 'date': self.date_start, + 'date_deadline': self.date_start, 'bom_line_id': bom_line.id if bom_line else False, 'picking_type_id': self.picking_type_id.id, 'product_id': product_id.id, @@ -1307,8 +1307,8 @@ class MrpProduction(models.Model): workorders = self.workorder_ids.filtered(lambda w: w.state not in ['done', 'cancel']) self.with_context(force_date=True).write({ - 'date_planned_start': min([workorder.leave_id.date_from for workorder in workorders]), - 'date_planned_finished': max([workorder.leave_id.date_to for workorder in workorders]) + 'date_start': min([workorder.leave_id.date_from for workorder in workorders]), + 'date_finished': max([workorder.leave_id.date_to for workorder in workorders]) }) def button_unplan(self): @@ -1319,8 +1319,8 @@ class MrpProduction(models.Model): self.workorder_ids.leave_id.unlink() self.workorder_ids.write({ - 'date_planned_start': False, - 'date_planned_finished': False, + 'date_start': False, + 'date_finished': False, }) def _get_consumption_issues(self): @@ -2050,7 +2050,7 @@ class MrpProduction(models.Model): self.with_context(skip_activity=True)._action_cancel() # set the new deadline of origin moves (stock to pre prod) - production.move_raw_ids.move_orig_ids.with_context(date_deadline_propagate_ids=set(production.move_raw_ids.ids)).write({'date_deadline': production.date_planned_start}) + production.move_raw_ids.move_orig_ids.with_context(date_deadline_propagate_ids=set(production.move_raw_ids.ids)).write({'date_deadline': production.date_start}) for p in self: p._message_log(body=_('This production has been merge in %s', production.display_name)) diff --git a/addons/mrp/models/mrp_workcenter.py b/addons/mrp/models/mrp_workcenter.py index 74d387c79e6..9b9b3e8c649 100644 --- a/addons/mrp/models/mrp_workcenter.py +++ b/addons/mrp/models/mrp_workcenter.py @@ -82,14 +82,14 @@ class MrpWorkcenter(models.Model): if workcenter in workcenter.alternative_workcenter_ids: raise ValidationError(_("Workcenter %s cannot be an alternative of itself.", workcenter.name)) - @api.depends('order_ids.duration_expected', 'order_ids.workcenter_id', 'order_ids.state', 'order_ids.date_planned_start') + @api.depends('order_ids.duration_expected', 'order_ids.workcenter_id', 'order_ids.state', 'order_ids.date_start') def _compute_workorder_count(self): MrpWorkorder = self.env['mrp.workorder'] result = {wid: {} for wid in self._ids} result_duration_expected = {wid: 0 for wid in self._ids} # Count Late Workorder data = MrpWorkorder._read_group( - [('workcenter_id', 'in', self.ids), ('state', 'in', ('pending', 'waiting', 'ready')), ('date_planned_start', '<', datetime.now().strftime('%Y-%m-%d'))], + [('workcenter_id', 'in', self.ids), ('state', 'in', ('pending', 'waiting', 'ready')), ('date_start', '<', datetime.now().strftime('%Y-%m-%d'))], ['workcenter_id'], ['workcenter_id']) count_data = dict((item['workcenter_id'][0], item['workcenter_id_count']) for item in data) # Count All, Pending, Ready, Progress Workorder diff --git a/addons/mrp/models/mrp_workorder.py b/addons/mrp/models/mrp_workorder.py index 1edd079c509..a83ced4865d 100644 --- a/addons/mrp/models/mrp_workorder.py +++ b/addons/mrp/models/mrp_workorder.py @@ -68,25 +68,18 @@ class MrpWorkorder(models.Model): 'resource.calendar.leaves', help='Slot into workcenter calendar once planned', check_company=True, copy=False) - date_planned_start = fields.Datetime( - 'Scheduled Start Date', - compute='_compute_dates_planned', - inverse='_set_dates_planned', - states={'done': [('readonly', True)], 'cancel': [('readonly', True)]}, - store=True, copy=False) - date_planned_finished = fields.Datetime( - 'Scheduled End Date', - compute='_compute_dates_planned', - inverse='_set_dates_planned', - states={'done': [('readonly', True)], 'cancel': [('readonly', True)]}, - store=True, copy=False) date_start = fields.Datetime( - 'Start Date', copy=False, - states={'done': [('readonly', True)], 'cancel': [('readonly', True)]}) + 'Start', + compute='_compute_dates', + inverse='_set_dates', + states={'done': [('readonly', True)], 'cancel': [('readonly', True)]}, + store=True, copy=False) date_finished = fields.Datetime( - 'End Date', copy=False, - states={'done': [('readonly', True)], 'cancel': [('readonly', True)]}) - + 'End', + compute='_compute_dates', + inverse='_set_dates', + states={'done': [('readonly', True)], 'cancel': [('readonly', True)]}, + store=True, copy=False) duration_expected = fields.Float( 'Expected Duration', digits=(16, 2), compute='_compute_duration_expected', states={'done': [('readonly', True)], 'cancel': [('readonly', True)]}, @@ -138,7 +131,7 @@ class MrpWorkorder(models.Model): scrap_ids = fields.One2many('stock.scrap', 'workorder_id') scrap_count = fields.Integer(compute='_compute_scrap_move_count', string='Scrap Move') - production_date = fields.Datetime('Production Date', related='production_id.date_planned_start', store=True) + production_date = fields.Datetime('Production Date', related='production_id.date_start', store=True) json_popover = fields.Char('Popover Data JSON', compute='_compute_json_popover') show_json_popover = fields.Boolean('Show Popover?', compute='_compute_json_popover') consumption = fields.Selection(related='production_id.consumption') @@ -177,33 +170,33 @@ class MrpWorkorder(models.Model): elif workorder.production_id.reservation_state != 'assigned' and workorder.state == 'ready': workorder.state = 'waiting' - @api.depends('production_state', 'date_planned_start', 'date_planned_finished') + @api.depends('production_state', 'date_start', 'date_finished') def _compute_json_popover(self): if self.ids: conflicted_dict = self._get_conflicted_workorder_ids() for wo in self: infos = [] - if not wo.date_planned_start or not wo.date_planned_finished or not wo.ids: + if not wo.date_start or not wo.date_finished or not wo.ids: wo.show_json_popover = False wo.json_popover = False continue if wo.state in ('pending', 'waiting', 'ready'): previous_wos = wo.blocked_by_workorder_ids - prev_start = min([workorder.date_planned_start for workorder in previous_wos]) if previous_wos else False - prev_finished = max([workorder.date_planned_finished for workorder in previous_wos]) if previous_wos else False - if wo.state == 'pending' and prev_start and not (prev_start > wo.date_planned_start): + prev_start = min([workorder.date_start for workorder in previous_wos]) if previous_wos else False + prev_finished = max([workorder.date_finished for workorder in previous_wos]) if previous_wos else False + if wo.state == 'pending' and prev_start and not (prev_start > wo.date_start): infos.append({ 'color': 'text-primary', 'msg': _("Waiting the previous work order, planned from %(start)s to %(end)s", start=format_datetime(self.env, prev_start, dt_format=False), end=format_datetime(self.env, prev_finished, dt_format=False)) }) - if wo.date_planned_finished < fields.Datetime.now(): + if wo.date_finished < fields.Datetime.now(): infos.append({ 'color': 'text-warning', 'msg': _("The work order should have already been processed.") }) - if prev_start and prev_start > wo.date_planned_start: + if prev_start and prev_start > wo.date_start: infos.append({ 'color': 'text-danger', 'msg': _("Scheduled before the previous work order, planned from %(start)s to %(end)s", @@ -245,26 +238,26 @@ class MrpWorkorder(models.Model): workorder.production_id.qty_producing = workorder.qty_producing workorder.production_id._set_qty_producing() - # Both `date_planned_start` and `date_planned_finished` are related fields on `leave_id`. Let's say + # Both `date_start` and `date_finished` are related fields on `leave_id`. Let's say # we slide a workorder on a gantt view, a single call to write is made with both # fields Changes. As the ORM doesn't batch the write on related fields and instead # makes multiple call, the constraint check_dates() is raised. # That's why the compute and set methods are needed. to ensure the dates are updated # in the same time. @api.depends('leave_id') - def _compute_dates_planned(self): + def _compute_dates(self): for workorder in self: - workorder.date_planned_start = workorder.leave_id.date_from - workorder.date_planned_finished = workorder.leave_id.date_to + workorder.date_start = workorder.leave_id.date_from + workorder.date_finished = workorder.leave_id.date_to - def _set_dates_planned(self): - if not self[0].date_planned_start or not self[0].date_planned_finished: + def _set_dates(self): + if not self[0].date_start or not self[0].date_finished: if not self.leave_id: return raise UserError(_("It is not possible to unplan one single Work Order. " "You should unplan the Manufacturing Order instead in order to unplan all the linked operations.")) - date_from = self[0].date_planned_start - date_to = self[0].date_planned_finished + date_from = self[0].date_start + date_to = self[0].date_finished to_write = self.env['mrp.workorder'] for wo in self.sudo(): if wo.leave_id: @@ -415,25 +408,25 @@ class MrpWorkorder(models.Model): self.name = self.operation_id.name self.workcenter_id = self.operation_id.workcenter_id.id - @api.onchange('date_planned_start', 'duration_expected', 'workcenter_id') - def _onchange_date_planned_start(self): - if self.date_planned_start and self.workcenter_id: - self.date_planned_finished = self._calculate_date_planned_finished() + @api.onchange('date_start', 'duration_expected', 'workcenter_id') + def _onchange_date_start(self): + if self.date_start and self.workcenter_id: + self.date_finished = self._calculate_date_finished() - def _calculate_date_planned_finished(self, date_planned_start=False): + def _calculate_date_finished(self, date_finished=False): return self.workcenter_id.resource_calendar_id.plan_hours( - self.duration_expected / 60.0, date_planned_start or self.date_planned_start, + self.duration_expected / 60.0, date_finished or self.date_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: + @api.onchange('date_finished') + def _onchange_date_finished(self): + if self.date_start and self.date_finished: self.duration_expected = self._calculate_duration_expected() - def _calculate_duration_expected(self, date_planned_start=False, date_planned_finished=False): + def _calculate_duration_expected(self, date_start=False, date_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, + date_start or self.date_start, date_finished or self.date_finished, domain=[('time_type', 'in', ['leave', 'other'])] ) return interval['hours'] * 60 @@ -453,30 +446,30 @@ class MrpWorkorder(models.Model): if workorder.state in ('progress', 'done', 'cancel'): raise UserError(_('You cannot change the workcenter of a work order that is in progress or done.')) workorder.leave_id.resource_id = self.env['mrp.workcenter'].browse(values['workcenter_id']).resource_id - if 'date_planned_start' in values or 'date_planned_finished' in values: + if 'date_start' in values or 'date_finished' in values: for workorder in self: - start_date = fields.Datetime.to_datetime(values.get('date_planned_start', workorder.date_planned_start)) - end_date = fields.Datetime.to_datetime(values.get('date_planned_finished', workorder.date_planned_finished)) - if start_date and end_date and start_date > end_date: + date_start = fields.Datetime.to_datetime(values.get('date_start', workorder.date_start)) + date_finished = fields.Datetime.to_datetime(values.get('date_finished', workorder.date_finished)) + if date_start and date_finished and date_start > date_finished: 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 = workorder._calculate_date_planned_finished(start_date) - values['date_planned_finished'] = computed_finished_time - elif start_date and end_date: - computed_duration = workorder._calculate_duration_expected(date_planned_start=start_date, date_planned_finished=end_date) + if values.get('date_start') and values.get('date_finished'): + computed_finished_time = workorder._calculate_date_finished(date_start) + values['date_finished'] = computed_finished_time + elif date_start and date_finished: + computed_duration = workorder._calculate_duration_expected(date_start=date_start, date_finished=date_finished) 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: - if values['date_planned_start']: + if workorder == workorder.production_id.workorder_ids[0] and 'date_start' in values: + if values['date_start']: workorder.production_id.with_context(force_date=True).write({ - 'date_planned_start': fields.Datetime.to_datetime(values['date_planned_start']) + 'date_start': fields.Datetime.to_datetime(values['date_start']) }) - if workorder == workorder.production_id.workorder_ids[-1] and 'date_planned_finished' in values: - if values['date_planned_finished']: + if workorder == workorder.production_id.workorder_ids[-1] and 'date_finished' in values: + if values['date_finished']: workorder.production_id.with_context(force_date=True).write({ - 'date_planned_finished': fields.Datetime.to_datetime(values['date_planned_finished']) + 'date_finished': fields.Datetime.to_datetime(values['date_finished']) }) return super(MrpWorkorder, self).write(values) @@ -503,12 +496,12 @@ class MrpWorkorder(models.Model): def _plan_workorder(self, replan=False): self.ensure_one() # Plan workorder after its predecessors - start_date = max(self.production_id.date_planned_start, datetime.now()) + date_start = max(self.production_id.date_start, datetime.now()) for workorder in self.blocked_by_workorder_ids: if workorder.state in ['done', 'cancel']: continue workorder._plan_workorder(replan) - start_date = max(start_date, workorder.date_planned_finished) + date_start = max(date_start, workorder.date_finished) # Plan only suitable workorders if self.state not in ['pending', 'waiting', 'ready']: return @@ -519,7 +512,7 @@ class MrpWorkorder(models.Model): return # Consider workcenter and alternatives workcenters = self.workcenter_id | self.workcenter_id.alternative_workcenter_ids - best_finished_date = datetime.max + best_date_finished = datetime.max vals = {} for workcenter in workcenters: if not workcenter.resource_calendar_id: @@ -529,28 +522,28 @@ class MrpWorkorder(models.Model): duration_expected = self.duration_expected else: duration_expected = self._get_duration_expected(alternative_workcenter=workcenter) - from_date, to_date = workcenter._get_first_available_slot(start_date, duration_expected) + from_date, to_date = workcenter._get_first_available_slot(date_start, duration_expected) # If the workcenter is unavailable, try planning on the next one if not from_date: continue # Check if this workcenter is better than the previous ones - if to_date and to_date < best_finished_date: - best_start_date = from_date - best_finished_date = to_date + if to_date and to_date < best_date_finished: + best_date_start = from_date + best_date_finished = to_date best_workcenter = workcenter vals = { 'workcenter_id': workcenter.id, 'duration_expected': duration_expected, } # If none of the workcenter are available, raise - if best_finished_date == datetime.max: + if best_date_finished == datetime.max: raise UserError(_('Impossible to plan the workorder. Please check the workcenter availabilities.')) # Create leave on chosen workcenter calendar leave = self.env['resource.calendar.leaves'].create({ 'name': self.display_name, 'calendar_id': best_workcenter.resource_calendar_id.id, - 'date_from': best_start_date, - 'date_to': best_finished_date, + 'date_from': best_date_start, + 'date_to': best_date_finished, 'resource_id': best_workcenter.resource_id.id, 'time_type': 'other' }) @@ -626,32 +619,33 @@ class MrpWorkorder(models.Model): }) if self.state == 'progress': return True - start_date = fields.Datetime.now() + date_start = fields.Datetime.now() vals = { 'state': 'progress', - 'date_start': start_date, + 'date_start': date_start, } if not self.leave_id: leave = self.env['resource.calendar.leaves'].create({ 'name': self.display_name, 'calendar_id': self.workcenter_id.resource_calendar_id.id, - 'date_from': start_date, - 'date_to': start_date + relativedelta(minutes=self.duration_expected), + 'date_from': date_start, + 'date_to': date_start + relativedelta(minutes=self.duration_expected), 'resource_id': self.workcenter_id.resource_id.id, 'time_type': 'other' }) + vals['date_finished'] = leave.date_to vals['leave_id'] = leave.id return self.write(vals) else: - if not self.date_planned_start or self.date_planned_start > start_date: - vals['date_planned_start'] = start_date - vals['date_planned_finished'] = self._calculate_date_planned_finished(start_date) - if self.date_planned_finished and self.date_planned_finished < start_date: - vals['date_planned_finished'] = start_date + if not self.date_start or self.date_start > date_start: + vals['date_start'] = date_start + vals['date_finished'] = self._calculate_date_finished(date_start) + if self.date_finished and self.date_finished < date_start: + vals['date_finished'] = date_start return self.with_context(bypass_duration_calculation=True).write(vals) def button_finish(self): - end_date = datetime.now() + date_finished = datetime.now() for workorder in self: if workorder.state in ('done', 'cancel'): continue @@ -659,14 +653,11 @@ class MrpWorkorder(models.Model): vals = { 'qty_produced': workorder.qty_produced or workorder.qty_producing or workorder.qty_production, 'state': 'done', - 'date_finished': end_date, - 'date_planned_finished': end_date, + 'date_finished': date_finished, 'costs_hour': workorder.workcenter_id.costs_hour } - if not workorder.date_start: - vals['date_start'] = end_date - if not workorder.date_planned_start or end_date < workorder.date_planned_start: - vals['date_planned_start'] = end_date + if not workorder.date_start or date_finished < workorder.date_start: + vals['date_start'] = date_finished workorder.with_context(bypass_duration_calculation=True).write(vals) return True @@ -717,7 +708,6 @@ class MrpWorkorder(models.Model): return self.write({ 'state': 'done', 'date_finished': end_date, - 'date_planned_finished': end_date, 'costs_hour': self.workcenter_id.costs_hour }) @@ -786,7 +776,7 @@ class MrpWorkorder(models.Model): :return: defaultdict with key as workorder id of self and value as related conflicted workorder """ - self.flush_model(['state', 'date_planned_start', 'date_planned_finished', 'workcenter_id']) + self.flush_model(['state', 'date_start', 'date_finished', 'workcenter_id']) sql = """ SELECT wo1.id, wo2.id FROM mrp_workorder wo1, mrp_workorder wo2 @@ -796,8 +786,8 @@ class MrpWorkorder(models.Model): AND wo2.state IN ('pending', 'waiting', 'ready') AND wo1.id != wo2.id AND wo1.workcenter_id = wo2.workcenter_id - AND (DATE_TRUNC('second', wo2.date_planned_start), DATE_TRUNC('second', wo2.date_planned_finished)) - OVERLAPS (DATE_TRUNC('second', wo1.date_planned_start), DATE_TRUNC('second', wo1.date_planned_finished)) + AND (DATE_TRUNC('second', wo2.date_start), DATE_TRUNC('second', wo2.date_finished)) + OVERLAPS (DATE_TRUNC('second', wo1.date_start), DATE_TRUNC('second', wo1.date_finished)) """ self.env.cr.execute(sql, [tuple(self.ids)]) res = defaultdict(list) diff --git a/addons/mrp/models/product.py b/addons/mrp/models/product.py index de60614180c..9517f976fa8 100644 --- a/addons/mrp/models/product.py +++ b/addons/mrp/models/product.py @@ -168,7 +168,7 @@ class ProductProduct(models.Model): def _compute_mrp_product_qty(self): date_from = fields.Datetime.to_string(fields.datetime.now() - timedelta(days=365)) #TODO: state = done? - domain = [('state', '=', 'done'), ('product_id', 'in', self.ids), ('date_planned_start', '>', date_from)] + domain = [('state', '=', 'done'), ('product_id', 'in', self.ids), ('date_start', '>', date_from)] read_group_res = self.env['mrp.production']._read_group(domain, ['product_id', 'product_uom_qty'], ['product_id']) mapped_data = dict([(data['product_id'][0], data['product_uom_qty']) for data in read_group_res]) for product in self: diff --git a/addons/mrp/models/stock_move.py b/addons/mrp/models/stock_move.py index 3680d5a31b5..27a0b318290 100644 --- a/addons/mrp/models/stock_move.py +++ b/addons/mrp/models/stock_move.py @@ -285,7 +285,7 @@ class StockMove(models.Model): continue # produced products + byproducts values['location_id'] = mo.production_location_id.id - values['date'] = mo._get_date_planned_finished() + values['date'] = mo.date_finished values['date_deadline'] = mo.date_deadline if not values.get('location_dest_id'): values['location_dest_id'] = mo.location_dest_id.id diff --git a/addons/mrp/models/stock_picking.py b/addons/mrp/models/stock_picking.py index f1a63be51fe..359752fa773 100644 --- a/addons/mrp/models/stock_picking.py +++ b/addons/mrp/models/stock_picking.py @@ -36,7 +36,7 @@ class StockPickingType(models.Model): domains = { 'count_mo_waiting': [('reservation_state', '=', 'waiting')], 'count_mo_todo': ['|', ('state', 'in', ('confirmed', 'draft', 'progress', 'to_close')), ('is_planned', '=', True)], - 'count_mo_late': [('date_planned_start', '<', fields.Date.today()), ('state', '=', 'confirmed')], + 'count_mo_late': [('date_start', '<', fields.Date.today()), ('state', '=', 'confirmed')], } for field in domains: data = self.env['mrp.production']._read_group(domains[field] + diff --git a/addons/mrp/models/stock_rule.py b/addons/mrp/models/stock_rule.py index 6d1a6c8ae89..50d70b9b491 100644 --- a/addons/mrp/models/stock_rule.py +++ b/addons/mrp/models/stock_rule.py @@ -156,8 +156,8 @@ class StockRule(models.Model): 'location_dest_id': location_dest_id.id, 'bom_id': bom.id, 'date_deadline': date_deadline, - 'date_planned_start': date_planned, - 'date_planned_finished': fields.Datetime.from_string(values['date_planned']), + 'date_start': date_planned, + 'date_finished': fields.Datetime.from_string(values['date_planned']), 'procurement_group_id': False, 'propagate_cancel': self.propagate_cancel, 'orderpoint_id': values.get('orderpoint_id', False) and values.get('orderpoint_id').id, diff --git a/addons/mrp/populate/mrp.py b/addons/mrp/populate/mrp.py index 45fc2316f66..be344ef1411 100644 --- a/addons/mrp/populate/mrp.py +++ b/addons/mrp/populate/mrp.py @@ -332,7 +332,7 @@ class MrpProduction(models.Model): picking_type = self.env['stock.picking.type'].browse(values['picking_type_id']) return picking_type.default_location_dest_id.id - def get_date_planned_start(values, counter, random): + def get_date_start(values, counter, random): # 95.45 % of picking scheduled between (-10, 30) days and follow a gauss distribution (only +-15% picking is late) delta = random.gauss(10, 10) return now + timedelta(days=delta) @@ -345,7 +345,7 @@ class MrpProduction(models.Model): ('product_uom_id', populate.compute(get_product_uom_id)), ('product_qty', populate.randint(1, 10)), ('picking_type_id', populate.compute(get_picking_type_id)), - ('date_planned_start', populate.compute(get_date_planned_start)), + ('date_start', populate.compute(get_date_start)), ('location_src_id', populate.compute(get_location_src_id)), ('location_dest_id', populate.compute(get_location_dest_id)), ('priority', populate.iterate(['0', '1'], [0.95, 0.05])), @@ -399,7 +399,7 @@ class StockMove(models.Model): values['location_dest_id'] = production.production_location_id.id values['picking_type_id'] = production.picking_type_id.id values['name'] = production.name - values['date'] = production.date_planned_start + values['date'] = production.date_start values['company_id'] = production.company_id.id yield values diff --git a/addons/mrp/report/mrp_report_mo_overview.py b/addons/mrp/report/mrp_report_mo_overview.py index 4d9798bdcd5..2d38f103bad 100644 --- a/addons/mrp/report/mrp_report_mo_overview.py +++ b/addons/mrp/report/mrp_report_mo_overview.py @@ -92,7 +92,7 @@ class ReportMoOverview(models.AbstractModel): 'quantity_free': product.uom_id._compute_quantity(product.free_qty, production.product_uom_id) if product.type == 'product' else False, 'quantity_on_hand': product.uom_id._compute_quantity(product.qty_available, production.product_uom_id) if product.type == 'product' else False, 'quantity_reserved': 0.0, - 'receipt': self._check_planned_start(production.date_planned_start, self._get_replenishment_receipt(production, components)), + 'receipt': self._check_planned_start(production.date_start, self._get_replenishment_receipt(production, components)), 'mo_cost': company.currency_id.round(mo_cost + operations.get('summary', {}).get('mo_cost', 0.0)), 'product_cost': company.currency_id.round(product.standard_price * production.product_uom_qty), 'currency_id': company.currency_id.id, @@ -202,7 +202,7 @@ class ReportMoOverview(models.AbstractModel): 'quantity_free': product.uom_id._compute_quantity(product.free_qty, move_raw.product_uom) if product.type == 'product' else False, 'quantity_on_hand': product.uom_id._compute_quantity(product.qty_available, move_raw.product_uom) if product.type == 'product' else False, 'quantity_reserved': self._get_reserved_qty(move_raw, production.warehouse_id, replenish_data), - 'receipt': self._check_planned_start(production.date_planned_start, self._get_component_receipt(product, move_raw, production.warehouse_id, replenishments, replenish_data)), + 'receipt': self._check_planned_start(production.date_start, self._get_component_receipt(product, move_raw, production.warehouse_id, replenishments, replenish_data)), 'mo_cost': company.currency_id.round(mo_cost if replenishments else product_cost), 'product_cost': company.currency_id.round(product_cost), 'currency_id': company.currency_id.id, @@ -281,7 +281,7 @@ class ReportMoOverview(models.AbstractModel): replenishment['components'] = self._get_components_data(doc_in, replenish_data, level + 2, replenishment_index) replenishment['operations'] = self._get_operations_data(doc_in, level + 2, replenishment_index) replenishment['summary']['mo_cost'] = currency.round(sum(component.get('summary', {}).get('mo_cost', 0.0) for component in replenishment['components']) + replenishment['operations'].get('summary', {}).get('mo_cost', 0.0)) - replenishment['summary']['receipt'] = self._check_planned_start(production.date_planned_start, self._get_replenishment_receipt(doc_in, replenishment.get('components', []))) + replenishment['summary']['receipt'] = self._check_planned_start(production.date_start, self._get_replenishment_receipt(doc_in, replenishment.get('components', []))) replenishments.append(replenishment) total_ordered += replenishment['summary']['quantity'] @@ -295,7 +295,7 @@ class ReportMoOverview(models.AbstractModel): rules_delay = sum(rule.delay for rule in resupply_rules) resupply_data = self._get_resupply_data(resupply_rules, rules_delay, missing_quantity, move_raw.product_uom, product, production.warehouse_id) if resupply_data: - receipt = self._check_planned_start(production.date_planned_start, self._format_receipt_date('estimated', fields.datetime.today() + timedelta(days=resupply_data['delay']))) + receipt = self._check_planned_start(production.date_start, self._format_receipt_date('estimated', fields.datetime.today() + timedelta(days=resupply_data['delay']))) else: receipt = self._format_receipt_date('unavailable') @@ -317,7 +317,7 @@ class ReportMoOverview(models.AbstractModel): }} if resupply_data: to_order_line['mo_cost'] = currency.round(resupply_data['cost'] * move_raw.product_uom._compute_quantity(missing_quantity, product.uom_id)) - to_order_line['receipt'] = self._check_planned_start(production.date_planned_start, self._format_receipt_date('estimated', fields.datetime.today() + timedelta(days=resupply_data['delay']))), + to_order_line['receipt'] = self._check_planned_start(production.date_start, self._format_receipt_date('estimated', fields.datetime.today() + timedelta(days=resupply_data['delay']))), else: to_order_line['mo_cost'] = currency.round(product.standard_price * move_raw.product_uom._compute_quantity(missing_quantity, product.uom_id)) to_order_line['receipt'] = self._format_receipt_date('unavailable') @@ -330,7 +330,7 @@ class ReportMoOverview(models.AbstractModel): def _get_replenishment_receipt(self, doc_in, components): if doc_in._name == 'mrp.production': - max_date_start = doc_in.date_planned_start + max_date_start = doc_in.date_start all_available = True some_unavailable = False some_estimated = False @@ -344,7 +344,7 @@ class ReportMoOverview(models.AbstractModel): if some_unavailable: return self._format_receipt_date('unavailable') if all_available: - return self._format_receipt_date('expected', doc_in.date_planned_finished) + return self._format_receipt_date('expected', doc_in.date_finished) new_date = max_date_start + timedelta(days=doc_in.product_id.produce_delay) receipt_state = 'estimated' if some_estimated else 'expected' diff --git a/addons/mrp/report/report_stock_reception.py b/addons/mrp/report/report_stock_reception.py index a58ce816375..b3b91e4c567 100644 --- a/addons/mrp/report/report_stock_reception.py +++ b/addons/mrp/report/report_stock_reception.py @@ -33,7 +33,7 @@ class ReceptionReport(models.AbstractModel): def _get_formatted_scheduled_date(self, source): if source._name == 'mrp.production': - return format_date(self.env, source.date_planned_start) + return format_date(self.env, source.date_start) return super()._get_formatted_scheduled_date(source) def _action_assign(self, in_move, out_move): diff --git a/addons/mrp/tests/test_backorder.py b/addons/mrp/tests/test_backorder.py index 6c9bc302c89..06e5fc91a7c 100644 --- a/addons/mrp/tests/test_backorder.py +++ b/addons/mrp/tests/test_backorder.py @@ -391,13 +391,13 @@ class TestMrpProductionBackorder(TestMrpCommon): The MO and the backorder should be assigned according to the reservation method defined in the default manufacturing operation type """ - def create_mo(date_planned_start=False): + def create_mo(date_start=False): mo_form = Form(self.env['mrp.production']) mo_form.product_id = self.bom_1.product_id mo_form.bom_id = self.bom_1 mo_form.product_qty = 2 - if date_planned_start: - mo_form.date_planned_start = date_planned_start + if date_start: + mo_form.date_start = date_start mo = mo_form.save() mo.action_confirm() return mo diff --git a/addons/mrp/tests/test_order.py b/addons/mrp/tests/test_order.py index 428bc118e14..5e4f968a938 100644 --- a/addons/mrp/tests/test_order.py +++ b/addons/mrp/tests/test_order.py @@ -57,14 +57,14 @@ class TestMrpOrder(TestMrpCommon): 'inventory_quantity': 500 }).action_apply_inventory() - test_date_planned = fields.Datetime.now() - timedelta(days=1) + date_start = fields.Datetime.now() - timedelta(days=1) test_quantity = 3.0 man_order_form = Form(self.env['mrp.production'].with_user(self.user_mrp_user)) man_order_form.product_id = self.product_4 man_order_form.bom_id = self.bom_1 man_order_form.product_uom_id = self.product_4.uom_id man_order_form.product_qty = test_quantity - man_order_form.date_planned_start = test_date_planned + man_order_form.date_start = date_start man_order_form.location_src_id = self.location_1 man_order_form.location_dest_id = self.warehouse_1.wh_output_stock_loc_id man_order = man_order_form.save() @@ -75,7 +75,7 @@ class TestMrpOrder(TestMrpCommon): # check production move production_move = man_order.move_finished_ids - self.assertAlmostEqual(production_move.date, test_date_planned + timedelta(hours=1), delta=timedelta(seconds=10)) + self.assertAlmostEqual(production_move.date, date_start + timedelta(hours=1), delta=timedelta(seconds=10)) self.assertEqual(production_move.product_id, self.product_4) self.assertEqual(production_move.product_uom, man_order.product_uom_id) self.assertEqual(production_move.product_qty, man_order.product_qty) @@ -84,7 +84,7 @@ class TestMrpOrder(TestMrpCommon): # check consumption moves for move in man_order.move_raw_ids: - self.assertEqual(move.date, test_date_planned) + self.assertEqual(move.date, date_start) first_move = man_order.move_raw_ids.filtered(lambda move: move.product_id == self.product_2) self.assertEqual(first_move.product_qty, test_quantity / self.bom_1.product_qty * self.product_4.uom_id.factor_inv * 2) first_move = man_order.move_raw_ids.filtered(lambda move: move.product_id == self.product_1) @@ -485,17 +485,17 @@ class TestMrpOrder(TestMrpCommon): def test_update_plan_date(self): """Editing the scheduled date after planning the MO should unplan the MO, and adjust the date on the stock moves""" - planned_date = datetime(2023, 5, 15, 9, 0) + date_start = datetime(2023, 5, 15, 9, 0) mo_form = Form(self.env['mrp.production']) mo_form.product_id = self.product_4 mo_form.bom_id = self.bom_1 mo_form.product_qty = 1 - mo_form.date_planned_start = planned_date + mo_form.date_start = date_start mo = mo_form.save() self.assertEqual(mo.move_finished_ids[0].date, datetime(2023, 5, 15, 10, 0)) mo.action_confirm() mo.button_plan() - mo.date_planned_start = datetime(2024, 5, 15, 9, 0) + mo.date_start = datetime(2024, 5, 15, 9, 0) self.assertEqual(mo.move_finished_ids[0].date, datetime(2024, 5, 15, 10, 0)) def test_rounding(self): @@ -1346,7 +1346,7 @@ class TestMrpOrder(TestMrpCommon): self.assertEqual(move.propagate_cancel, mo.propagate_cancel) self.assertFalse(move.raw_material_production_id) self.assertEqual(move.location_id, mo.production_location_id) - self.assertEqual(move.date, mo._get_date_planned_finished()) + self.assertEqual(move.date, mo.date_finished) self.assertEqual(move.date_deadline, mo.date_deadline) mo.move_raw_ids |= move @@ -1580,7 +1580,7 @@ class TestMrpOrder(TestMrpCommon): now = fields.Datetime.now() mo_form = Form(self.env['mrp.production']) mo_form.bom_id = self.bom_3 # product_5 (2), product_4 (8), product_2 (12) - mo_form.date_planned_start = now + mo_form.date_start = now mo = mo_form.save() self.assertEqual(mo.components_availability, False) # no compute for draft mo.action_confirm() @@ -1607,7 +1607,7 @@ class TestMrpOrder(TestMrpCommon): self.assertEqual(mo.components_availability, f'Exp {format_date(self.env, tommorrow)}') self.assertEqual(mo.components_availability_state, 'late') - mo.date_planned_start = after_tommorrow + mo.date_start = after_tommorrow self.assertEqual(mo.components_availability, f'Exp {format_date(self.env, tommorrow)}') self.assertEqual(mo.components_availability_state, 'expected') @@ -1959,10 +1959,10 @@ class TestMrpOrder(TestMrpCommon): }) # Next Monday at 6:00 am UTC - date_planned = (fields.Datetime.now() + timedelta(days=7 - fields.Datetime.now().weekday())).replace(hour=6, minute=0, second=0) + date_start = (fields.Datetime.now() + timedelta(days=7 - fields.Datetime.now().weekday())).replace(hour=6, minute=0, second=0) mo_form = Form(self.env['mrp.production']) mo_form.bom_id = bom - mo_form.date_planned_start = date_planned + mo_form.date_start = date_start mo = mo_form.save() mo.workorder_ids[0].duration_expected = 240 @@ -1974,11 +1974,11 @@ class TestMrpOrder(TestMrpCommon): # Asia/Bangkok is UTC+7 and the start date is on Monday at 06:00 UTC (i.e., 13:00 UTC+7). # So, in Bangkok, the first workorder uses the entire Monday afternoon slot 13:00 - 17:00 UTC+7 (i.e., 06:00 - 10:00 UTC) # The second job uses the beginning of the Tuesday morning slot: 08:00 - 09:00 UTC+7 (i.e., 01:00 - 02:00 UTC) - self.assertEqual(mo.workorder_ids[0].date_planned_start, date_planned) - self.assertEqual(mo.workorder_ids[0].date_planned_finished, date_planned + timedelta(hours=4)) - tuesday = date_planned + timedelta(days=1) - self.assertEqual(mo.workorder_ids[1].date_planned_start, tuesday.replace(hour=1)) - self.assertEqual(mo.workorder_ids[1].date_planned_finished, tuesday.replace(hour=2)) + self.assertEqual(mo.workorder_ids[0].date_start, date_start) + self.assertEqual(mo.workorder_ids[0].date_finished, date_start + timedelta(hours=4)) + tuesday = date_start + timedelta(days=1) + self.assertEqual(mo.workorder_ids[1].date_start, tuesday.replace(hour=1)) + self.assertEqual(mo.workorder_ids[1].date_finished, tuesday.replace(hour=2)) def test_backorder_with_overconsumption(self): """ Check that the components of the backorder have the correct quantities @@ -2838,7 +2838,7 @@ class TestMrpOrder(TestMrpCommon): mo_form = Form(self.env['mrp.production']) mo_form.bom_id = self.bom_4 with mo_form.workorder_ids.edit(0) as wo_line: - wo_line.date_planned_start = datetime.now() + wo_line.date_start = datetime.now() mos += mo_form.save() mos.action_confirm() @@ -2853,7 +2853,7 @@ class TestMrpOrder(TestMrpCommon): self.assertFalse(wo_01.show_json_popover) self.assertFalse(wo_02.show_json_popover) - self.assertEqual(wo_01.date_planned_finished, wo_02.date_planned_start) + self.assertEqual(wo_01.date_finished, wo_02.date_start) @freeze_time('2022-06-28 08:00') def test_replan_workorders02(self): @@ -2876,7 +2876,7 @@ class TestMrpOrder(TestMrpCommon): for mo in mos: with Form(mo) as mo_form: with mo_form.workorder_ids.edit(0) as wo_line: - wo_line.date_planned_start = datetime.now() + wo_line.date_start = datetime.now() wo_01 = mo_01.workorder_ids wo_02 = mo_02.workorder_ids @@ -2887,7 +2887,7 @@ class TestMrpOrder(TestMrpCommon): self.assertFalse(wo_01.show_json_popover) self.assertFalse(wo_02.show_json_popover) - self.assertEqual(wo_01.date_planned_finished, wo_02.date_planned_start) + self.assertEqual(wo_01.date_finished, wo_02.date_start) @freeze_time('2022-10-05 12:00') def test_replan_mo_without_bom(self): @@ -2930,27 +2930,27 @@ class TestMrpOrder(TestMrpCommon): 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) + workorder.date_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)) + self.assertEqual(op_2.date_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) + workorder.date_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) + self.assertEqual(op_1.date_start, datetime(2022, 10, 18, 12)) + self.assertEqual(op_1.date_finished, op_2.date_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) + workorder.date_start = datetime(2022, 10, 20, 12) mo_02 = mo_02_form.save() mo_02.action_confirm() @@ -2958,11 +2958,11 @@ class TestMrpOrder(TestMrpCommon): 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) + workorder.date_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.assertEqual(op_1.date_start, datetime(2022, 10, 20, 12)) self.assertTrue(op_2.show_json_popover) @freeze_time('2023-03-01 12:00') @@ -3014,9 +3014,9 @@ class TestMrpOrder(TestMrpCommon): mo = mo_form.save() mo.action_confirm() mo.button_plan() - self.assertEqual(mo.workorder_ids[0].date_planned_start, datetime(2023, 3, 1, 12, 0)) - self.assertEqual(mo.workorder_ids[1].date_planned_start, datetime(2023, 3, 1, 13, 15)) - self.assertEqual(mo.workorder_ids[2].date_planned_start, datetime(2023, 3, 1, 14, 30)) + self.assertEqual(mo.workorder_ids[0].date_start, datetime(2023, 3, 1, 12, 0)) + self.assertEqual(mo.workorder_ids[1].date_start, datetime(2023, 3, 1, 13, 15)) + self.assertEqual(mo.workorder_ids[2].date_start, datetime(2023, 3, 1, 14, 30)) # wo_1 completely finished mo_form = Form(mo) @@ -3041,9 +3041,9 @@ class TestMrpOrder(TestMrpCommon): self.assertEqual(mo_backorder.workorder_ids[0].state, 'cancel') self.assertEqual(mo_backorder.workorder_ids[1].state, 'waiting') self.assertEqual(mo_backorder.workorder_ids[2].state, 'pending') - self.assertFalse(mo_backorder.workorder_ids[0].date_planned_start) - self.assertEqual(mo_backorder.workorder_ids[1].date_planned_start, datetime(2023, 3, 1, 12, 0)) - self.assertEqual(mo_backorder.workorder_ids[2].date_planned_start, datetime(2023, 3, 1, 12, 45)) + self.assertFalse(mo_backorder.workorder_ids[0].date_start) + self.assertEqual(mo_backorder.workorder_ids[1].date_start, datetime(2023, 3, 1, 12, 0)) + self.assertEqual(mo_backorder.workorder_ids[2].date_start, datetime(2023, 3, 1, 12, 45)) def test_compute_product_id(self): """ diff --git a/addons/mrp/tests/test_procurement.py b/addons/mrp/tests/test_procurement.py index 3caa9d79825..49bc491009d 100644 --- a/addons/mrp/tests/test_procurement.py +++ b/addons/mrp/tests/test_procurement.py @@ -249,11 +249,11 @@ class TestProcurement(TestMrpCommon): self.assertEqual(len(move_orig), 1, 'the move orig is not created') self.assertEqual(move_orig.product_qty, 10, 'the quantity to produce is not good relative to the move') - new_sheduled_date = fields.Datetime.to_datetime(mo.date_planned_start) + timedelta(days=5) - mo.date_planned_start = new_sheduled_date + new_date_start = fields.Datetime.to_datetime(mo.date_start) + timedelta(days=5) + mo.date_start = new_date_start - self.assertAlmostEqual(mo.move_raw_ids.date, mo.date_planned_start, delta=timedelta(seconds=1)) - self.assertAlmostEqual(mo.move_finished_ids.date, mo.date_planned_finished, delta=timedelta(seconds=1)) + self.assertAlmostEqual(mo.move_raw_ids.date, mo.date_start, delta=timedelta(seconds=1)) + self.assertAlmostEqual(mo.move_finished_ids.date, mo.date_finished, delta=timedelta(seconds=1)) def test_finished_move_cancellation(self): """Check state of finished move on cancellation of raw moves. """ diff --git a/addons/mrp/views/mrp_production_views.xml b/addons/mrp/views/mrp_production_views.xml index e262f61f954..7f4cdd7fd51 100644 --- a/addons/mrp/views/mrp_production_views.xml +++ b/addons/mrp/views/mrp_production_views.xml @@ -23,7 +23,7 @@ - + @@ -41,8 +41,8 @@ - - + + - + @@ -239,13 +239,14 @@ -