diff --git a/addons/mrp/models/mrp_production.py b/addons/mrp/models/mrp_production.py index a262e1eaeed..141db911e2c 100644 --- a/addons/mrp/models/mrp_production.py +++ b/addons/mrp/models/mrp_production.py @@ -95,11 +95,13 @@ class MrpProduction(models.Model): help="Location where the system will stock the finished products.") date_planned_start = fields.Datetime( 'Planned Date', copy=False, default=fields.Datetime.now, + compute='_compute_dates_planned', inverse='_set_date_planned_start', help="Date at which you plan to start the production.", index=True, required=True, store=True) date_planned_finished = fields.Datetime( 'Planned End Date', default=_get_default_date_planned_finished, + compute='_compute_dates_planned', inverse='_set_date_planned_finished', help="Date at which you plan to finish the production.", copy=False, store=True) date_deadline = fields.Datetime( @@ -221,6 +223,18 @@ class MrpProduction(models.Model): delivery_count = fields.Integer(string='Delivery Orders', compute='_compute_picking_ids') confirm_cancel = fields.Boolean(compute='_compute_confirm_cancel') + @api.depends('move_raw_ids.date_expected', 'move_finished_ids.date_expected') + def _compute_dates_planned(self): + for production in self: + production.date_planned_start = max(production.mapped('move_raw_ids.date_expected') or [fields.Datetime.now()]) + production.date_planned_finished = max(production.mapped('move_finished_ids.date_expected') or [production.date_deadline or fields.Datetime.now()]) + + def _set_date_planned_start(self): + self.move_raw_ids.write({'date_expected': self.date_planned_start}) + + def _set_date_planned_finished(self): + self.move_finished_ids.write({'date_expected': self.date_planned_finished}) + @api.depends('move_raw_ids.state', 'move_finished_ids.state') def _compute_confirm_cancel(self): """ If the manufacturing order contains some done move (via an intermediate @@ -428,10 +442,6 @@ class MrpProduction(models.Model): @api.onchange('date_planned_start') def _onchange_date_planned_start(self): - self.move_raw_ids.update({ - 'date': self.date_planned_start, - 'date_expected': self.date_planned_start, - }) if not self.routing_id: self.date_planned_finished = self.date_planned_start + datetime.timedelta(hours=1) @@ -474,12 +484,7 @@ class MrpProduction(models.Model): def write(self, vals): res = super(MrpProduction, self).write(vals) - if 'date_planned_start' in vals: - moves = (self.mapped('move_raw_ids') + self.mapped('move_finished_ids')).filtered( - lambda r: r.state not in ['done', 'cancel']) - moves.write({ - 'date_expected': fields.Datetime.to_datetime(vals['date_planned_start']), - }) + for production in self: if 'date_planned_start' in vals: if production.state in ['done', 'cancel']: @@ -488,6 +493,10 @@ class MrpProduction(models.Model): raise UserError(_('You cannot move a planned manufacturing order.')) if 'move_raw_ids' in vals and production.state != 'draft': production.move_raw_ids.filtered(lambda m: m.state == 'draft')._action_confirm() + if not production.routing_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) return res @api.model diff --git a/addons/mrp/tests/test_procurement.py b/addons/mrp/tests/test_procurement.py index 7ff4bdf9a45..0fb99e5570c 100644 --- a/addons/mrp/tests/test_procurement.py +++ b/addons/mrp/tests/test_procurement.py @@ -2,10 +2,12 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. from datetime import timedelta +from odoo import fields from odoo.tests import Form from odoo.addons.mrp.tests.common import TestMrpCommon from odoo.exceptions import UserError + class TestProcurement(TestMrpCommon): def test_procurement(self): @@ -177,6 +179,9 @@ class TestProcurement(TestMrpCommon): ('product_id', '=', product_1.id), ('state', '=', 'confirmed') ]) + + self.assertAlmostEqual(mo.move_finished_ids.date_expected, mo.move_raw_ids.date_expected + timedelta(hours=1)) + self.assertEqual(len(mo), 1, 'the manufacture order is not created') mo_form = Form(mo) @@ -193,10 +198,12 @@ class TestProcurement(TestMrpCommon): self.assertEqual(move_orig.product_qty, 10, 'the quantity to produce is not good relative to the move') move_dest_scheduled_date = move_dest.date_expected - mo.date_planned_start += timedelta(days=5) - # Adding 5 days to the date planned start makes the next move's date 4 days and 23 hours - # later since the date planned start was set one hour before the date_planned_end. - self.assertAlmostEqual(move_dest.date_expected, move_dest_scheduled_date + timedelta(days=4, hours=23), delta=timedelta(seconds=1), msg='date is not propagated') + + mo_form = Form(mo) + mo_form.date_planned_start = fields.Datetime.to_datetime(mo_form.date_planned_start) + timedelta(days=5) + mo_form.save() + + self.assertAlmostEqual(move_dest.date_expected, move_dest_scheduled_date + timedelta(days=5), delta=timedelta(seconds=1), msg='date is not propagated') def test_finished_move_cancellation(self): """Check state of finished move on cancellation of raw moves. """