[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.
This commit is contained in:
Pierre Masereel
2017-07-26 17:23:55 +02:00
committed by Simon Lejeune
parent 2a0b158d44
commit 8a497cdd5f
2 changed files with 49 additions and 8 deletions
+10 -8
View File
@@ -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
+39
View File
@@ -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.