summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPierre Masereel <pim@odoo.com>2017-07-26 12:18:33 +0200
committerSimon Lejeune <sle@openerp.com>2017-07-26 17:23:55 +0200
commit8a497cdd5ff4cf93067d0519a9839ea6ec9adc21 (patch)
treeeef4e9c4bfd4caf8381d38d122e08502cfc8ff76
parent2a0b158d4490817388da7de94969447d02744386 (diff)
[FIX] stock: quant: _update_reserved_quantity and negative quantity
If we have multiple quants returned when we want to decrease the reservation of a move line, the min function will always return the quantity passed in argument because 'reserved_quantity' is always a positive number and quantity a negative one. This can lead to negative reserved quantity on a quant, if the quantity to reserve on the first quant is lower than the absolute value of the quantity to decrease. To fix this, we correctly separate the behaviors for decrease and increase. We add a test that show the, now fixed, bug.
-rw-r--r--addons/stock/models/stock_quant.py18
-rw-r--r--addons/stock/tests/test_move.py39
2 files changed, 49 insertions, 8 deletions
diff --git a/addons/stock/models/stock_quant.py b/addons/stock/models/stock_quant.py
index 15084292a5e..641e3e3f5b4 100644
--- a/addons/stock/models/stock_quant.py
+++ b/addons/stock/models/stock_quant.py
@@ -183,15 +183,17 @@ class StockQuant(models.Model):
max_quantity_on_quant = quant.quantity - quant.reserved_quantity
if max_quantity_on_quant <= 0:
continue
+ max_quantity_on_quant = min(max_quantity_on_quant, quantity)
+ quant.reserved_quantity += max_quantity_on_quant
+ reserved_quants.append((quant, max_quantity_on_quant))
+ quantity -= max_quantity_on_quant
+ available_quantity -= max_quantity_on_quant
else:
- max_quantity_on_quant = quant.reserved_quantity
- max_quantity_on_quant = min(max_quantity_on_quant, quantity)
-
- quant.reserved_quantity += max_quantity_on_quant
- reserved_quants.append((quant, max_quantity_on_quant))
-
- quantity -= max_quantity_on_quant
- available_quantity -= max_quantity_on_quant
+ max_quantity_on_quant = min(quant.reserved_quantity, abs(quantity))
+ quant.reserved_quantity -= max_quantity_on_quant
+ reserved_quants.append((quant, -max_quantity_on_quant))
+ quantity += max_quantity_on_quant
+ available_quantity += max_quantity_on_quant
if quantity == 0 or available_quantity == 0:
break
diff --git a/addons/stock/tests/test_move.py b/addons/stock/tests/test_move.py
index 597945466f4..c08a63a2f8c 100644
--- a/addons/stock/tests/test_move.py
+++ b/addons/stock/tests/test_move.py
@@ -831,6 +831,45 @@ class StockMove(TransactionCase):
self.assertEqual(quants.reserved_quantity, 0.0)
self.assertEqual(len(move1.move_line_ids), 0.0)
+ def test_unreserve_5(self):
+ """ Check the unreservation of a stock move reserved on multiple quants.
+ """
+ # make some stock
+ self.env['stock.quant']._update_available_quantity(self.product1, self.stock_location, 3)
+ self.env['stock.quant'].create({
+ 'product_id': self.product1.id,
+ 'location_id': self.stock_location.id,
+ 'quantity': 2,
+ })
+ self.assertEqual(len(self.env['stock.quant']._gather(self.product1, self.stock_location)), 2)
+ self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product1, self.stock_location), 5)
+
+ # creation
+ move1 = self.env['stock.move'].create({
+ 'name': 'test_unreserve_5',
+ 'location_id': self.stock_location.id,
+ 'location_dest_id': self.customer_location.id,
+ 'product_id': self.product1.id,
+ 'product_uom': self.uom_unit.id,
+ 'product_uom_qty': 5.0,
+ })
+ self.assertEqual(move1.state, 'draft')
+
+ # confirmation
+ move1.action_confirm()
+ self.assertEqual(move1.state, 'confirmed')
+
+ # assignment
+ move1.action_assign()
+ self.assertEqual(move1.state, 'assigned')
+ self.assertEqual(len(move1.move_line_ids), 1)
+ move1.do_unreserve()
+
+ quants = self.env['stock.quant']._gather(self.product1, self.stock_location)
+ self.assertEqual(len(quants), 2.0)
+ for quant in quants:
+ self.assertEqual(quant.reserved_quantity, 0)
+
def test_link_assign_1(self):
""" Test the assignment mechanism when two chained stock moves try to move one unit of an
untracked product.