Skip to content

Commit 2e528f1

Browse files
MiquelRForgeFlowWhenrow
authored andcommitted
[FIX] stock: avoid lot required error when scrapping tracked products without picking
When scrapping a tracked product without a lot and without a picking_type_id, `stock.move.line._action_done` raises a UserError requiring a lot/serial number. This happens because the method checks for the absence of both `picking_type_id`, `is_inventory`, and `lot_id`, assuming a lot is always mandatory outside inventory and picking flows. However, scrap operations may occur outside these flows and should not necessarily require a lot, especially when triggered programmatically (e.g. via API or automation), bypassing the form view validation. This commit updates the condition in `_action_done()` to check the context key `is_scrap`, which is already passed in `do_scrap()` via `move.with_context(is_scrap=True)._action_done()`. This allows tracked products to be scrapped without a lot in valid scenarios, without misleadingly assigning a `picking_type_id` to the move. closes odoo#213536 X-original-commit: a14c8dc Signed-off-by: William Henrotin (whe) <[email protected]>
1 parent 06d65f9 commit 2e528f1

File tree

2 files changed

+23
-1
lines changed

2 files changed

+23
-1
lines changed

addons/stock/models/stock_move_line.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -621,7 +621,7 @@ def _action_done(self):
621621
if ml.product_id.tracking == 'none':
622622
continue
623623
picking_type_id = ml.move_id.picking_type_id
624-
if not picking_type_id and not ml.is_inventory and not ml.lot_id:
624+
if not picking_type_id and not ml.is_inventory and not ml.lot_id and not ml.move_id.scrap_id:
625625
ml_ids_tracked_without_lot.add(ml.id)
626626
continue
627627
if not picking_type_id or ml.lot_id or (not picking_type_id.use_create_lots and not picking_type_id.use_existing_lots):

addons/stock/tests/test_stock_flow.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2251,6 +2251,28 @@ def test_stock_move_with_partner_id(self):
22512251
picking.write({'partner_id': partner_2.id})
22522252
self.assertEqual(picking.move_ids.partner_id, partner_2)
22532253

2254+
def test_scrap_tracked_product_without_lot(self):
2255+
"""Scrapping a tracked product without lot should not raise
2256+
if is_scrap context is set."""
2257+
stock_location = self.StockLocationObj.browse(self.stock_location)
2258+
tracked_product = self.env['product.product'].create({
2259+
'name': 'Tracked Product',
2260+
'type': 'consu',
2261+
'is_storable': True,
2262+
'tracking': 'lot',
2263+
})
2264+
self.env['stock.quant']._update_available_quantity(tracked_product, stock_location, 1.0)
2265+
2266+
scrap = self.env['stock.scrap'].create({
2267+
'product_id': tracked_product.id,
2268+
'product_uom_id': tracked_product.uom_id.id,
2269+
'location_id': self.stock_location,
2270+
'scrap_qty': 1.0,
2271+
})
2272+
scrap.do_scrap()
2273+
2274+
self.assertEqual(scrap.move_ids.state, 'done')
2275+
22542276
def test_cancel_picking_with_scrapped_products(self):
22552277
"""
22562278
The user scraps some products of a picking, then cancel this picking

0 commit comments

Comments
 (0)