diff --git a/addons/mrp/models/mrp_production.py b/addons/mrp/models/mrp_production.py index 2387ebc26a6..84af8642414 100644 --- a/addons/mrp/models/mrp_production.py +++ b/addons/mrp/models/mrp_production.py @@ -222,6 +222,13 @@ class MrpProduction(models.Model): picking_ids = fields.Many2many('stock.picking', compute='_compute_picking_ids', string='Picking associated to this manufacturing order') delivery_count = fields.Integer(string='Delivery Orders', compute='_compute_picking_ids') confirm_cancel = fields.Boolean(compute='_compute_confirm_cancel') + consumption = fields.Selection([ + ('strict', 'Strict'), + ('flexible', 'Flexible')], + required=True, + readonly=True, + default='strict', + ) mrp_production_child_count = fields.Integer("Number of generated MO", compute='_compute_mrp_production_child_count') mrp_production_source_count = fields.Integer("Number of source MO", compute='_compute_mrp_production_source_count') @@ -529,7 +536,7 @@ class MrpProduction(models.Model): if production.workorder_ids and not self.env.context.get('force_date', False): 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() + production._autoconfirm_production() 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: @@ -711,6 +718,22 @@ class MrpProduction(models.Model): return 'assigned' return 'confirmed' + def _autoconfirm_production(self): + """Automatically run `action_confirm` on `self`. + + If the production has one of its move was added after the initial call + to `action_confirm`. + """ + moves_to_confirm = self.env['stock.move'] + for production in self: + if production.state in ('done', 'cancel'): + continue + moves_to_confirm |= (production.move_raw_ids | production.move_finished_ids).filtered( + lambda move: move.state == 'draft' and move.additional + ) + if moves_to_confirm: + moves_to_confirm._action_confirm() + def action_view_mrp_production_childs(self): self.ensure_one() mrp_production_ids = self.procurement_group_id.stock_move_ids.created_production_id.ids @@ -754,6 +777,7 @@ class MrpProduction(models.Model): def action_confirm(self): self._check_company() for production in self: + production.consumption = production.bom_id.consumption if not production.move_raw_ids: raise UserError(_("Add some materials to consume before marking this MO as to do.")) for move_raw in production.move_raw_ids: diff --git a/addons/mrp/models/stock_move.py b/addons/mrp/models/stock_move.py index d0d9082db22..8485dd64f98 100644 --- a/addons/mrp/models/stock_move.py +++ b/addons/mrp/models/stock_move.py @@ -151,8 +151,11 @@ class StockMove(models.Model): defaults = super(StockMove, self).default_get(fields_list) if self.env.context.get('default_raw_material_production_id'): production_id = self.env['mrp.production'].browse(self.env.context['default_raw_material_production_id']) - if production_id.state == 'done': - defaults['state'] = 'done' + if production_id.state in ('confirmed', 'done'): + if production_id.state == 'confirmed': + defaults['state'] = 'draft' + else: + defaults['state'] = 'done' defaults['product_uom_qty'] = 0.0 defaults['additional'] = True return defaults diff --git a/addons/mrp/tests/test_workorder_operation.py b/addons/mrp/tests/test_workorder_operation.py index a40de34a204..d6acdf1db76 100644 --- a/addons/mrp/tests/test_workorder_operation.py +++ b/addons/mrp/tests/test_workorder_operation.py @@ -1791,3 +1791,37 @@ class TestRoutingAndKits(SavepointCase): wo1 = mo.workorder_ids[0] lines = wo1.raw_workorder_line_ids self.assertEqual(lines.product_id, add_product) + + def test_add_move_2(self): + """ Make a production using multi step routing. Add an additional move + on a specific operation and check that the produce is consumed into the + right workorder. """ + self.bom_finished1.consumption = 'flexible' + add_product = self.env['product.product'].create({ + 'name': 'Additional', + }) + mo_form = Form(self.env['mrp.production']) + mo_form.product_id = self.finished1 + mo_form.bom_id = self.bom_finished1 + mo_form.product_qty = 10.0 + mo = mo_form.save() + mo.action_confirm() + mo_form = Form(mo) + with mo_form.move_raw_ids.new() as move: + move.name = mo.name + move.product_id = add_product + move.product_uom = add_product.uom_id + move.location_id = mo.location_src_id + move.location_dest_id = mo.production_location_id + move.product_uom_qty = 2 + move.operation_id = mo.routing_id.operation_ids[0] + mo = mo_form.save() + new_move = mo.move_raw_ids.filtered(lambda move: move.additional) + self.assertEqual(len(mo.move_raw_ids), 3) + self.assertEqual(len(new_move), 1) + self.assertEqual(mo.move_raw_ids.mapped('state'), ['confirmed'] * 3) + mo.button_plan() + self.assertEqual(len(mo.workorder_ids), 3) + wo1 = mo.workorder_ids[0] + lines = wo1.raw_workorder_line_ids + self.assertEqual(lines.product_id, add_product) diff --git a/addons/mrp/views/mrp_production_views.xml b/addons/mrp/views/mrp_production_views.xml index 75c140d8d4b..803e29c28e1 100644 --- a/addons/mrp/views/mrp_production_views.xml +++ b/addons/mrp/views/mrp_production_views.xml @@ -73,6 +73,7 @@ +