diff --git a/addons/stock/models/stock_move.py b/addons/stock/models/stock_move.py index 7ef8306d976..b6fa82a3b19 100644 --- a/addons/stock/models/stock_move.py +++ b/addons/stock/models/stock_move.py @@ -466,14 +466,7 @@ class StockMove(models.Model): def _do_unreserve(self): if any(move.state in ('done', 'cancel') for move in self): raise UserError(_('Cannot unreserve a done move')) - for move in self: - move.move_line_ids.unlink() - if move.procure_method == 'make_to_order' and not move.move_orig_ids: - move.state = 'waiting' - elif move.move_orig_ids and not all(orig.state in ('done', 'cancel') for orig in move.move_orig_ids): - move.state = 'waiting' - else: - move.state = 'confirmed' + self.mapped('move_line_ids').unlink() return True def _push_apply(self): @@ -1136,7 +1129,9 @@ class StockMove(models.Model): elif move.reserved_availability and move.reserved_availability <= move.product_uom_qty: move.state = 'partially_available' else: - if move.move_orig_ids: + if move.procure_method == 'make_to_order' and not move.move_orig_ids: + move.state = 'waiting' + elif move.move_orig_ids and not all(orig.state in ('done', 'cancel') for orig in move.move_orig_ids): move.state = 'waiting' else: move.state = 'confirmed' diff --git a/addons/stock/models/stock_move_line.py b/addons/stock/models/stock_move_line.py index c5d712b8bc4..ba9383473ef 100644 --- a/addons/stock/models/stock_move_line.py +++ b/addons/stock/models/stock_move_line.py @@ -348,7 +348,11 @@ class StockMoveLine(models.Model): if ml.product_id.type == 'product' and not ml.location_id.should_bypass_reservation() and not float_is_zero(ml.product_qty, precision_digits=precision): self.env['stock.quant']._update_reserved_quantity(ml.product_id, ml.location_id, -ml.product_qty, lot_id=ml.lot_id, package_id=ml.package_id, owner_id=ml.owner_id, strict=True) - return super(StockMoveLine, self).unlink() + moves = self.mapped('move_id') + res = super(StockMoveLine, self).unlink() + if moves: + moves._recompute_state() + return res def _action_done(self): """ This method is called during a move's `action_done`. It'll actually move a quant from diff --git a/addons/stock/tests/test_move2.py b/addons/stock/tests/test_move2.py index 30868ec2dae..43a92522339 100644 --- a/addons/stock/tests/test_move2.py +++ b/addons/stock/tests/test_move2.py @@ -608,6 +608,45 @@ class TestPickShip(TestStockCommon): picking_client.action_confirm() self.assertEqual(len(picking_client.move_lines), 2, 'Moves should not be merged') + def test_mto_cancel_move_line(self): + """ Create a pick ship situation. Then process the pick picking + with a backorder. Then try to unlink the move line created on + the ship and check if the picking and move state are updated. + Then validate the backorder and unlink the ship move lines in + order to check again if the picking and state are updated. + """ + picking_pick, picking_client = self.create_pick_ship() + location = self.env['stock.location'].browse(self.stock_location) + + # make some stock + self.env['stock.quant']._update_available_quantity(self.productA, location, 10.0) + picking_pick.move_lines.quantity_done = 5.0 + backorder_wizard_values = picking_pick.button_validate() + backorder_wizard = self.env[(backorder_wizard_values.get('res_model'))].browse(backorder_wizard_values.get('res_id')) + backorder_wizard.process() + + self.assertTrue(picking_client.move_line_ids, 'A move line should be created.') + self.assertEqual(picking_client.move_line_ids.product_uom_qty, 5, 'The move line should have 5 unit reserved.') + + # Directly delete the move lines on the picking. (Use show detail operation on picking type) + # Should do the same behavior than unreserve + picking_client.move_line_ids.unlink() + + self.assertEqual(picking_client.move_lines.state, 'waiting', 'The move state should be waiting since nothing is reserved and another origin move still in progess.') + self.assertEqual(picking_client.state, 'waiting', 'The picking state should not be ready anymore.') + + picking_client.action_assign() + + back_order = self.env['stock.picking'].search([('backorder_id', '=', picking_pick.id)]) + back_order.move_lines.quantity_done = 5 + back_order.button_validate() + + self.assertEqual(picking_client.move_lines.reserved_availability, 10, 'The total quantity should be reserved since everything is available.') + picking_client.move_line_ids.unlink() + + self.assertEqual(picking_client.move_lines.state, 'confirmed', 'The move should be confirmed since all the origin moves are processed.') + self.assertEqual(picking_client.state, 'confirmed', 'The picking should be confirmed since all the moves are confirmed.') + class TestSinglePicking(TestStockCommon): def test_backorder_1(self): diff --git a/addons/stock/tests/test_stock_flow.py b/addons/stock/tests/test_stock_flow.py index d625d9227f9..022e319f95f 100644 --- a/addons/stock/tests/test_stock_flow.py +++ b/addons/stock/tests/test_stock_flow.py @@ -1796,6 +1796,6 @@ class TestStockFlow(TestStockCommon): move_with_ancestors._do_unreserve() other_move._do_unreserve() - self.assertEquals(move_mto_alone.state, "waiting") + self.assertEquals(move_mto_alone.state, "draft") self.assertEquals(move_with_ancestors.state, "waiting") self.assertEquals(other_move.state, "confirmed")