diff --git a/addons/mrp/models/mrp_production.py b/addons/mrp/models/mrp_production.py index 09c779b29da..339c97d5bb0 100644 --- a/addons/mrp/models/mrp_production.py +++ b/addons/mrp/models/mrp_production.py @@ -509,12 +509,13 @@ class MrpProduction(models.Model): move[0]._recompute_state() move[0]._action_assign() move[0].unit_factor = quantity / move[0].raw_material_production_id.product_qty - elif quantity < 0: # Do not remove 0 lines + return move[0], old_qty, quantity + else: if move[0].quantity_done > 0: raise UserError(_('Lines need to be deleted, but can not as you still have some quantities to consume in them. ')) move[0]._action_cancel() move[0].unlink() - return move[0], old_qty, quantity + return self.env['stock.move'], old_qty, quantity else: move = self._generate_raw_move(bom_line, line_data) return move, 0, quantity diff --git a/addons/mrp/tests/test_order.py b/addons/mrp/tests/test_order.py index 61538b5ecab..fc98bfcdbc3 100644 --- a/addons/mrp/tests/test_order.py +++ b/addons/mrp/tests/test_order.py @@ -5,6 +5,7 @@ from odoo.tests import Form from datetime import datetime, timedelta from odoo.fields import Datetime as Dt +from odoo.exceptions import UserError from odoo.addons.mrp.tests.common import TestMrpCommon @@ -677,6 +678,51 @@ class TestMrpOrder(TestMrpCommon): self.assertEqual(mo.move_raw_ids.filtered(lambda m: m.product_id == p1).quantity_done, 20, 'Update the produce quantity should not impact already produced quantity.') mo.button_mark_done() + def test_product_produce_6(self): + """ Plan 5 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 3. Now, try to update the quantity to produce to 3. It should fail since there + are consumed quantities. Unlock and edit, remove the consumed quantities and + update the quantity to produce to 3.""" + self.stock_location = self.env.ref('stock.stock_location_stock') + mo, bom, p_final, p1, p2 = self.generate_mo() + 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() + + produce_wizard = self.env['mrp.product.produce'].with_context({ + 'active_id': mo.id, + 'active_ids': [mo.id], + }).create({ + 'product_qty': 3.0, + }) + produce_wizard._onchange_product_qty() + produce_wizard.do_produce() + + mo.post_inventory() + self.assertEqual(len(mo.move_raw_ids), 4) + + mo.move_raw_ids.filtered(lambda m: m.state != 'done')[0].quantity_done = 3 + + update_quantity_wizard = self.env['change.production.qty'].create({ + 'mo_id': mo.id, + 'product_qty': 3, + }) + with self.assertRaises(UserError): + update_quantity_wizard.change_prod_qty() + + mo.move_raw_ids.filtered(lambda m: m.state != 'done')[0].quantity_done = 0 + update_quantity_wizard.change_prod_qty() + + self.assertEqual(len(mo.move_raw_ids), 2) + + mo.button_mark_done() + self.assertTrue(all(s == 'done' for s in mo.move_raw_ids.mapped('state'))) + self.assertEqual(sum(mo.move_raw_ids.mapped('move_line_ids.product_uom_qty')), 0) + def test_product_produce_uom(self): plastic_laminate = self.env.ref('mrp.product_product_plastic_laminate') bom = self.env.ref('mrp.mrp_bom_plastic_laminate') diff --git a/addons/mrp/wizard/change_production_qty.py b/addons/mrp/wizard/change_production_qty.py index b92616c9a50..ff7439f3d12 100644 --- a/addons/mrp/wizard/change_production_qty.py +++ b/addons/mrp/wizard/change_production_qty.py @@ -54,15 +54,22 @@ class ChangeProductionQty(models.TransientModel): boms, lines = production.bom_id.explode(production.product_id, factor, picking_type=production.bom_id.picking_type_id) documents = {} for line, line_data in lines: - move, old_qty, new_qty = production._update_raw_move(line, line_data) + move = production.move_raw_ids.filtered(lambda x: x.bom_line_id.id == line.id and x.state not in ('done', 'cancel')) + if move: + old_qty = move[0].product_uom_qty + else: + old_qty = 0 iterate_key = production._get_document_iterate_key(move) if iterate_key: - document = self.env['stock.picking']._log_activity_get_documents({move: (new_qty, old_qty)}, iterate_key, 'UP') + document = self.env['stock.picking']._log_activity_get_documents({move: (line_data['qty'], old_qty)}, iterate_key, 'UP') for key, value in document.items(): if documents.get(key): documents[key] += [value] else: documents[key] = [value] + + production._update_raw_move(line, line_data) + production._log_manufacture_exception(documents) operation_bom_qty = {} for bom, bom_data in boms: