summaryrefslogtreecommitdiff
path: root/addons
diff options
context:
space:
mode:
authorQuentin (OpenERP) <qdp-launchpad@openerp.com>2014-02-20 11:10:21 +0100
committerQuentin (OpenERP) <qdp-launchpad@openerp.com>2014-02-20 11:10:21 +0100
commitc4cdceb0e0dff2c82cd80c0cdf92c1904a0aed8f (patch)
tree3c6006d9daf71d55bf8239aa518279af37963595 /addons
parentec11ed6413fe916d413133b8571ad32f221887e7 (diff)
parentca99f5bd2443db61f17b1a63ea46f088758ee1fd (diff)
[MERGE] refactoring of do_prepare_partial in order to have better proposals, to keep already reserved quants and try to reserve full packages
bzr revid: qdp-launchpad@openerp.com-20140220101021-or4tjvofifkdi8e5
Diffstat (limited to 'addons')
-rw-r--r--addons/stock/stock.py139
1 files changed, 79 insertions, 60 deletions
diff --git a/addons/stock/stock.py b/addons/stock/stock.py
index 5c60aa33b5e..384c93ee2d4 100644
--- a/addons/stock/stock.py
+++ b/addons/stock/stock.py
@@ -319,7 +319,7 @@ class stock_quant(osv.osv):
self.write(cr, SUPERUSER_ID, toreserve, {'reservation_id': move.id, 'link_move_operation_id': link and link.id or False}, context=context)
#check if move'state needs to be set as 'assigned'
move.refresh()
- if sum([q.qty for q in move.reserved_quant_ids]) == move.product_qty and move.state in ('confirmed', 'waiting'):
+ if move.reserved_availability == move.product_qty and move.state in ('confirmed', 'waiting'):
self.pool.get('stock.move').write(cr, uid, [move.id], {'state': 'assigned'}, context=context)
def quants_move(self, cr, uid, quants, move, lot_id=False, owner_id=False, src_package_id=False, dest_package_id=False, context=None):
@@ -933,83 +933,102 @@ class stock_picking(osv.osv):
self.do_prepare_partial(cr, uid, picking_ids, context=context)
def do_prepare_partial(self, cr, uid, picking_ids, context=None):
- #TODO refactore me
context = context or {}
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 packages and delete them
+ #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):
+ packages = []
+ reserved_move = {}
+ qtys_remaining = {}
+
+ #Calculate packages, reserved quants, qtys of this picking's moves
for move in picking.move_lines:
if move.state not in ('assigned', 'confirmed'):
continue
+ packages += [x.package_id for x in move.reserved_quant_ids if x.package_id]
+ reserved_move[move.id] = set([x.id for x in move.reserved_quant_ids])
+ if move.state == 'assigned':
+ qty = move.product_qty
+ else:
+ qty = move.reserved_availability
- #Check which of the reserved quants are entirely in packages (can be in separate method)
- packages = list(set([x.package_id for x in move.reserved_quant_ids if x.package_id]))
- done_packages = []
- for pack in packages:
- cont = True
- good_pack = False
- test_pack = pack
- while cont:
- quants = pack_obj.get_content(cr, uid, [test_pack.id], context=context)
- if all([x.reservation_id.id == move.id for x in quant_obj.browse(cr, uid, quants, context=context) if x.reservation_id]):
- good_pack = test_pack.id
- if test_pack.parent_id:
- test_pack = test_pack.parent_id
- else:
- cont = False
+ #Add qty to qtys remaining
+ if qtys_remaining.get(move.product_id.id):
+ qtys_remaining[move.product_id.id] += qty
+ else:
+ qtys_remaining[move.product_id.id] = qty
+
+ # Try to find as much as possible top-level packages that can be moved
+ top_lvl_packages = set()
+ for pack in packages:
+ loop = True
+ good_pack = False
+ test_pack = pack
+ while loop:
+ quants = pack_obj.get_content(cr, uid, [test_pack.id], context=context)
+ if all([(x.reservation_id and x.reservation_id.id in [x.id for x in picking.move_lines] or False) for x in quant_obj.browse(cr, uid, quants, context=context)]):
+ good_pack = test_pack.id
+ if test_pack.parent_id:
+ test_pack = test_pack.parent_id
else:
- cont = False
- if good_pack:
- done_packages.append(good_pack)
- done_packages = list(set(done_packages))
-
- #Create package operations
- reserved = set([x.id for x in move.reserved_quant_ids])
- remaining_qty = move.product_qty
- for pack in pack_obj.browse(cr, uid, done_packages, context=context):
- quantl = pack_obj.get_content(cr, uid, [pack.id], context=context)
- for quant in quant_obj.browse(cr, uid, quantl, context=context):
- remaining_qty -= quant.qty
- quants = set(pack_obj.get_content(cr, uid, [pack.id], context=context))
- reserved -= quants
- pack_operation_obj.create(cr, uid, {
+ #stop the loop when there's no parent package anymore
+ loop = False
+ else:
+ #stop the loop when the package test_pack is not totally reserved for moves of this picking
+ #(some quants may be reserved for other picking or not reserved at all)
+ loop = False
+ 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)
+ for quant in quant_obj.browse(cr, uid, quants, context=context):
+ reserved_move[quant.reservation_id.id] -= set([quant.id])
+ qtys_remaining[quant.product_id.id] -= quant.qty
+ pack_operation_obj.create(cr, uid, {
'picking_id': picking.id,
'package_id': pack.id,
'product_qty': 1.0,
}, context=context)
- yet_to_reserve = list(reserved)
- #Create operations based on quants
- for quant in quant_obj.browse(cr, uid, yet_to_reserve, context=context):
- qty = min(quant.qty, move.product_qty)
- remaining_qty -= qty
- pack_operation_obj.create(cr, uid, {
- 'picking_id': picking.id,
- 'product_qty': qty,
- 'product_id': quant.product_id.id,
- 'lot_id': quant.lot_id and quant.lot_id.id or False,
- 'product_uom_id': quant.product_id.uom_id.id,
- 'owner_id': quant.owner_id and quant.owner_id.id or False,
- 'cost': quant.cost,
- 'package_id': quant.package_id and quant.package_id.id or False,
- }, context=context)
- if move.state == 'assigned' and remaining_qty > 0:
- #only add a line with remaining qty if we have all qty reserved (move is assigned)
- #otherwise we may be in a case where we do a partial delivery with only a few
- #available products and we don't want to propose to transfer everything
- pack_operation_obj.create(cr, uid, {
- 'picking_id': picking.id,
- 'product_qty': remaining_qty,
- 'product_id': move.product_id.id,
- 'product_uom_id': move.product_id.uom_id.id,
- 'cost': move.product_id.standard_price,
- }, context=context)
+ # Go through all remaining reserved quants and group by product, package, lot, owner
+ qtys_grouped = {}
+ for move, quant_set in reserved_move.items():
+ for quant in quant_obj.browse(cr, uid, list(quant_set), context=context):
+ qtys_remaining[quant.product_id.id] -= quant.qty
+ key = (quant.product_id.id, quant.package_id.id, quant.lot_id.id, quant.owner_id.id)
+ if qtys_grouped.get(key):
+ qtys_grouped[key] += quant.qty
+ else:
+ qtys_grouped[key] = quant.qty
+
+ # Add remaining qtys (in cases of force_assign for example)
+ for product in qtys_remaining.keys():
+ if qtys_remaining[product] > 0:
+ key = (product, False, False, False)
+ if qtys_grouped.get(key):
+ qtys_grouped[key] += qtys_remaining[product]
+ else:
+ qtys_grouped[key] = qtys_remaining[product]
+
+ # Create the necessary operations for the grouped quants and remaining qtys
+ for key, qty in qtys_grouped.items():
+ pack_operation_obj.create(cr, uid, {
+ 'picking_id': picking.id,
+ 'product_qty': qty,
+ 'product_id': key[0],
+ 'package_id': key[1],
+ 'lot_id': key[2],
+ 'owner_id': key[3],
+ 'product_uom_id': self.pool.get("product.product").browse(cr, uid, key[0], context=context).uom_id.id,
+ }, context=context)
def do_unreserve(self, cr, uid, picking_ids, context=None):
"""
@@ -1895,7 +1914,7 @@ class stock_move(osv.osv):
for move in todo_moves:
#then if the move isn't totally assigned, try to find quants without any specific domain
if move.state != 'assigned':
- qty_already_assigned = sum([q.qty for q in move.reserved_quant_ids])
+ qty_already_assigned = move.reserved_availability
qty = move.product_qty - qty_already_assigned
quants = quant_obj.quants_get_prefered_domain(cr, uid, move.location_id, move.product_id, qty, domain=main_domain[move.id], prefered_domain=prefered_domain[move.id], fallback_domain=fallback_domain[move.id], restrict_lot_id=move.restrict_lot_id.id, restrict_partner_id=move.restrict_partner_id.id, context=context)
quant_obj.quants_reserve(cr, uid, quants, move, context=context)