[FIX] stock: state change tracking

The `stock.picking`.`state` field is set
to track the change of values
(`track_visibility='onchange'`)

It's supposed to write the state changes
within the picking thread.

It does not work properly for function fields,
as the onchange tracking is designed to work
only with direct user changes, direct
`write` operations on the record, while,
here, the state value changes according to the
picking moves changes, for instance.

To solve this, the tracking changes have to be
hooked within the `create` & `write` methods
of the model on which this function depends on.

Therefore, from now, when changes are
performed in the moves, on the fields that
could lead to the picking state change, we
force the tracking of the picking state.

In addition, we had the `mail_notrack` key
in the context when creating back orders,
to avoid displaying the back and forths
in the state
e.g. when transferring 9 units on 10, the
changes were displayed as below:
Draft -> Waiting availability
Waiting Availability -> Ready to Transfer
Ready to Transfer -> Draft
Draft -> Partially available
Partially Available -> Waiting availability
Waiting Availability -> Transferred

opw-666317
This commit is contained in:
Denis Ledoux 2016-01-20 12:29:50 +01:00
parent c0571d4066
commit d349584f9d
1 changed files with 32 additions and 5 deletions

View File

@ -1435,6 +1435,7 @@ class stock_picking(osv.osv):
"""
if not context:
context = {}
notrack_context = dict(context, mail_notrack=True)
stock_move_obj = self.pool.get('stock.move')
for picking in self.browse(cr, uid, picking_ids, context=context):
if not picking.pack_operation_ids:
@ -1461,7 +1462,7 @@ class stock_picking(osv.osv):
todo_move_ids.append(move.id)
elif float_compare(remaining_qty,0, precision_rounding = move.product_id.uom_id.rounding) > 0 and \
float_compare(remaining_qty, move.product_qty, precision_rounding = move.product_id.uom_id.rounding) < 0:
new_move = stock_move_obj.split(cr, uid, move, remaining_qty, context=context)
new_move = stock_move_obj.split(cr, uid, move, remaining_qty, context=notrack_context)
todo_move_ids.append(move.id)
#Assign move as it was assigned before
toassign_move_ids.append(new_move)
@ -1470,7 +1471,7 @@ class stock_picking(osv.osv):
self.rereserve_quants(cr, uid, picking, move_ids=todo_move_ids, context=context)
self.do_recompute_remaining_quantities(cr, uid, [picking.id], context=context)
if todo_move_ids and not context.get('do_only_split'):
self.pool.get('stock.move').action_done(cr, uid, todo_move_ids, context=context)
self.pool.get('stock.move').action_done(cr, uid, todo_move_ids, context=notrack_context)
elif context.get('do_only_split'):
context = dict(context, split=todo_move_ids)
self._create_backorder(cr, uid, picking, context=context)
@ -1978,14 +1979,29 @@ class stock_move(osv.osv):
res.append(self._create_procurement(cr, uid, move, context=context))
return res
def create(self, cr, uid, vals, context=None):
if context is None:
context = {}
picking_obj = self.pool['stock.picking']
track = not context.get('mail_notrack') and vals.get('picking_id')
if track:
picking = picking_obj.browse(cr, uid, vals['picking_id'], context=context)
initial_values = {picking.id: {'state': picking.state}}
res = super(stock_move, self).create(cr, uid, vals, context=context)
if track:
picking_obj.message_track(cr, uid, [vals['picking_id']], picking_obj.fields_get(cr, uid, ['state'], context=context), initial_values, context=context)
return res
def write(self, cr, uid, ids, vals, context=None):
if context is None:
context = {}
if isinstance(ids, (int, long)):
ids = [ids]
picking_obj = self.pool['stock.picking']
# Check that we do not modify a stock.move which is done
frozen_fields = set(['product_qty', 'product_uom', 'product_uos_qty', 'product_uos', 'location_id', 'location_dest_id', 'product_id'])
for move in self.browse(cr, uid, ids, context=context):
moves = self.browse(cr, uid, ids, context=context)
for move in moves:
if move.state == 'done':
if frozen_fields.intersection(vals):
raise osv.except_osv(_('Operation Forbidden!'),
@ -2023,7 +2039,18 @@ class stock_move(osv.osv):
#Note that, for pulled moves we intentionally don't propagate on the procurement.
if propagated_changes_dict:
self.write(cr, uid, [move.move_dest_id.id], propagated_changes_dict, context=context)
return super(stock_move, self).write(cr, uid, ids, vals, context=context)
track_pickings = not context.get('mail_notrack') and any(field in vals for field in ['state', 'picking_id', 'partially_available'])
if track_pickings:
to_track_picking_ids = set([move.picking_id.id for move in moves if move.picking_id])
if vals.get('picking_id'):
to_track_picking_ids.add(vals['picking_id'])
to_track_picking_ids = list(to_track_picking_ids)
pickings = picking_obj.browse(cr, uid, to_track_picking_ids, context=context)
initial_values = dict((picking.id, {'state': picking.state}) for picking in pickings)
res = super(stock_move, self).write(cr, uid, ids, vals, context=context)
if track_pickings:
picking_obj.message_track(cr, uid, to_track_picking_ids, picking_obj.fields_get(cr, uid, ['state'], context=context), initial_values, context=context)
return res
def onchange_quantity(self, cr, uid, ids, product_id, product_qty, product_uom, product_uos):
""" On change of product quantity finds UoM and UoS quantities
@ -2229,7 +2256,7 @@ class stock_move(osv.osv):
for state, write_ids in states.items():
if len(write_ids):
self.write(cr, uid, write_ids, {'state': state})
self.write(cr, uid, write_ids, {'state': state}, context=context)
#assign picking in batch for all confirmed move that share the same details
for key, move_ids in to_assign.items():
procurement_group, location_from, location_to = key