[FIX] stock: cancel picking with scrapped SM
Cancelling a picking with scrapped and done SM will cancel this SM too. To reproduce the issue: 1. In Settings, enable "Storage Locations" 2. Create a storable product P 3. Update the quantity of P: 10 in WH/Stock 4. Create a planned delivery order DO with 2 x P 5. Mark DO as todo, Check availability 6. Scrap 2 x P 7. Cancel DO 8. Open the SM of the scrapping Error: The SM is cancelled. This is incorrect: the move was done, so there is a quant with 2 x P in scrap location. There is now an incoherence between quants and SMs report. OPW-2805604 closes odoo/odoo#89987 X-original-commit: bd3324acc3ec227438d2cb25a1df1e0fca2a2789 Signed-off-by: Arnold Moyaux <arm@odoo.com> Signed-off-by: Adrien Widart <awt@odoo.com>
This commit is contained in:
@@ -1565,7 +1565,7 @@ class StockMove(models.Model):
|
||||
def _action_cancel(self):
|
||||
if any(move.state == 'done' and not move.scrapped for move in self):
|
||||
raise UserError(_('You cannot cancel a stock move that has been set to \'Done\'. Create a return in order to reverse the moves which took place.'))
|
||||
moves_to_cancel = self.filtered(lambda m: m.state != 'cancel')
|
||||
moves_to_cancel = self.filtered(lambda m: m.state != 'cancel' and not (m.state == 'done' and m.scrapped))
|
||||
# self cannot contain moves that are either cancelled or done, therefore we can safely
|
||||
# unlink all associated move_line_ids
|
||||
moves_to_cancel._do_unreserve()
|
||||
@@ -1580,7 +1580,7 @@ class StockMove(models.Model):
|
||||
if all(state in ('done', 'cancel') for state in siblings_states):
|
||||
move.move_dest_ids.write({'procure_method': 'make_to_stock'})
|
||||
move.move_dest_ids.write({'move_orig_ids': [(3, move.id, 0)]})
|
||||
self.write({
|
||||
moves_to_cancel.write({
|
||||
'state': 'cancel',
|
||||
'move_orig_ids': [(5, 0, 0)],
|
||||
'procure_method': 'make_to_stock',
|
||||
|
||||
@@ -523,7 +523,7 @@ class Picking(models.Model):
|
||||
'''
|
||||
picking_moves_state_map = defaultdict(dict)
|
||||
picking_move_lines = defaultdict(set)
|
||||
for move in self.env['stock.move'].search([('picking_id', 'in', self.ids)]):
|
||||
for move in self.env['stock.move'].search([('picking_id', 'in', self.ids), ('scrapped', '=', False)]):
|
||||
picking_id = move.picking_id
|
||||
move_state = move.state
|
||||
picking_moves_state_map[picking_id.id].update({
|
||||
|
||||
@@ -2180,3 +2180,43 @@ class TestStockFlow(TestStockCommon):
|
||||
|
||||
picking.write({'partner_id': partner_2.id})
|
||||
self.assertEqual(picking.move_ids.partner_id, partner_2)
|
||||
|
||||
def test_cancel_picking_with_scrapped_products(self):
|
||||
"""
|
||||
The user scraps some products of a picking, then cancel this picking
|
||||
The test ensures that the scrapped SM is not cancelled
|
||||
"""
|
||||
stock_location = self.env['stock.location'].browse(self.stock_location)
|
||||
self.env['stock.quant']._update_available_quantity(self.productA, stock_location, 10)
|
||||
|
||||
picking = self.env['stock.picking'].create({
|
||||
'picking_type_id': self.picking_type_out,
|
||||
'location_id': self.supplier_location,
|
||||
'location_dest_id': self.stock_location,
|
||||
})
|
||||
move = self.env['stock.move'].create({
|
||||
'name': self.productA.name,
|
||||
'product_id': self.productA.id,
|
||||
'product_uom_qty': 1,
|
||||
'product_uom': self.productA.uom_id.id,
|
||||
'picking_id': picking.id,
|
||||
'location_id': self.supplier_location,
|
||||
'location_dest_id': self.stock_location,
|
||||
})
|
||||
|
||||
picking.action_confirm()
|
||||
picking.action_assign()
|
||||
|
||||
scrap = self.env['stock.scrap'].create({
|
||||
'picking_id': picking.id,
|
||||
'product_id': self.productA.id,
|
||||
'product_uom_id': self.productA.uom_id.id,
|
||||
'scrap_qty': 1.0,
|
||||
})
|
||||
scrap.do_scrap()
|
||||
|
||||
picking.action_cancel()
|
||||
|
||||
self.assertEqual(picking.state, 'cancel')
|
||||
self.assertEqual(move.state, 'cancel')
|
||||
self.assertEqual(scrap.move_id.state, 'done')
|
||||
|
||||
Reference in New Issue
Block a user