[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:
parent
5b8bbb161b
commit
e202c84b27
|
@ -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 = [
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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)
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue