Sometimes users make mistakes, and they realize it after delivering it.
So i choosed the follwing process to do the reverse picking process :
Make an automatic return, by creating reverse stock move, for example if I deliver a quantity to a client, source would be "mystock" and destination would be "client location", so the follwing method will create a reverse stock move from the "client locations" to "mystock", and the confirm this stock move, and it will be on the done state.
Here after the methode suggested :
class StockPickingOut(orm.Model):
_inherit = 'stock.picking.out'
_name = 'stock.picking.out'
def cancel_delivery(self, cr, uid, ids, context=None):
move_pool = self.pool.get('account.move')
stock_pool = self.pool.get('stock.move')
date_cur = time.strftime('%Y-%m-%d %H:%M:%S')
uom_obj = self.pool.get('product.uom')
wf_service = netsvc.LocalService("workflow")
moves = []
for delivery in self.browse(cr,uid,ids,context):for move_line in delivery.move_lines:
# changer l etat
stock_pool.write(cr, uid, move_line.id, {'state':'draft'})
# creer mouvement inverse
new_location = move_line.location_dest_id.id
new_move=stock_pool.copy(cr, uid, move_line.id, {
'picking_id': '',
'partner_id': '',
'type': 'in',
'product_qty': move_line.product_qty,
'product_uos_qty': uom_obj._compute_qty(cr, uid, move_line.product_uom.id, move_line.product_qty, move_line.product_uos.id),
'state': 'draft',
'location_id': new_location,
'location_dest_id': move_line.location_id.id,
'date': date_cur,
})
#valider mouvement inverse
moves.append(new_move)
stock_pool.action_done(cr,uid,moves)
self.write(cr,uid,ids,{'state':'confirmed'})
return True
The problem is when I verify the returned quantities to mystock, i found that the last line of stock move is returned twice, I don't know why. For example if I expect for 3 products the following returned quantities :
P1 : Q1/ P2: Q2 / P3: Q3 I'm getting : P1 : Q1/ P2: Q2 / P3: Q3*2 The problem is always with the last line of the stock move lines.
I'll post here the action_done method, maybe you'll find the solution :
def action_done(self, cr, uid, ids, context=None):
""" Makes the move done and if all moves are done, it will finish the picking.
@return:
"""
picking_ids = []
move_ids = []
wf_service = netsvc.LocalService("workflow")
if context is None:
context = {}todo = []
for move in self.browse(cr, uid, ids, context=context):
if move.state=="draft":
todo.append(move.id)
if todo:
self.action_confirm(cr, uid, todo, context=context)
todo = []for move in self.browse(cr, uid, ids, context=context):
if move.state in ['done','cancel']:
continue
move_ids.append(move.id)if move.picking_id:
picking_ids.append(move.picking_id.id)
if move.move_dest_id.id and (move.state != 'done'):
# Downstream move should only be triggered if this move is the last pending upstream move
other_upstream_move_ids = self.search(cr, uid, [('id','!=',move.id),('state','not in',['done','cancel']),
('move_dest_id','=',move.move_dest_id.id)], context=context)
if not other_upstream_move_ids:
self.write(cr, uid, [move.id], {'move_history_ids': [(4, move.move_dest_id.id)]})
if move.move_dest_id.state in ('waiting', 'confirmed'):
self.force_assign(cr, uid, [move.move_dest_id.id], context=context)
if move.move_dest_id.picking_id:
wf_service.trg_write(uid, 'stock.picking', move.move_dest_id.picking_id.id, cr)
if move.move_dest_id.auto_validate:
self.action_done(cr, uid, [move.move_dest_id.id], context=context)self._create_product_valuation_moves(cr, uid, move, context=context)
if move.state not in ('confirmed','done','assigned'):
todo.append(move.id)if todo:
self.action_confirm(cr, uid, todo, context=context)self.write(cr, uid, move_ids, {'state': 'done', 'date': time.strftime(DEFAULT_SERVER_DATETIME_FORMAT)}, context=context)
for id in move_ids:
wf_service.trg_trigger(uid, 'stock.move', id, cr)for pick_id in picking_ids:
wf_service.trg_write(uid, 'stock.picking', pick_id, cr)return True
Any suggestions will be welcome.
Thanks.
If you cancel a delivery order, and there are many other delivery and picking orders created after it, it will cause the incorrect standard_price value if average or real price methods are used.