[IMP] Improve recompute with dictionary of moves for every product
bzr revid: jco@openerp.com-20140305154836-f279eafnickmyjz9
This commit is contained in:
parent
abd79cc036
commit
3e2ebaae80
|
@ -31,7 +31,7 @@ from openerp import SUPERUSER_ID
|
||||||
import openerp.addons.decimal_precision as dp
|
import openerp.addons.decimal_precision as dp
|
||||||
import logging
|
import logging
|
||||||
_logger = logging.getLogger(__name__)
|
_logger = logging.getLogger(__name__)
|
||||||
|
from profilehooks import profile
|
||||||
#----------------------------------------------------------
|
#----------------------------------------------------------
|
||||||
# Incoterms
|
# Incoterms
|
||||||
#----------------------------------------------------------
|
#----------------------------------------------------------
|
||||||
|
@ -382,6 +382,8 @@ class stock_quant(osv.osv):
|
||||||
the choice on the quants that match the prefered_domain as well. But if the qty requested is not reached
|
the choice on the quants that match the prefered_domain as well. But if the qty requested is not reached
|
||||||
it tries to find the remaining quantity by using the fallback_domain.
|
it tries to find the remaining quantity by using the fallback_domain.
|
||||||
'''
|
'''
|
||||||
|
if location.usage in ['inventory', 'production', 'supplier']:
|
||||||
|
return [(None, qty)]
|
||||||
if prefered_domain and fallback_domain:
|
if prefered_domain and fallback_domain:
|
||||||
if domain is None:
|
if domain is None:
|
||||||
domain = []
|
domain = []
|
||||||
|
@ -502,36 +504,38 @@ class stock_quant(osv.osv):
|
||||||
dom += [('package_id', '=', quant.package_id.id)]
|
dom += [('package_id', '=', quant.package_id.id)]
|
||||||
if move.move_dest_id:
|
if move.move_dest_id:
|
||||||
dom += [('negative_move_id', '=', move.move_dest_id.id)]
|
dom += [('negative_move_id', '=', move.move_dest_id.id)]
|
||||||
quants = self.quants_get(cr, uid, quant.location_id, quant.product_id, quant.qty, dom, context=context)
|
quants = self.search(cr, uid, [('product_id', '=', quant.product_id.id), ('qty','<', 0)], context=context)
|
||||||
for quant_neg, qty in quants:
|
if quants:
|
||||||
if not quant_neg:
|
quants = self.quants_get(cr, uid, quant.location_id, quant.product_id, quant.qty, dom, context=context)
|
||||||
continue
|
for quant_neg, qty in quants:
|
||||||
to_solve_quant_ids = self.search(cr, uid, [('propagated_from_id', '=', quant_neg.id)], context=context)
|
if not quant_neg:
|
||||||
if not to_solve_quant_ids:
|
|
||||||
continue
|
|
||||||
solving_qty = qty
|
|
||||||
solved_quant_ids = []
|
|
||||||
for to_solve_quant in self.browse(cr, uid, to_solve_quant_ids, context=context):
|
|
||||||
if solving_qty <= 0:
|
|
||||||
continue
|
continue
|
||||||
solved_quant_ids.append(to_solve_quant.id)
|
to_solve_quant_ids = self.search(cr, uid, [('propagated_from_id', '=', quant_neg.id)], context=context)
|
||||||
self._quant_split(cr, uid, to_solve_quant, min(solving_qty, to_solve_quant.qty), context=context)
|
if not to_solve_quant_ids:
|
||||||
solving_qty -= min(solving_qty, to_solve_quant.qty)
|
continue
|
||||||
remaining_solving_quant = self._quant_split(cr, uid, solving_quant, qty, context=context)
|
solving_qty = qty
|
||||||
remaining_neg_quant = self._quant_split(cr, uid, quant_neg, -qty, context=context)
|
solved_quant_ids = []
|
||||||
#if the reconciliation was not complete, we need to link together the remaining parts
|
for to_solve_quant in self.browse(cr, uid, to_solve_quant_ids, context=context):
|
||||||
if remaining_neg_quant:
|
if solving_qty <= 0:
|
||||||
remaining_to_solve_quant_ids = self.search(cr, uid, [('propagated_from_id', '=', quant_neg.id), ('id', 'not in', solved_quant_ids)], context=context)
|
continue
|
||||||
if remaining_to_solve_quant_ids:
|
solved_quant_ids.append(to_solve_quant.id)
|
||||||
self.write(cr, SUPERUSER_ID, remaining_to_solve_quant_ids, {'propagated_from_id': remaining_neg_quant.id}, context=context)
|
self._quant_split(cr, uid, to_solve_quant, min(solving_qty, to_solve_quant.qty), context=context)
|
||||||
#delete the reconciled quants, as it is replaced by the solved quants
|
solving_qty -= min(solving_qty, to_solve_quant.qty)
|
||||||
self.unlink(cr, SUPERUSER_ID, [quant_neg.id], context=context)
|
remaining_solving_quant = self._quant_split(cr, uid, solving_quant, qty, context=context)
|
||||||
#price update + accounting entries adjustments
|
remaining_neg_quant = self._quant_split(cr, uid, quant_neg, -qty, context=context)
|
||||||
self._price_update(cr, uid, solved_quant_ids, solving_quant.cost, context=context)
|
#if the reconciliation was not complete, we need to link together the remaining parts
|
||||||
#merge history (and cost?)
|
if remaining_neg_quant:
|
||||||
self._quants_merge(cr, uid, solved_quant_ids, solving_quant, context=context)
|
remaining_to_solve_quant_ids = self.search(cr, uid, [('propagated_from_id', '=', quant_neg.id), ('id', 'not in', solved_quant_ids)], context=context)
|
||||||
self.unlink(cr, SUPERUSER_ID, [solving_quant.id], context=context)
|
if remaining_to_solve_quant_ids:
|
||||||
solving_quant = remaining_solving_quant
|
self.write(cr, SUPERUSER_ID, remaining_to_solve_quant_ids, {'propagated_from_id': remaining_neg_quant.id}, context=context)
|
||||||
|
#delete the reconciled quants, as it is replaced by the solved quants
|
||||||
|
self.unlink(cr, SUPERUSER_ID, [quant_neg.id], context=context)
|
||||||
|
#price update + accounting entries adjustments
|
||||||
|
self._price_update(cr, uid, solved_quant_ids, solving_quant.cost, context=context)
|
||||||
|
#merge history (and cost?)
|
||||||
|
self._quants_merge(cr, uid, solved_quant_ids, solving_quant, context=context)
|
||||||
|
self.unlink(cr, SUPERUSER_ID, [solving_quant.id], context=context)
|
||||||
|
solving_quant = remaining_solving_quant
|
||||||
|
|
||||||
def _price_update(self, cr, uid, ids, newprice, context=None):
|
def _price_update(self, cr, uid, ids, newprice, context=None):
|
||||||
self.write(cr, SUPERUSER_ID, ids, {'cost': newprice}, context=context)
|
self.write(cr, SUPERUSER_ID, ids, {'cost': newprice}, context=context)
|
||||||
|
@ -549,8 +553,8 @@ class stock_quant(osv.osv):
|
||||||
domain += location and [('location_id', 'child_of', location.id)] or []
|
domain += location and [('location_id', 'child_of', location.id)] or []
|
||||||
domain += [('product_id', '=', product.id)] + domain
|
domain += [('product_id', '=', product.id)] + domain
|
||||||
#don't take into account location that are production, supplier or inventory
|
#don't take into account location that are production, supplier or inventory
|
||||||
ignore_location_ids = self.pool.get('stock.location').search(cr, uid, [('usage', 'in', ('production', 'supplier', 'inventory'))], context=context)
|
#ignore_location_ids = self.pool.get('stock.location').search(cr, uid, [('usage', 'in', ('production', 'supplier', 'inventory'))], context=context)
|
||||||
domain.append(('location_id','not in',ignore_location_ids))
|
#domain.append(('location_id','not in',ignore_location_ids))
|
||||||
res = []
|
res = []
|
||||||
offset = 0
|
offset = 0
|
||||||
while quantity > 0:
|
while quantity > 0:
|
||||||
|
@ -1144,6 +1148,7 @@ class stock_picking(osv.osv):
|
||||||
stock_move_obj.do_unreserve(cr, uid, move_ids, context=context)
|
stock_move_obj.do_unreserve(cr, uid, move_ids, context=context)
|
||||||
stock_move_obj.action_assign(cr, uid, move_ids, context=context)
|
stock_move_obj.action_assign(cr, uid, move_ids, context=context)
|
||||||
|
|
||||||
|
|
||||||
def do_transfer(self, cr, uid, picking_ids, context=None):
|
def do_transfer(self, cr, uid, picking_ids, context=None):
|
||||||
"""
|
"""
|
||||||
If no pack operation, we do simple action_done of the picking
|
If no pack operation, we do simple action_done of the picking
|
||||||
|
@ -3552,19 +3557,18 @@ class stock_pack_operation(osv.osv):
|
||||||
res_id = super(stock_pack_operation, self).create(cr, uid, vals, context=context)
|
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)
|
self.recompute_rem_qty_from_operation(cr, uid, [res_id], context=context)
|
||||||
return res_id
|
return res_id
|
||||||
|
@profile(immediate=True)
|
||||||
def recompute_rem_qty_from_operation(self, cr, uid, op_ids, context=None):
|
def recompute_rem_qty_from_operation(self, cr, uid, op_ids, context=None):
|
||||||
def _create_link_for_product(product_id, qty):
|
def _create_link_for_product(product_id, qty):
|
||||||
qty_to_assign = qty
|
qty_to_assign = qty
|
||||||
for move in sorted_moves:
|
for move in prod_move[product_id]:
|
||||||
if move.product_id.id == product_id and move.state not in ['done', 'cancel']:
|
qty_on_link = min(qty_move_rem[move.id], qty_to_assign)
|
||||||
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
|
||||||
cr.execute("""insert into stock_move_operation_link (move_id, operation_id, qty) values
|
(%s, %s, %s)""", (move.id, op.id, qty_on_link,))
|
||||||
(%s, %s, %s)""", (move.id, op.id, qty_on_link,))
|
qty_move_rem[move.id] -= qty_on_link
|
||||||
qty_move_rem[move.id] -= qty_on_link
|
qty_to_assign -= qty_on_link
|
||||||
qty_to_assign -= qty_on_link
|
if qty_to_assign <= 0:
|
||||||
if qty_to_assign <= 0:
|
break
|
||||||
break
|
|
||||||
return qty_to_assign == 0
|
return qty_to_assign == 0
|
||||||
|
|
||||||
def _check_quants_reserved(ops):
|
def _check_quants_reserved(ops):
|
||||||
|
@ -3612,7 +3616,7 @@ class stock_pack_operation(osv.osv):
|
||||||
package_obj = self.pool.get('stock.quant.package')
|
package_obj = self.pool.get('stock.quant.package')
|
||||||
quant_obj = self.pool.get('stock.quant')
|
quant_obj = self.pool.get('stock.quant')
|
||||||
quants_done = {}
|
quants_done = {}
|
||||||
|
prod_move = {}
|
||||||
qty_rem = {}
|
qty_rem = {}
|
||||||
qty_move_rem = {}
|
qty_move_rem = {}
|
||||||
operations = self.browse(cr, uid, op_ids, context=context)
|
operations = self.browse(cr, uid, op_ids, context=context)
|
||||||
|
@ -3628,8 +3632,13 @@ class stock_pack_operation(osv.osv):
|
||||||
for quant in move.reserved_quant_ids:
|
for quant in move.reserved_quant_ids:
|
||||||
qty_rem[move.id] -= quant.qty
|
qty_rem[move.id] -= quant.qty
|
||||||
quants_done[quant.id] = quant.qty
|
quants_done[quant.id] = quant.qty
|
||||||
sorted_moves = op.picking_id.move_lines
|
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])
|
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)
|
||||||
|
|
||||||
to_unlink_ids = [x.id for x in op.linked_move_operation_ids]
|
to_unlink_ids = [x.id for x in op.linked_move_operation_ids]
|
||||||
if to_unlink_ids:
|
if to_unlink_ids:
|
||||||
|
@ -3648,8 +3657,6 @@ class stock_pack_operation(osv.osv):
|
||||||
prod_quants = self._get_remaining_prod_quantities(cr, uid, op, context=context)
|
prod_quants = self._get_remaining_prod_quantities(cr, uid, op, context=context)
|
||||||
for product_id, qty in prod_quants.items():
|
for product_id, qty in prod_quants.items():
|
||||||
if qty > 0:
|
if qty > 0:
|
||||||
if op.product_id.type != 'consu':
|
|
||||||
quants_reserve_ok = False
|
|
||||||
remaining_qty_ok = remaining_qty_ok and _create_link_for_product(product_id, qty)
|
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()])
|
quants_reserve_ok = all([quants_done[x] == 0 for x in quants_done.keys()])
|
||||||
|
|
Loading…
Reference in New Issue