summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArnold Moyaux <arm@odoo.com>2019-07-01 07:52:50 +0000
committerArnold Moyaux <arm@odoo.com>2019-07-15 11:52:47 +0000
commitccbd6712f6f2797a00aa165ded3292d355fcc5a0 (patch)
tree65ed567a8c556278fb8e657e46c38a8b7327b59d
parentd9b7cc7ab7ae7ee759c9931be20361c2348d2753 (diff)
[FIX] mrp: MO change the quantity to 0
Usecase to reproduce: - Create a MO for 5 final units - Reserve all the components - Produce 3 units - Post Inventory (debug mode) - Edit/Unlock - Edit a line to consume to an arbitrary amount of quantity - Change the product qty and set it to 3. At this point, the reserved quantity and the quantity to consume still the same than intialy even if the final quantity was updated. - Mark as done Then a move is marked as done withtout quantity done and still have reserved quantity. It happens because the _update_raw_move function do nothing if the new quantity to consume is equals to 0. The arguments returns in _update_raw_move still exists for override but are not used by the chang_prod_qty method. It's not possible to cancel the move and then find its parents in order to log the activity. opw-2023653 closes odoo/odoo#34471 Signed-off-by: Arnold Moyaux <amoyaux@users.noreply.github.com>
-rw-r--r--addons/mrp/models/mrp_production.py5
-rw-r--r--addons/mrp/tests/test_order.py46
-rw-r--r--addons/mrp/wizard/change_production_qty.py11
3 files changed, 58 insertions, 4 deletions
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: