[IMP] Recompute quantities always on picking and disabling when doing prepare partial + prepare partial / recompute optimize
bzr revid: jco@openerp.com-20140310151133-ku0v80g148a6eyks
This commit is contained in:
parent
8ac2d35579
commit
2e7fedb889
|
@ -965,16 +965,18 @@ class stock_picking(osv.osv):
|
|||
|
||||
def do_prepare_partial(self, cr, uid, picking_ids, context=None):
|
||||
context = context or {}
|
||||
ctx = context.copy()
|
||||
ctx['no_recompute'] = True
|
||||
pack_operation_obj = self.pool.get('stock.pack.operation')
|
||||
pack_obj = self.pool.get("stock.quant.package")
|
||||
quant_obj = self.pool.get("stock.quant")
|
||||
|
||||
|
||||
#get list of existing operations and delete them
|
||||
existing_package_ids = pack_operation_obj.search(cr, uid, [('picking_id', 'in', picking_ids)], context=context)
|
||||
if existing_package_ids:
|
||||
pack_operation_obj.unlink(cr, uid, existing_package_ids, context)
|
||||
|
||||
|
||||
for picking in self.browse(cr, uid, picking_ids, context=context):
|
||||
reserved_move = {}
|
||||
qtys_remaining = {} #Quantity remaining after calculating reserved quants
|
||||
|
@ -1006,14 +1008,12 @@ class stock_picking(osv.osv):
|
|||
good_pack = False
|
||||
test_pack = pack
|
||||
while loop:
|
||||
quants = pack_obj.get_contents(cr, uid, test_pack, context=context)
|
||||
quants_to_compare = putaway_quants_dict.keys()
|
||||
# move_list = [m.id for m in picking.move_lines]
|
||||
quants_pack = pack_obj.get_contents(cr, uid, test_pack, context=context)
|
||||
common_location = False
|
||||
all_in = True
|
||||
for quant in quants:
|
||||
for quant in quants_pack:
|
||||
# If the quant is not in the quants to compare and not in the common location
|
||||
if not quant.id in quants_to_compare:
|
||||
if not quant in quants:
|
||||
all_in = False
|
||||
break
|
||||
else:
|
||||
|
@ -1023,13 +1023,8 @@ class stock_picking(osv.osv):
|
|||
elif common_location != quants_tup[1]:
|
||||
all_in = False
|
||||
break
|
||||
# if not (quant in quants_to_compare and (not common_location or putaway_quants_dict[quant][1] == common_location)):
|
||||
# all_in = False
|
||||
# break
|
||||
# elif not common_location and quant in quants_to_compare:
|
||||
# common_location = putaway_quants_dict[quant][1]
|
||||
if all_in:
|
||||
good_pack = test_pack.id
|
||||
good_pack = test_pack
|
||||
if test_pack.parent_id:
|
||||
test_pack = test_pack.parent_id
|
||||
else:
|
||||
|
@ -1042,18 +1037,19 @@ class stock_picking(osv.osv):
|
|||
if good_pack:
|
||||
top_lvl_packages.add(good_pack)
|
||||
|
||||
|
||||
# Create pack operations for the top-level packages found
|
||||
for pack in pack_obj.browse(cr, uid, list(top_lvl_packages), context=context):
|
||||
quants = pack_obj.get_content(cr, uid, [pack.id], context=context)
|
||||
quant = quant_obj.browse(cr, uid, quants[0], context=context)
|
||||
for pack in list(top_lvl_packages):
|
||||
quants = pack_obj.get_contents(cr, uid, pack, context=context)
|
||||
quant = quants[0]
|
||||
pack_operation_obj.create(cr, uid, {
|
||||
'picking_id': picking.id,
|
||||
'package_id': pack.id,
|
||||
'product_qty': 1.0,
|
||||
'location_id': pack.location_id.id,
|
||||
'location_dest_id': putaway_quants_dict[quant][0][1].id,
|
||||
}, context=context)
|
||||
for quant in quant_obj.browse(cr, uid, quants, context=context):
|
||||
}, context=ctx)
|
||||
for quant in quants:
|
||||
reserved_move[quant.reservation_id.id] -= set([quant.id])
|
||||
del putaway_quants_dict[quant]
|
||||
qtys_remaining[quant.product_id] -= quant.qty
|
||||
|
@ -1092,8 +1088,8 @@ class stock_picking(osv.osv):
|
|||
'location_id': key[4],
|
||||
'location_dest_id': key[5],
|
||||
'product_uom_id': self.pool.get("product.product").browse(cr, uid, key[0], context=context).uom_id.id,
|
||||
}, context=context)
|
||||
self.do_recompute_remaining_quantities(cr, uid, [picking.id], context=context)
|
||||
}, context=ctx)
|
||||
self.recompute_remaining_qty(cr, uid, picking, context=context)
|
||||
|
||||
def do_unreserve(self, cr, uid, picking_ids, context=None):
|
||||
"""
|
||||
|
@ -1109,18 +1105,129 @@ class stock_picking(osv.osv):
|
|||
self.pool.get('stock.pack.operation').unlink(cr, uid, pack_line_to_unreserve, context=context)
|
||||
self.pool.get('stock.move').do_unreserve(cr, uid, moves_to_unreserve, context=context)
|
||||
|
||||
def recompute_remaining_qty(self, cr, uid, picking, context=None):
|
||||
def _create_link_for_product(product_id, qty):
|
||||
qty_to_assign = qty
|
||||
if prod_move.get(product_id):
|
||||
for move in prod_move[product_id]:
|
||||
qty_on_link = min(qty_move_rem[move.id], qty_to_assign)
|
||||
cr.execute("""insert into stock_move_operation_link (move_id, operation_id, qty) values
|
||||
(%s, %s, %s)""", (move.id, op.id, qty_on_link,))
|
||||
qty_move_rem[move.id] -= qty_on_link
|
||||
qty_to_assign -= qty_on_link
|
||||
if qty_to_assign <= 0:
|
||||
break
|
||||
return qty_to_assign == 0
|
||||
|
||||
def _check_quants_reserved(ops):
|
||||
if ops.package_id and not ops.product_id:
|
||||
qty_op_rem[ops.id] = {}
|
||||
package_obj.get_contents(cr, uid, ops.package_id)
|
||||
for quant in package_obj.get_contents(cr, uid, ops.package_id):
|
||||
if quant.id in quants_done.keys() and (quants_done[quant.id] == quant.qty):
|
||||
#Entire packages means entire quants from those packages
|
||||
if not quants_done.get(quant.id):
|
||||
quants_done[quant.id] = 0
|
||||
cr.execute("""insert into stock_move_operation_link (move_id, operation_id, qty) values
|
||||
(%s, %s, %s)""", (quant.reservation_id.id, ops.id, quant.qty,))
|
||||
qty_move_rem[quant.reservation_id.id] -= quant.qty
|
||||
else:
|
||||
if qty_op_rem[ops.id].get(quant.product_id.id):
|
||||
qty_op_rem[ops.id][quant.product_id.id] += quant.qty
|
||||
else:
|
||||
qty_op_rem[ops.id][quant.product_id.id] = quant.qty
|
||||
else:
|
||||
qty = uom_obj._compute_qty_obj(cr, uid, ops.product_uom_id, ops.product_qty, ops.product_id.uom_id, context=context)
|
||||
#Check moves with same product
|
||||
if prod_move.get(ops.product_id.id):
|
||||
for move in prod_move[ops.product_id.id]:
|
||||
for quant in move.reserved_quant_ids:
|
||||
if not qty > 0:
|
||||
break
|
||||
if ops.package_id:
|
||||
flag = quant.package_id and bool(package_obj.search(cr, uid, [('id', 'child_of', [ops.package_id.id]), ('id', '=', quant.package_id.id)], context=context)) or False
|
||||
else:
|
||||
flag = not quant.package_id.id
|
||||
flag = flag and ((ops.lot_id and ops.lot_id.id == quant.lot_id.id) or not ops.lot_id)
|
||||
flag = flag and (ops.owner_id.id == quant.owner_id.id)
|
||||
if flag:
|
||||
quant_qty = quant.qty
|
||||
if quants_done.get(quant.id):
|
||||
if quants_done[quant.id] == 0:
|
||||
continue
|
||||
quant_qty = quants_done[quant.id]
|
||||
if quant_qty > qty:
|
||||
qty_todo = qty
|
||||
quants_done[quant.id] = quant_qty - qty
|
||||
else:
|
||||
qty_todo = quant_qty
|
||||
quants_done[quant.id] = 0
|
||||
qty -= qty_todo
|
||||
cr.execute("""insert into stock_move_operation_link (move_id, operation_id, qty) values
|
||||
(%s, %s, %s)""", (move.id, ops.id, qty_todo,))
|
||||
qty_move_rem[move.id] -= qty_todo
|
||||
qty_op_rem[ops.id] = qty
|
||||
|
||||
uom_obj = self.pool.get('product.uom')
|
||||
package_obj = self.pool.get('stock.quant.package')
|
||||
quants_done = {}
|
||||
prod_move = {}
|
||||
qty_rem = {}
|
||||
qty_move_rem = {}
|
||||
qty_op_rem = {}
|
||||
operations = picking.pack_operation_ids
|
||||
operations.sort(key=lambda x: ((x.package_id and not x.product_id) and -4 or 0) + (x.package_id and -2 or 0) + (x.lot_id and -1 or 0))
|
||||
cr.execute("""DELETE FROM stock_move_operation_link WHERE
|
||||
operation_id in %s
|
||||
""", (tuple([x.id for x in operations]),))
|
||||
for move in picking.move_lines:
|
||||
prod_qty = move.product_qty
|
||||
qty_rem[move.id] = prod_qty
|
||||
qty_move_rem[move.id] = prod_qty
|
||||
#Fill moves by product dict
|
||||
if not prod_move.get(move.product_id.id):
|
||||
prod_move[move.product_id.id] = [move]
|
||||
else:
|
||||
prod_move[move.product_id.id].append(move)
|
||||
# Fill qty remaining dict
|
||||
for quant in move.reserved_quant_ids:
|
||||
quants_done[quant.id] = quant.qty
|
||||
sorted_moves = [x for x in picking.move_lines if x.state not in ['done', 'cancel']]
|
||||
sorted_moves.sort(key=lambda x: qty_rem[x.id])
|
||||
|
||||
for op in operations:
|
||||
_check_quants_reserved(op)
|
||||
|
||||
remaining_qty_ok = True
|
||||
for op in operations:
|
||||
op.refresh()
|
||||
if op.product_id:
|
||||
#TODO: Remaining qty: UoM conversions are done twice
|
||||
normalized_qty = qty_op_rem[op.id]
|
||||
if normalized_qty > 0:
|
||||
remaining_qty_ok = remaining_qty_ok and _create_link_for_product(op.product_id.id, normalized_qty)
|
||||
elif op.package_id:
|
||||
for product_id, qty in qty_op_rem[op.id].items():
|
||||
if qty > 0:
|
||||
remaining_qty_ok = remaining_qty_ok and _create_link_for_product(product_id, qty)
|
||||
|
||||
quants_reserve_ok = all([quants_done[x] == 0 for x in quants_done.keys()])
|
||||
return (quants_reserve_ok, remaining_qty_ok)
|
||||
|
||||
|
||||
def do_recompute_remaining_quantities(self, cr, uid, picking_ids, context=None):
|
||||
pack_op_obj = self.pool.get('stock.pack.operation')
|
||||
quants_res = True
|
||||
remaining_res = True
|
||||
for picking in self.browse(cr, uid, picking_ids, context=context):
|
||||
op_ids = [op.id for op in picking.pack_operation_ids]
|
||||
if op_ids:
|
||||
(quants_ok, remaining_ok) = pack_op_obj.recompute_rem_qty_from_operation(cr, uid, op_ids, context=context)
|
||||
if picking.pack_operation_ids:
|
||||
(quants_ok, remaining_ok) = self.recompute_remaining_qty(cr, uid, picking, context=context)
|
||||
quants_res = quants_res and quants_ok
|
||||
remaining_res = remaining_res and remaining_ok
|
||||
return (quants_res, remaining_res)
|
||||
|
||||
|
||||
|
||||
|
||||
def _create_extra_moves(self, cr, uid, picking, context=None):
|
||||
'''This function creates move lines on a picking, at the time of do_transfer, based on
|
||||
unexpected product transfers (or exceeding quantities) found in the pack operations.
|
||||
|
@ -3562,124 +3669,22 @@ class stock_pack_operation(osv.osv):
|
|||
res = super(stock_pack_operation, self).write(cr, uid, ids, vals, context=context)
|
||||
if isinstance(ids, (int, long)):
|
||||
ids = [ids]
|
||||
#self.recompute_rem_qty_from_operation(cr, uid, ids, context=context)
|
||||
if not context.get("no_recompute"):
|
||||
if vals.get('picking_id'):
|
||||
self.pool.get("stock.picking").do_recompute_remaining_quantities(cr, uid, [vals['picking_id']], context=context)
|
||||
else:
|
||||
moves = self.browse(cr, uid, ids, context=context)
|
||||
pickings = list(set([x.picking_id.id for x in moves]))
|
||||
self.pool.get("stock.picking").do_recompute_remaining_quantities(cr, uid, pickings, context=context)
|
||||
return res
|
||||
|
||||
def create(self, cr, uid, vals, context=None):
|
||||
res_id = super(stock_pack_operation, self).create(cr, uid, vals, context=context)
|
||||
#self.recompute_rem_qty_from_operation(cr, uid, [res_id], context=context)
|
||||
if vals.get("picking_id") and not context.get("no_recompute"):
|
||||
self.pool.get("stock.picking").do_recompute_remaining_quantities(cr, uid, [vals['picking_id']], context=context)
|
||||
return res_id
|
||||
|
||||
def recompute_rem_qty_from_operation(self, cr, uid, op_ids, context=None):
|
||||
def _create_link_for_product(product_id, qty):
|
||||
qty_to_assign = qty
|
||||
if prod_move.get(product_id):
|
||||
for move in prod_move[product_id]:
|
||||
qty_on_link = min(qty_move_rem[move.id], qty_to_assign)
|
||||
cr.execute("""insert into stock_move_operation_link (move_id, operation_id, qty) values
|
||||
(%s, %s, %s)""", (move.id, op.id, qty_on_link,))
|
||||
qty_move_rem[move.id] -= qty_on_link
|
||||
qty_to_assign -= qty_on_link
|
||||
if qty_to_assign <= 0:
|
||||
break
|
||||
return qty_to_assign == 0
|
||||
|
||||
def _check_quants_reserved(ops):
|
||||
if ops.package_id and not ops.product_id:
|
||||
qty_op_rem[ops.id] = {}
|
||||
package_obj.get_contents(cr, uid, ops.package_id)
|
||||
for quant in package_obj.get_contents(cr, uid, ops.package_id):
|
||||
if quant.id in quants_done.keys() and (quants_done[quant.id] == quant.qty):
|
||||
#Entire packages means entire quants from those packages
|
||||
if not quants_done.get(quant.id):
|
||||
quants_done[quant.id] = 0
|
||||
cr.execute("""insert into stock_move_operation_link (move_id, operation_id, qty) values
|
||||
(%s, %s, %s)""", (quant.reservation_id.id, ops.id, quant.qty,))
|
||||
qty_move_rem[quant.reservation_id.id] -= quant.qty
|
||||
else:
|
||||
if qty_op_rem[ops.id].get(quant.product_id.id):
|
||||
qty_op_rem[ops.id][quant.product_id.id] += quant.qty
|
||||
else:
|
||||
qty = uom_obj._compute_qty_obj(cr, uid, ops.product_uom_id, ops.product_qty, ops.product_id.uom_id, context=context)
|
||||
#Check moves with same product
|
||||
if prod_move.get(ops.product_id.id):
|
||||
for move in prod_move[ops.product_id.id]:
|
||||
for quant in move.reserved_quant_ids:
|
||||
if not qty > 0:
|
||||
break
|
||||
if ops.package_id:
|
||||
flag = quant.package_id and bool(package_obj.search(cr, uid, [('id', 'child_of', [ops.package_id.id]), ('id', '=', quant.package_id.id)], context=context)) or False
|
||||
else:
|
||||
flag = not quant.package_id.id
|
||||
flag = flag and ((ops.lot_id and ops.lot_id.id == quant.lot_id.id) or not ops.lot_id)
|
||||
flag = flag and (ops.owner_id.id == quant.owner_id.id)
|
||||
if flag:
|
||||
quant_qty = quant.qty
|
||||
if quants_done.get(quant.id):
|
||||
if quants_done[quant.id] == 0:
|
||||
continue
|
||||
quant_qty = quants_done[quant.id]
|
||||
if quant_qty > qty:
|
||||
qty_todo = qty
|
||||
quants_done[quant.id] = quant_qty - qty
|
||||
else:
|
||||
qty_todo = quant_qty
|
||||
quants_done[quant.id] = 0
|
||||
qty -= qty_todo
|
||||
cr.execute("""insert into stock_move_operation_link (move_id, operation_id, qty) values
|
||||
(%s, %s, %s)""", (move.id, ops.id, qty_todo,))
|
||||
qty_move_rem[move.id] -= qty_todo
|
||||
qty_op_rem[ops.id] = qty
|
||||
|
||||
link_obj = self.pool.get('stock.move.operation.link')
|
||||
uom_obj = self.pool.get('product.uom')
|
||||
package_obj = self.pool.get('stock.quant.package')
|
||||
quant_obj = self.pool.get('stock.quant')
|
||||
quants_done = {}
|
||||
prod_move = {}
|
||||
qty_rem = {}
|
||||
qty_move_rem = {}
|
||||
qty_op_rem = {}
|
||||
operations = self.browse(cr, uid, op_ids, context=context)
|
||||
operations.sort(key=lambda x: ((x.package_id and not x.product_id) and -4 or 0) + (x.package_id and -2 or 0) + (x.lot_id and -1 or 0))
|
||||
sorted_moves = []
|
||||
cr.execute("""DELETE FROM stock_move_operation_link WHERE
|
||||
operation_id in %s
|
||||
""", (tuple([x.id for x in operations]),))
|
||||
for op in operations:
|
||||
if not sorted_moves:
|
||||
#sort moves in order to process first the ones that have already reserved quants
|
||||
for move in op.picking_id.move_lines:
|
||||
prod_qty = move.product_qty
|
||||
qty_rem[move.id] = prod_qty
|
||||
qty_move_rem[move.id] = prod_qty
|
||||
for quant in move.reserved_quant_ids:
|
||||
qty_rem[move.id] -= quant.qty
|
||||
quants_done[quant.id] = quant.qty
|
||||
sorted_moves = [x for x in op.picking_id.move_lines if x.state not in ['done', 'cancel']]
|
||||
sorted_moves.sort(key=lambda x: qty_rem[x.id])
|
||||
for move in sorted_moves:
|
||||
if not prod_move.get(move.product_id.id):
|
||||
prod_move[move.product_id.id] = [move]
|
||||
else:
|
||||
prod_move[move.product_id.id].append(move)
|
||||
_check_quants_reserved(op)
|
||||
|
||||
remaining_qty_ok = True
|
||||
for op in operations:
|
||||
op.refresh()
|
||||
if op.product_id:
|
||||
#TODO: Remaining qty: UoM conversions are done twice
|
||||
normalized_qty = qty_op_rem[op.id]
|
||||
if normalized_qty > 0:
|
||||
remaining_qty_ok = remaining_qty_ok and _create_link_for_product(op.product_id.id, normalized_qty)
|
||||
elif op.package_id:
|
||||
for product_id, qty in qty_op_rem[op.id].items():
|
||||
if qty > 0:
|
||||
remaining_qty_ok = remaining_qty_ok and _create_link_for_product(product_id, qty)
|
||||
|
||||
quants_reserve_ok = all([quants_done[x] == 0 for x in quants_done.keys()])
|
||||
return (quants_reserve_ok, remaining_qty_ok)
|
||||
|
||||
def process_packaging(self, cr, uid, operation, quants, context=None):
|
||||
''' Process the packaging of a given operation, after the quants have been moved. If there was not enough quants found
|
||||
|
|
Loading…
Reference in New Issue