summaryrefslogtreecommitdiff
path: root/addons
diff options
context:
space:
mode:
Diffstat (limited to 'addons')
-rw-r--r--addons/stock/models/stock_move.py17
-rw-r--r--addons/stock/tests/test_move.py53
2 files changed, 63 insertions, 7 deletions
diff --git a/addons/stock/models/stock_move.py b/addons/stock/models/stock_move.py
index c5375658518..bb0dd9366fc 100644
--- a/addons/stock/models/stock_move.py
+++ b/addons/stock/models/stock_move.py
@@ -865,11 +865,6 @@ class StockMove(models.Model):
package_id=package_id, owner_id=owner_id, strict=strict
)
except UserError:
- # If it raises here, it means that the `available_quantity` brought by a done move line
- # is not available on the quants itself. This could be the result of an inventory
- # adjustment that removed totally of partially `available_quantity`. When this happens, we
- # chose to do nothing. This situation could not happen on MTS move, because in this case
- # `available_quantity` is directly the quantity on the quants themselves.
taken_quantity = 0
# Find a candidate move line to update or create a new one.
@@ -985,7 +980,17 @@ class StockMove(models.Model):
available_move_lines[(move_line.location_id, move_line.lot_id, move_line.result_package_id, move_line.owner_id)] -= move_line.product_qty
for (location_id, lot_id, package_id, owner_id), quantity in available_move_lines.items():
need = move.product_qty - sum(move.move_line_ids.mapped('product_qty'))
- taken_quantity = move._update_reserved_quantity(need, quantity, location_id, lot_id, package_id, owner_id)
+ # `quantity` is what is brought by chained done move lines. We double check
+ # here this quantity is available on the quants themselves. If not, this
+ # could be the result of an inventory adjustment that removed totally of
+ # partially `quantity`. When this happens, we chose to reserve the maximum
+ # still available. This situation could not happen on MTS move, because in
+ # this case `quantity` is directly the quantity on the quants themselves.
+ available_quantity = self.env['stock.quant']._get_available_quantity(
+ move.product_id, location_id, lot_id=lot_id, package_id=package_id, owner_id=owner_id, strict=True)
+ if float_is_zero(available_quantity, precision_rounding=move.product_id.uom_id.rounding):
+ continue
+ taken_quantity = move._update_reserved_quantity(need, min(quantity, available_quantity), location_id, lot_id, package_id, owner_id)
if float_is_zero(taken_quantity, precision_rounding=move.product_id.uom_id.rounding):
continue
if need - taken_quantity == 0.0:
diff --git a/addons/stock/tests/test_move.py b/addons/stock/tests/test_move.py
index 53948b477f9..8025cf4a13c 100644
--- a/addons/stock/tests/test_move.py
+++ b/addons/stock/tests/test_move.py
@@ -1751,7 +1751,7 @@ class StockMove(TransactionCase):
ml.qty_done = 1
res_dict_for_back_order = picking_pack_cust.button_validate()
backorder_wizard = self.env[(res_dict_for_back_order.get('res_model'))].browse(res_dict_for_back_order.get('res_id'))
- backorder_wizard.with_context(debug=True).process()
+ backorder_wizard.process()
backorder = self.env['stock.picking'].search([('backorder_id', '=', picking_pack_cust.id)])
backordered_move = backorder.move_lines
@@ -1782,6 +1782,57 @@ class StockMove(TransactionCase):
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product2, self.customer_location), 3)
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product2, self.pack_location), 0)
+ def test_link_assign_10(self):
+ """ Test the assignment mechanism with partial availability.
+ """
+ # make some stock:
+ # stock location: 2.0
+ # pack location: -1.0
+ self.env['stock.quant']._update_available_quantity(self.product1, self.stock_location, 2.0)
+ self.assertEqual(len(self.env['stock.quant']._gather(self.product1, self.stock_location)), 1.0)
+
+ move_out = self.env['stock.move'].create({
+ 'name': 'test_link_assign_out',
+ 'location_id': self.pack_location.id,
+ 'location_dest_id': self.customer_location.id,
+ 'product_id': self.product1.id,
+ 'product_uom': self.uom_unit.id,
+ 'product_uom_qty': 1.0,
+ })
+ move_out._action_confirm()
+ move_out._action_assign()
+ move_out.quantity_done = 1.0
+ move_out._action_done()
+ self.assertEqual(len(self.env['stock.quant']._gather(self.product1, self.pack_location)), 1.0)
+
+ move_stock_pack = self.env['stock.move'].create({
+ 'name': 'test_link_assign_1_1',
+ 'location_id': self.stock_location.id,
+ 'location_dest_id': self.pack_location.id,
+ 'product_id': self.product1.id,
+ 'product_uom': self.uom_unit.id,
+ 'product_uom_qty': 2.0,
+ })
+ move_pack_cust = self.env['stock.move'].create({
+ 'name': 'test_link_assign_1_2',
+ 'location_id': self.pack_location.id,
+ 'location_dest_id': self.customer_location.id,
+ 'product_id': self.product1.id,
+ 'product_uom': self.uom_unit.id,
+ 'product_uom_qty': 2.0,
+ })
+ move_stock_pack.write({'move_dest_ids': [(4, move_pack_cust.id, 0)]})
+ move_pack_cust.write({'move_orig_ids': [(4, move_stock_pack.id, 0)]})
+
+ (move_stock_pack + move_pack_cust)._action_confirm()
+ move_stock_pack._action_assign()
+ move_stock_pack.quantity_done = 2.0
+ move_stock_pack._action_done()
+ self.assertEqual(len(move_pack_cust.move_line_ids), 1)
+
+ self.assertAlmostEqual(move_pack_cust.reserved_availability, 1.0)
+ self.assertEqual(move_pack_cust.state, 'partially_available')
+
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.