[FIX] stock: immediate transfer

Create an immediate transfer for a receipt, add a move, set a quantity
done and due to rev[0], an initial demand is set, then
_autoconfirm_picking is called and action_confirm of picking calls
_action_assign if the location source bypasses the reservation. Set
again an inferior qty_done, the initial demand is also updated due to
rev[0] and somehow the system tries to write on a now unlinked move
line.

fixes
- never reserve an immediate transfer
- never update the initial demand if the move is reserved to fix the
existing databases.
- adapt _compute_state so that immediate transfer moves considered
reserved so that they're always "ready"
- adapt the test that was working on an immediate transfer picking and
setting the initial demand while it's not possible through the
interface, the user can only set the done quantity.

[0] 8303b1a

closes odoo/odoo#45317

X-original-commit: 357e0a862744f1bc23a9643a1822d2ee4a2eb7a2
Signed-off-by: Simon Lejeune (sle) <sle@openerp.com>
This commit is contained in:
fw-bot
2020-02-17 14:55:04 +00:00
committed by Simon Lejeune
parent 260b6f0731
commit 0494e6763f
4 changed files with 11 additions and 8 deletions
+2 -1
View File
@@ -347,7 +347,8 @@ class StockMoveLine(models.Model):
# done stock move should have its `quantity_done` equals to its `product_uom_qty`, and
# this is what move's `action_done` will do. So, we replicate the behavior here.
if updates or 'qty_done' in vals:
moves = self.filtered(lambda ml: ml.move_id.state == 'done' or ml.move_id.picking_id and ml.move_id.picking_id.immediate_transfer).mapped('move_id')
moves = self.filtered(lambda ml: ml.move_id.state == 'done').mapped('move_id')
moves |= self.filtered(lambda ml: ml.move_id.state not in ('done', 'cancel') and ml.move_id.picking_id.immediate_transfer and not ml.product_uom_qty).mapped('move_id')
for move in moves:
move.product_uom_qty = move.quantity_done
next_moves._do_unreserve()
+5 -3
View File
@@ -427,7 +427,7 @@ class Picking(models.Model):
]
})
@api.depends('move_type', 'move_lines.state', 'move_lines.picking_id')
@api.depends('move_type', 'immediate_transfer', 'move_lines.state', 'move_lines.picking_id')
def _compute_state(self):
''' State of a picking depends on the state of its related stock.move
- Draft: only used for "planned pickings"
@@ -452,7 +452,9 @@ class Picking(models.Model):
picking.state = 'done'
else:
relevant_move_state = picking.move_lines._get_relevant_state_among_moves()
if relevant_move_state == 'partially_available':
if picking.immediate_transfer and relevant_move_state not in ('draft', 'cancel', 'done'):
picking.state = 'assigned'
elif relevant_move_state == 'partially_available':
picking.state = 'assigned'
else:
picking.state = relevant_move_state
@@ -656,7 +658,7 @@ class Picking(models.Model):
.filtered(lambda move: move.state == 'draft')\
._action_confirm()
# call `_action_assign` on every confirmed move which location_id bypasses the reservation
self.filtered(lambda picking: picking.location_id.usage in ('supplier', 'inventory', 'production') and picking.state == 'confirmed')\
self.filtered(lambda picking: not picking.immediate_transfer and picking.location_id.usage in ('supplier', 'inventory', 'production') and picking.state == 'confirmed')\
.mapped('move_lines')._action_assign()
return True
+2 -2
View File
@@ -88,8 +88,8 @@ SELECT
ELSE date::date - interval '1 day'
END, '1 day'::interval)::date date,
CASE
WHEN (whs.id IS NOT NULL AND whd.id IS NULL) OR ls.usage = 'transit' AND m.state = 'done' THEN product_qty
WHEN (whs.id IS NULL AND whd.id IS NOT NULL) OR ld.usage = 'transit' AND m.state = 'done' THEN -product_qty
WHEN ((whs.id IS NOT NULL AND whd.id IS NULL) OR ls.usage = 'transit') AND m.state = 'done' THEN product_qty
WHEN ((whs.id IS NULL AND whd.id IS NOT NULL) OR ld.usage = 'transit') AND m.state = 'done' THEN -product_qty
WHEN (whs.id IS NOT NULL AND whd.id IS NULL) OR ls.usage = 'transit' THEN -product_qty
WHEN (whs.id IS NULL AND whd.id IS NOT NULL) OR ld.usage = 'transit' THEN product_qty
END AS product_qty,
+2 -2
View File
@@ -4277,12 +4277,12 @@ class StockMove(SavepointCase):
'location_dest_id': self.stock_location.id,
'product_id': self.product.id,
'product_uom': self.uom_unit.id,
'product_uom_qty': 10.0,
'quantity_done': 10.0,
'picking_id': picking.id,
})
picking._autoconfirm_picking()
self.assertEqual(picking.state, 'assigned')
move1.product_uom_qty = 12
move1.quantity_done = 12
self.assertEqual(picking.state, 'assigned')
def test_initial_demand_4(self):