[FIX] stock: unlink move line don't update move state

Use case to reproduce:
- Go for a delivery order and use show detailed operations mode
- Have something reserved on a picking
- Manually delete the stock.move.line
-> The move state is not adapted to the new state of the stock move lines

It happens because the move state is not computed not
update on the move line unlink method.

This commit use the existing move function in order
to compute the state and add a test.

A part of test_stock_flow_74 is updated. Since procurement
refactoring make a move mto and confirm it will not work
since purchase or mrp are not install (Usererror). Also do an unreserve
on a draft move is not a real use case and should not pass
it in waiting since moves orig are never created.
This commit is contained in:
Arnold Moyaux
2017-12-12 14:55:55 +01:00
parent 96c3001f0e
commit 81e983443c
4 changed files with 49 additions and 11 deletions
+4 -9
View File
@@ -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'
+5 -1
View File
@@ -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
+39
View File
@@ -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):
+1 -1
View File
@@ -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")