Skip to content

Commit bf41a93

Browse files
committed
[IMP] stock_picking_operation_loss_quantity: cancel loss reservation on inventory
When an inventory is validated, we need to cancel any remaining pending moves created to make the quantity no more available in case of loss declaration.
1 parent dff9c13 commit bf41a93

File tree

5 files changed

+78
-11
lines changed

5 files changed

+78
-11
lines changed

stock_picking_operation_loss_quantity/models/stock_move_line.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,9 +106,11 @@ def _prepare_values_for_loss_movement(self, group_key):
106106
"reserved_uom_qty": loss_quantity,
107107
"product_id": group_key.product_id.id,
108108
"picking_type_id": pick_type_id.id,
109+
"package_id": group_key.package_id.id,
109110
"location_id": group_key.location_id.id,
110111
"location_dest_id": pick_type_id.default_location_dest_id.id,
111112
"lot_id": group_key.lot_id.id,
113+
"owner_id": group_key.owner_id.id,
112114
"origin": "Operator: %s / Pickings: %s"
113115
% (
114116
self.env.user.name,

stock_picking_operation_loss_quantity/models/stock_quant.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,33 @@ def _lock_quants_for_loss(self):
2020
"SELECT id FROM stock_quant WHERE id in %s FOR UPDATE NOWAIT",
2121
(tuple(self.ids),),
2222
)
23+
24+
def _apply_inventory(self):
25+
"""When an inventory is validated, we need to cancel any remaining
26+
pending moves created to make the quantity no more available
27+
in case of loss declaration.
28+
"""
29+
moves_to_cancel = self.env["stock.move"]
30+
if self.env.context.get("inventory_mode"):
31+
for quant in self:
32+
loss_picking_type = quant.warehouse_id.loss_type_id
33+
search_domain = [
34+
("reserved_uom_qty", ">", 0.0),
35+
("product_id", "=", quant.product_id.id),
36+
("package_id", "=", quant.package_id.id),
37+
("location_id", "=", quant.location_id.id),
38+
("picking_type_id", "=", loss_picking_type.id),
39+
(
40+
"location_dest_id",
41+
"=",
42+
loss_picking_type.default_location_dest_id.id,
43+
),
44+
("lot_id", "=", quant.lot_id.id),
45+
("owner_id", "=", quant.owner_id.id),
46+
]
47+
lines = self.env["stock.move.line"].search(search_domain)
48+
if lines:
49+
moves_to_cancel |= lines.mapped("move_id")
50+
if moves_to_cancel:
51+
moves_to_cancel._action_cancel()
52+
return super(StockQuant, self)._apply_inventory()

stock_picking_operation_loss_quantity/tests/common.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,13 +151,16 @@ def initiate_values_no_tracking(cls):
151151
cls._create_quantities(cls.product_3, 5.0)
152152

153153
@classmethod
154-
def _create_quantities(cls, product, quantity, location=None, lot=None):
154+
def _create_quantities(
155+
cls, product, quantity, location=None, lot=None, package=None
156+
):
155157
cls.quant_obj.with_context(inventory_mode=True).create(
156158
{
157159
"product_id": product.id,
158160
"inventory_quantity": quantity,
159161
"location_id": location.id if location else cls.location.id,
160162
"lot_id": lot.id if lot else False,
163+
"package_id": package.id if package else False,
161164
}
162165
)._apply_inventory()
163166

stock_picking_operation_loss_quantity/tests/test_picking_operation_loss.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,17 @@ def test_loss_line_no_tracking(self):
9696
self.assertTrue(loss_pickings.activity_ids)
9797
self.assertEqual(self.user_demo, loss_pickings.activity_user_id)
9898

99+
# make an inventory adjustment and check that the loss picking is now
100+
# cancelled
101+
self._create_quantities(
102+
new_line_2.product_id,
103+
new_line_2.reserved_uom_qty,
104+
location=new_line_2.location_id,
105+
lot=new_line_2.lot_id,
106+
package=new_line_2.package_id,
107+
)
108+
self.assertEqual(loss_pickings.state, "cancel")
109+
99110
def test_loss_line_no_tracking_multi(self):
100111
"""
101112
Product 2: 1.0 quantity done (demand 6.0)

stock_picking_operation_loss_quantity/tests/test_picking_operation_loss_tracking.py

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -37,17 +37,27 @@ def test_loss_line_tracking(self):
3737
loss_pickings = self._get_loss_pickings()
3838

3939
self.assertEqual(1, len(loss_pickings))
40-
line = loss_pickings.move_line_ids.filtered(
40+
loss_line_lot_a = loss_pickings.move_line_ids.filtered(
4141
lambda line: line.lot_id == self.product_1_lotA
4242
)
43-
self.assertTrue(line)
44-
self.assertEqual(line.state, "assigned")
45-
self.assertEqual(line.reserved_uom_qty, 2)
43+
self.assertTrue(loss_line_lot_a)
44+
self.assertEqual(loss_line_lot_a.state, "assigned")
45+
self.assertEqual(loss_line_lot_a.reserved_uom_qty, 2)
4646

47-
line = loss_pickings.move_line_ids.filtered(
47+
loss_line_lot_b = loss_pickings.move_line_ids.filtered(
4848
lambda line: line.lot_id == self.product_1_lotB
4949
)
50-
self.assertFalse(line)
50+
self.assertFalse(loss_line_lot_b)
51+
# make an inventory adjustment and check that the loss picking is now
52+
# cancelled
53+
self._create_quantities(
54+
loss_line_lot_a.product_id,
55+
loss_line_lot_a.reserved_uom_qty,
56+
location=loss_line_lot_a.location_id,
57+
lot=loss_line_lot_a.lot_id,
58+
package=loss_line_lot_a.package_id,
59+
)
60+
self.assertEqual(loss_pickings.state, "cancel")
5161

5262
def test_loss_line_tracking_with_pack(self):
5363
"""
@@ -95,14 +105,25 @@ def test_loss_line_tracking_with_pack(self):
95105
loss_pickings = self._get_loss_pickings()
96106

97107
self.assertEqual(1, len(loss_pickings))
98-
line = loss_pickings.move_line_ids.filtered(
108+
loss_line_lot_a = loss_pickings.move_line_ids.filtered(
99109
lambda line: line.lot_id == self.product_1_lotA
100110
)
101-
self.assertTrue(line)
102-
self.assertEqual(line.state, "assigned")
103-
self.assertEqual(line.reserved_uom_qty, 2)
111+
self.assertTrue(loss_line_lot_a)
112+
self.assertEqual(loss_line_lot_a.state, "assigned")
113+
self.assertEqual(loss_line_lot_a.reserved_uom_qty, 2)
104114

105115
line = loss_pickings.move_line_ids.filtered(
106116
lambda line: line.lot_id == self.product_1_lotB
107117
)
108118
self.assertFalse(line)
119+
120+
# make an inventory adjustment and check that the loss picking is now
121+
# cancelled
122+
self._create_quantities(
123+
loss_line_lot_a.product_id,
124+
loss_line_lot_a.reserved_uom_qty,
125+
location=loss_line_lot_a.location_id,
126+
lot=loss_line_lot_a.lot_id,
127+
package=loss_line_lot_a.package_id,
128+
)
129+
self.assertEqual(loss_pickings.state, "cancel")

0 commit comments

Comments
 (0)