[FIX] stock, purchase_stock: do not recompute draft, done, cancel moves

Usecase to reproduce:
- Set a product with routes: MTO + Buy
- Create and valide a SO
- Cancel the delivery
- Cancel the RFQ linked

-> The delivery will be switch to confirmed state while it should remain
cancel.

It happens because the button_cancel on purchase.order call
_recompute_state on move. _recompute_state modify the state to confirm,
partially_available or available depending the reservation status.
Howver it should never be call on 'draft', 'cancel' or 'done' moves
since it would modify their state.

A fix would be to filter the set of moves in order to exclude moves that
are cancel, done or draft before using _recompute_state. However this is
easy to forget and the issue would be probably redo in the future.

A more stable fix is to add the filter in the _recompute_state directly.

closes odoo/odoo#42471

Task: 2157543
X-original-commit: 0619415c17dc810aea67890cd3415c3f05dd2290
Signed-off-by: Arnold Moyaux <amoyaux@users.noreply.github.com>
This commit is contained in:
Pratima Gupta
2019-12-30 11:27:07 +00:00
committed by Arnold Moyaux
parent c7b9602165
commit e901dfe466
2 changed files with 48 additions and 1 deletions
@@ -246,3 +246,48 @@ class TestMoveCancelPropagation(PurchaseTestCommon):
self.assertNotEqual(pick.state, 'cancel')
self.assertNotEqual(pack.state, 'cancel')
self.assertNotEqual(self.picking_out.state, 'cancel')
def test_cancel_move_lines_operation(self):
"""Check for done and cancelled moves. Ensure that the RFQ cancellation
will not impact the delivery state if it's already cancelled.
"""
stock_location = self.env['ir.model.data'].xmlid_to_object('stock.stock_location_stock')
customer_location = self.env['ir.model.data'].xmlid_to_object('stock.stock_location_customers')
picking_type_out = self.env['ir.model.data'].xmlid_to_object('stock.picking_type_out')
partner = self.env['res.partner'].create({
'name': 'Steve'
})
seller = self.env['product.supplierinfo'].create({
'name': partner.id,
'price': 10.0,
})
product_car = self.env['product.product'].create({
'name': 'Car',
'type': 'product',
'route_ids': [(4, self.ref('stock.route_warehouse0_mto')), (4, self.ref('purchase_stock.route_warehouse0_buy'))],
'seller_ids': [(6, 0, [seller.id])],
'categ_id': self.env.ref('product.product_category_all').id,
})
customer_picking = self.env['stock.picking'].create({
'location_id': stock_location.id,
'location_dest_id': customer_location.id,
'partner_id': partner.id,
'picking_type_id': picking_type_out.id,
})
customer_move = self.env['stock.move'].create({
'name': 'move out',
'location_id': stock_location.id,
'location_dest_id': customer_location.id,
'product_id': product_car.id,
'product_uom': product_car.uom_id.id,
'product_uom_qty': 10.0,
'procure_method': 'make_to_order',
'picking_id': customer_picking.id,
})
customer_move._action_confirm()
purchase_order = self.env['purchase.order'].search([('partner_id', '=', partner.id)])
customer_move._action_cancel()
self.assertEqual(customer_move.state, 'cancel', 'Move should be cancelled')
purchase_order.button_cancel()
self.assertEqual(customer_move.state, 'cancel', 'State of cancelled and done moves should not change.')
+3 -1
View File
@@ -1494,7 +1494,9 @@ class StockMove(models.Model):
def _recompute_state(self):
for move in self:
if move.reserved_availability == move.product_uom_qty:
if move.state in ('cancel', 'done', 'draft'):
continue
elif move.reserved_availability == move.product_uom_qty:
move.state = 'assigned'
elif move.reserved_availability and move.reserved_availability <= move.product_uom_qty:
move.state = 'partially_available'