[FIX] mrp: unlock and modify quantity of overproduced MO

Usecase to reproduce:
- Create a MO for 2 unit (1 component per finished product)
- Produce 3 units
- Mark as done
- Unlock and change the quantity to 3 units

Expected behavior:
3 components removed from stock

Current behavior:
6 components removed from stock

It happens because the set_quantity_done create a new stock.move.line
with excessive quantity. Then the write of qty_producing in
mrp.production will write this quantity on all the `stock.move.line`.
It results by moving number of sml * the new quantity producing

Solution do the write of new quantity done on the `stock.move` level
and let him manage the `stock.move.line`

closes odoo/odoo#161728

X-original-commit: fa3439e5c595a04e67fa22965d6b10bb1f487f63
Signed-off-by: William Henrotin (whe) <whe@odoo.com>
Signed-off-by: Arnold Moyaux (arm) <arm@odoo.com>
This commit is contained in:
Arnold Moyaux
2024-04-25 13:22:55 +00:00
parent cc6b224bb0
commit 5063f8f913
2 changed files with 35 additions and 3 deletions
+4 -3
View File
@@ -889,12 +889,13 @@ class MrpProduction(models.Model):
if production in production_to_replan:
production._plan_workorders()
if production.state == 'done' and ('lot_producing_id' in vals or 'qty_producing' in vals):
finished_move_lines = production.move_finished_ids.filtered(
lambda move: move.product_id == production.product_id and move.state == 'done').mapped('move_line_ids')
finished_move = production.move_finished_ids.filtered(
lambda move: move.product_id == production.product_id and move.state == 'done')
finished_move_lines = finished_move.move_line_ids
if 'lot_producing_id' in vals:
finished_move_lines.write({'lot_id': vals.get('lot_producing_id')})
if 'qty_producing' in vals:
finished_move_lines.write({'quantity': vals.get('qty_producing')})
finished_move.quantity = vals.get('qty_producing')
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:
+31
View File
@@ -805,6 +805,37 @@ class TestMrpOrder(TestMrpCommon):
mo.button_mark_done()
self.assertTrue(all(s in ['done', 'cancel'] for s in mo.move_raw_ids.mapped('state')))
def test_product_produce_7(self):
""" Plan 2 finished products, reserve and produce 3. Post the current production.
Simulate an unlock and edit and, on the opened moves, set the consumed quantity
to 5, and to 4. Check the component quantity removed from inventory is correct."""
self.stock_location = self.env.ref('stock.stock_location_stock')
mo, _, _, p1, p2 = self.generate_mo(qty_final=1)
self.assertEqual(len(mo), 1, 'MO should have been created')
self.env['stock.quant']._update_available_quantity(p1, self.stock_location, 20)
self.env['stock.quant']._update_available_quantity(p2, self.stock_location, 5)
mo.action_assign()
mo_form = Form(mo)
mo_form.qty_producing = 2
mo = mo_form.save()
mo.button_mark_done()
self.assertEqual(sum(mo.move_finished_ids.move_line_ids.mapped('quantity')), 2)
self.assertTrue(mo.is_locked)
mo.action_toggle_is_locked()
self.assertFalse(mo.is_locked)
mo_form = Form(mo)
mo_form.qty_producing = 5
mo = mo_form.save()
self.assertAlmostEqual(sum(mo.move_finished_ids.move_line_ids.mapped('quantity')), 5)
mo_form = Form(mo)
mo_form.qty_producing = 4
mo = mo_form.save()
self.assertAlmostEqual(sum(mo.move_finished_ids.move_line_ids.mapped('quantity')), 4)
def test_consumption_strict_1(self):
""" Checks the constraints of a strict BOM without tracking when playing around
quantities to consume."""