diff --git a/addons/stock/models/stock_move_line.py b/addons/stock/models/stock_move_line.py index e965ea28d0b..3f966d3e5b1 100644 --- a/addons/stock/models/stock_move_line.py +++ b/addons/stock/models/stock_move_line.py @@ -510,6 +510,8 @@ class StockMoveLine(models.Model): candidate.product_uom_qty = 0.0 else: candidate.unlink() + if float_is_zero(quantity, precision_rounding=rounding): + break else: # split this move line and assign the new part to our extra move quantity_split = float_round( @@ -517,8 +519,6 @@ class StockMoveLine(models.Model): precision_rounding=self.product_uom_id.rounding, rounding_method='UP') candidate.product_uom_qty = self.product_id.uom_id._compute_quantity(quantity_split, candidate.product_uom_id, rounding_method='HALF-UP') - quantity -= quantity_split move_to_recompute_state |= candidate.move_id - if quantity == 0.0: break move_to_recompute_state._recompute_state() diff --git a/addons/stock/tests/test_move.py b/addons/stock/tests/test_move.py index 1ce26f22f1f..9a48f814abe 100644 --- a/addons/stock/tests/test_move.py +++ b/addons/stock/tests/test_move.py @@ -1854,6 +1854,48 @@ class StockMove(TransactionCase): self.assertAlmostEqual(move_pack_cust.reserved_availability, 1.0) self.assertEqual(move_pack_cust.state, 'partially_available') + def test_use_reserved_move_line_1(self): + """ Test that _free_reservation work when quantity is only available on + reserved move lines. + """ + self.env['stock.quant']._update_available_quantity(self.product1, self.stock_location, 10.0) + move1 = self.env['stock.move'].create({ + 'name': 'test_use_unreserved_move_line_1_1', + '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, + }) + move2 = self.env['stock.move'].create({ + 'name': 'test_use_unreserved_move_line_1_1', + '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, + }) + move1._action_confirm() + move1._action_assign() + move2._action_confirm() + move2._action_assign() + move3 = self.env['stock.move'].create({ + 'name': 'test_use_unreserved_move_line_1_1', + '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': 0.0, + 'quantity_done': 1.0, + }) + move3._action_confirm() + move3._action_assign() + move3._action_done() + self.assertEqual(move3.state, 'done') + quant = self.env['stock.quant']._gather(self.product1, self.stock_location) + self.assertEqual(quant.quantity, 9.0) + self.assertEqual(quant.reserved_quantity, 9.0) + def test_use_unreserved_move_line_1(self): """ Test that validating a stock move linked to an untracked product reserved by another one correctly unreserves the other one.