[REF] stock: assign picking by batch on confirmation of stock moves. This new version will work for confirmed move from elsewhere than the sale order

bzr revid: qdp-launchpad@openerp.com-20140318115746-fixnxghkrlth38ze
This commit is contained in:
Quentin (OpenERP) 2014-03-18 12:57:46 +01:00
parent 5b8bbb161b
commit e202c84b27
5 changed files with 40 additions and 86 deletions

View File

@ -31,7 +31,6 @@ import openerp.addons.decimal_precision as dp
from openerp.osv.orm import browse_record, browse_null from openerp.osv.orm import browse_record, browse_null
from openerp.tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT, DATETIME_FORMATS_MAP from openerp.tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT, DATETIME_FORMATS_MAP
class purchase_order(osv.osv): class purchase_order(osv.osv):
def _amount_all(self, cr, uid, ids, field_name, arg, context=None): def _amount_all(self, cr, uid, ids, field_name, arg, context=None):
@ -164,11 +163,11 @@ class purchase_order(osv.osv):
""" """
cr.execute(query, (tuple(ids), )) cr.execute(query, (tuple(ids), ))
picks = cr.fetchall() picks = cr.fetchall()
for pick in picks: for pick_id, po_id in picks:
if not res.get(pick[1]): if not res.get(po_id):
res[pick[1]] = [pick[0]] res[po_id] = [pick_id]
else: else:
res[pick[1]].append(pick[0]) res[po_id].append(pick_id)
return res return res
STATE_SELECTION = [ STATE_SELECTION = [

View File

@ -677,8 +677,6 @@ class sale_order(osv.osv):
:return: True :return: True
""" """
if not context:
context = {}
procurement_obj = self.pool.get('procurement.order') procurement_obj = self.pool.get('procurement.order')
sale_line_obj = self.pool.get('sale.order.line') sale_line_obj = self.pool.get('sale.order.line')
for order in self.browse(cr, uid, ids, context=context): for order in self.browse(cr, uid, ids, context=context):
@ -704,11 +702,7 @@ class sale_order(osv.osv):
proc_ids.append(proc_id) proc_ids.append(proc_id)
#Confirm procurement order such that rules will be applied on it #Confirm procurement order such that rules will be applied on it
#note that the workflow normally ensure proc_ids isn't an empty list #note that the workflow normally ensure proc_ids isn't an empty list
ctx = context.copy() procurement_obj.run(cr, uid, proc_ids, context=context)
ctx["no_picking_assign"] = True
procurement_obj.run(cr, uid, proc_ids, context=ctx)
#Check all moves associated and do the picking_assign
procurement_obj.group_picking_assign(cr, uid, proc_ids, context=context)
#if shipping was in exception and the user choose to recreate the delivery order, write the new status of SO #if shipping was in exception and the user choose to recreate the delivery order, write the new status of SO
if order.state == 'shipping_except': if order.state == 'shipping_except':
@ -1177,5 +1171,3 @@ class procurement_order(osv.osv):
'sale_line_id': fields.many2one('sale.order.line', string='Sale Order Line'), 'sale_line_id': fields.many2one('sale.order.line', string='Sale Order Line'),
} }
def group_picking_assign(self, cr, uid, proc_ids, context=None):
return True

View File

@ -453,18 +453,3 @@ class stock_picking(osv.osv):
created_lines = sale_line_obj.invoice_line_create(cr, uid, sale_line_ids, context=context) created_lines = sale_line_obj.invoice_line_create(cr, uid, sale_line_ids, context=context)
invoice_line_obj.write(cr, uid, created_lines, {'invoice_id': invoice_id}, context=context) invoice_line_obj.write(cr, uid, created_lines, {'invoice_id': invoice_id}, context=context)
return invoice_id return invoice_id
class procurement_order(osv.osv):
_inherit = 'procurement.order'
def group_picking_assign(self, cr, uid, proc_ids, context=None):
moves = []
procurements = proc_ids
while procurements:
related_moves = []
for proc in self.browse(cr, uid, procurements, context=context):
related_moves += proc.move_ids
procurements = self.search(cr, uid, [('move_dest_id', 'in', [x.id for x in related_moves])], context=context)
moves += related_moves
self.pool.get("stock.move")._group_picking_assign(cr, uid, moves, context=context)

View File

@ -215,11 +215,23 @@ class procurement_order(osv.osv):
return False return False
move_obj = self.pool.get('stock.move') move_obj = self.pool.get('stock.move')
move_dict = self._run_move_create(cr, uid, procurement, context=context) move_dict = self._run_move_create(cr, uid, procurement, context=context)
move_id = move_obj.create(cr, uid, move_dict, context=context) move_obj.create(cr, uid, move_dict, context=context)
self.message_post(cr, uid, [procurement.id], body=_("Supply Move created"), context=context) self.message_post(cr, uid, [procurement.id], body=_("Supply Move created"), context=context)
move_obj.action_confirm(cr, uid, [move_id], context=context)
return True return True
return super(procurement_order, self)._run(cr, uid, procurement, context) return super(procurement_order, self)._run(cr, uid, procurement, context=context)
def run(self, cr, uid, ids, context=None):
move_obj = self.pool.get('stock.move')
res = super(procurement_order, self).run(cr, uid, ids, context=context)
#after all the procurements are run, check if some created a draft stock move that needs to be confirmed
#(we do that in batch because it fasten the picking assignation and the picking state computation)
move_to_confirm_ids = []
for procurement in self.browse(cr, uid, ids, context=context):
if procurement.state == "running" and procurement.rule_id and procurement.rule_id.action == "move":
move_to_confirm_ids += [m.id for m in procurement.move_ids if m.state == 'draft']
if move_to_confirm_ids:
move_obj.action_confirm(cr, uid, move_to_confirm_ids, context=context)
return res
def _check(self, cr, uid, procurement, context=None): def _check(self, cr, uid, procurement, context=None):
''' Implement the procurement checking for rules of type 'move'. The procurement will be satisfied only if all related ''' Implement the procurement checking for rules of type 'move'. The procurement will be satisfied only if all related

View File

@ -946,13 +946,11 @@ class stock_picking(osv.osv):
self.action_assign(cr, uid, picking_ids, context=context) self.action_assign(cr, uid, picking_ids, context=context)
self.do_prepare_partial(cr, uid, picking_ids, context=context) self.do_prepare_partial(cr, uid, picking_ids, context=context)
def _picking_putaway_resolution(self, cr, uid, picking, product, putaway, context=None): def _picking_putaway_resolution(self, cr, uid, picking, product, putaway, context=None):
if putaway.method == 'fixed' and putaway.location_spec_id: if putaway.method == 'fixed' and putaway.location_spec_id:
return putaway.location_spec_id.id return putaway.location_spec_id.id
return False return False
def _get_top_level_packages(self, cr, uid, quants_suggested_locations, context=None): def _get_top_level_packages(self, cr, uid, quants_suggested_locations, context=None):
"""This method searches for the higher level packages that can be moved as a single operation, given a list of quants """This method searches for the higher level packages that can be moved as a single operation, given a list of quants
to move and their suggested destination, and returns the list of matching packages. to move and their suggested destination, and returns the list of matching packages.
@ -1559,7 +1557,6 @@ class stock_move(osv.osv):
res += [x.id for x in picking.move_lines] res += [x.id for x in picking.move_lines]
return res return res
_columns = { _columns = {
'name': fields.char('Description', required=True, select=True), 'name': fields.char('Description', required=True, select=True),
'priority': fields.selection([('0', 'Not urgent'), ('1', 'Urgent')], 'Priority'), 'priority': fields.selection([('0', 'Not urgent'), ('1', 'Urgent')], 'Priority'),
@ -1923,25 +1920,20 @@ class stock_move(osv.osv):
result['location_dest_id'] = loc_dest_id result['location_dest_id'] = loc_dest_id
return {'value': result} return {'value': result}
def _picking_assign(self, cr, uid, move, context=None): def _picking_assign(self, cr, uid, move_ids, procurement_group, location_from, location_to, context=None):
if not context: """Assign a picking on the given move_ids, which is a list of move supposed to share the same procurement_group, location_from and location_to
context = {} (and company). Those attributes are also given as parameters.
if context.get("no_picking_assign") and context['no_picking_assign']: """
return False
if move.picking_id or not move.picking_type_id:
return False
context = context or {}
pick_obj = self.pool.get("stock.picking") pick_obj = self.pool.get("stock.picking")
picks = []
group = move.group_id and move.group_id.id or False
picks = pick_obj.search(cr, uid, [ picks = pick_obj.search(cr, uid, [
('group_id', '=', group), ('group_id', '=', procurement_group),
('location_id', '=', move.location_id.id), ('location_id', '=', location_from),
('location_dest_id', '=', move.location_dest_id.id), ('location_dest_id', '=', location_to),
('state', 'in', ['draft', 'confirmed', 'waiting'])], context=context) ('state', 'in', ['draft', 'confirmed', 'waiting'])], context=context)
if picks: if picks:
pick = picks[0] pick = picks[0]
else: else:
move = self.browse(cr, uid, move_ids, context=context)[0]
values = { values = {
'origin': move.origin, 'origin': move.origin,
'company_id': move.company_id and move.company_id.id or False, 'company_id': move.company_id and move.company_id.id or False,
@ -1950,42 +1942,7 @@ class stock_move(osv.osv):
'picking_type_id': move.picking_type_id and move.picking_type_id.id or False, 'picking_type_id': move.picking_type_id and move.picking_type_id.id or False,
} }
pick = pick_obj.create(cr, uid, values, context=context) pick = pick_obj.create(cr, uid, values, context=context)
move.write({'picking_id': pick}) return self.write(cr, uid, move_ids, {'picking_id': pick}, context=context)
return True
def _group_picking_assign(self, cr, uid, moves, context=None):
if not context:
context = {}
if context.get("no_picking_assign"):
return False
move_dict = {}
for move in moves:
group_by = (move.location_id, move.location_dest_id, move.group_id)
if not move_dict.get(group_by, False):
move_dict[group_by] = [move]
else:
move_dict[group_by].append(move)
pick_obj = self.pool.get("stock.picking")
for to_compare in move_dict.keys():
picks = pick_obj.search(cr, uid, [
('group_id', '=', to_compare[2].id),
('location_id', '=', to_compare[0].id),
('location_dest_id', '=', to_compare[1].id),
('state', 'in', ['draft', 'confirmed', 'waiting']),
], context=context)
if picks:
pick = picks[0]
else:
move = move_dict[to_compare][0]
values = {
'origin': move.origin,
'company_id': move.company_id and move.company_id.id or False,
'move_type': move.group_id and move.group_id.move_type or 'one',
'partner_id': move.group_id and move.group_id.partner_id and move.group_id.partner_id.id or False,
'picking_type_id': move.picking_type_id and move.picking_type_id.id or False,
}
pick = pick_obj.create(cr, uid, values, context=context)
self.write(cr, uid, [x.id for x in move_dict[to_compare]], {'picking_id': pick}, context=context)
def onchange_date(self, cr, uid, ids, date, date_expected, context=None): def onchange_date(self, cr, uid, ids, date, date_expected, context=None):
""" On change of Scheduled Date gives a Move date. """ On change of Scheduled Date gives a Move date.
@ -2007,6 +1964,7 @@ class stock_move(osv.osv):
'confirmed': [], 'confirmed': [],
'waiting': [] 'waiting': []
} }
to_assign = {}
for move in self.browse(cr, uid, ids, context=context): for move in self.browse(cr, uid, ids, context=context):
state = 'confirmed' state = 'confirmed'
#if the move is preceeded, then it's waiting (if preceeding move is done, then action_assign has been called already and its state is already available) #if the move is preceeded, then it's waiting (if preceeding move is done, then action_assign has been called already and its state is already available)
@ -2019,9 +1977,13 @@ class stock_move(osv.osv):
if move2.move_orig_ids: if move2.move_orig_ids:
state = 'waiting' state = 'waiting'
move2 = move2.split_from move2 = move2.split_from
states[state].append(move.id) states[state].append(move.id)
self._picking_assign(cr, uid, move, context=context)
if not move.picking_id and move.picking_type_id:
key = (move.group_id.id, move.location_id.id, move.location_dest_id.id)
if key not in to_assign:
to_assign[key] = []
to_assign[key].append(move.id)
for move in self.browse(cr, uid, states['confirmed'], context=context): for move in self.browse(cr, uid, states['confirmed'], context=context):
if move.procure_method == 'make_to_order': if move.procure_method == 'make_to_order':
@ -2032,6 +1994,10 @@ class stock_move(osv.osv):
for state, write_ids in states.items(): for state, write_ids in states.items():
if len(write_ids): if len(write_ids):
self.write(cr, uid, write_ids, {'state': state}) self.write(cr, uid, write_ids, {'state': state})
#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
self._picking_assign(cr, uid, move_ids, procurement_group, location_from, location_to, context=context)
moves = self.browse(cr, uid, ids, context=context) moves = self.browse(cr, uid, ids, context=context)
self._push_apply(cr, uid, moves, context=context) self._push_apply(cr, uid, moves, context=context)
return ids return ids