[WIP] stock: partial transfer and rereserve reimplementation

bzr revid: qdp-launchpad@openerp.com-20131118095021-b0mze9fuz30sanrg
This commit is contained in:
Quentin (OpenERP) 2013-11-18 10:50:21 +01:00
parent 80809a29f4
commit a4f38da847
2 changed files with 60 additions and 37 deletions

View File

@ -758,7 +758,6 @@ class stock_picking(osv.osv):
if todo_force_assign: if todo_force_assign:
self.force_assign(cr, uid, todo_force_assign, context=context) self.force_assign(cr, uid, todo_force_assign, context=context)
return True return True
def action_assign(self, cr, uid, ids, context=None): def action_assign(self, cr, uid, ids, context=None):
@ -772,7 +771,7 @@ class stock_picking(osv.osv):
move = record.move_id move = record.move_id
domain = [('product_id', '=', move.produc_id.id)] domain = [('product_id', '=', move.produc_id.id)]
if op.package_id: if op.package_id:
domain.append(('id', 'in', package_obj. _get_content_package(cr, uid, [op.package_id.id, context=context])) domain.append(('id', 'in', package_obj. _get_content_package(cr, uid, [op.package_id.id], context=context)))
elif op.quant_id: elif op.quant_id:
domain.append(('id', '=', op.quant_id.id)) domain.append(('id', '=', op.quant_id.id))
elif op.lot_id: elif op.lot_id:
@ -800,7 +799,7 @@ class stock_picking(osv.osv):
domain = build_domain(record) domain = build_domain(record)
if domain: if domain:
quants = quant_obj.quants_get(cr, uid, move.location_id, move.product_id, record.qty, domain=domain) quants = quant_obj.quants_get(cr, uid, move.location_id, move.product_id, record.qty, domain=domain)
quants_obj.quants_reserve(cr, uid, quants, move, context=context) quant_obj.quants_reserve(cr, uid, quants, move, context=context)
#if the move is still not totally available (not possible to reserve everything based on the pack operations), #if the move is still not totally available (not possible to reserve everything based on the pack operations),
#queue this move in the list to recompute based on generic action_assign of the move. #queue this move in the list to recompute based on generic action_assign of the move.
if move.state != 'assigned': if move.state != 'assigned':
@ -964,14 +963,7 @@ class stock_picking(osv.osv):
#first unreserve the quants of related picking, because this function could be used to unreserve #first unreserve the quants of related picking, because this function could be used to unreserve
#quants on several pickings in order to group the available ones on a single picking. #quants on several pickings in order to group the available ones on a single picking.
self.do_unreserve(cr, uid, picking_ids, context=context) self.do_unreserve(cr, uid, picking_ids, context=context)
return self.action_assign(cr, uid picking_ids, context=context) return self.action_assign(cr, uid, picking_ids, context=context)
#def do_rereserve(self, cr, uid, picking_ids, context=None):
# '''
# Needed for parameter create
# '''
# self.rereserve(cr, uid, picking_ids, context=context)
def do_unreserve(self, cr, uid, picking_ids, context=None): def do_unreserve(self, cr, uid, picking_ids, context=None):
""" """
@ -983,6 +975,33 @@ class stock_picking(osv.osv):
if moves_to_unreserve: if moves_to_unreserve:
self.pool.get('stock.move').do_unreserve(cr, uid, moves_to_unreserve, context=context) self.pool.get('stock.move').do_unreserve(cr, uid, moves_to_unreserve, context=context)
def do_recompute_remaining_quantities(self, cr, uid, picking_ids, context=None):
def _create_link_for_product(product_id, qty):
qty_to_assign = qty
for move in picking.move_lines:
if move.product_id.id == product_id:
qty_on_link = min(move.remaining_qty, qty_to_assign)
link_obj.create(cr, uid, {'move_id': move.id, 'operation_id': op.id, 'qty': qty_on_link}, context=context)
qty_to_assign -= qty_on_link
if qty_to_assign <= 0:
break
link_obj = self.pool.get('stock.move.operation.link')
uom_obj = self.pool.get('product.uom')
package_obj = self.pool.get('stock.quant.package')
for picking in self.browse(cr, uid, picking_ids, context=context):
for op in picking.pack_operation_ids:
to_unlink_ids = [x.id for x in op.linked_move_operation_ids]
if to_unlink_ids:
link_obj.unlink(cr, uid, to_unlink_ids, context=context)
if op.package_id:
for product_id, qty in package_obj._get_all_products_quantities(cr, uid, op.package_id.id, context=context).items():
_create_link_for_product(product_id, qty)
elif op.product_id:
normalized_qty = uom_obj._compute_qty(cr, uid, op.product_uom_id.id, op.product_qty, op.product_id.uom_id.id)
_create_link_for_product(op.product_id.id, normalized_qty)
#def _reserve_quants_ops_move(self, cr, uid, ops, move, qty, create=False, context=None): #def _reserve_quants_ops_move(self, cr, uid, ops, move, qty, create=False, context=None):
# """ # """
# Will return the quantity that could not be reserved # Will return the quantity that could not be reserved
@ -1140,8 +1159,9 @@ class stock_picking(osv.osv):
'''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 '''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
''' '''
move_obj = self.pool.get('stock.move') move_obj = self.pool.get('stock.move')
operation_obj = self.pool.get('stock.pack.operation')
for op in picking.pack_operation_ids: for op in picking.pack_operation_ids:
for product_id, remaining_qty in package_obj._get_remaining_prod_quantities(cr, uid, op, context=context).items(): for product_id, remaining_qty in operation_obj._get_remaining_prod_quantities(cr, uid, op, context=context).items():
if remaining_qty < 0: if remaining_qty < 0:
product = self.pool.get('product.product').browse(cr, uid, product_id, context=context) product = self.pool.get('product.product').browse(cr, uid, product_id, context=context)
vals = { vals = {
@ -1172,6 +1192,8 @@ class stock_picking(osv.osv):
if not context: if not context:
context = {} context = {}
stock_move_obj = self.pool.get('stock.move') stock_move_obj = self.pool.get('stock.move')
pack_obj = self.pool.get('stock.quant.package')
quant_obj = self.pool.get('stock.quant')
for picking in self.browse(cr, uid, picking_ids, context=context): for picking in self.browse(cr, uid, picking_ids, context=context):
if not picking.pack_operation_ids: if not picking.pack_operation_ids:
self.action_done(cr, uid, [picking.id], context=context) self.action_done(cr, uid, [picking.id], context=context)
@ -1387,6 +1409,7 @@ class stock_move(osv.osv):
return res return res
def _get_remaining_qty(self, cr, uid, ids, field_name, args, context=None): def _get_remaining_qty(self, cr, uid, ids, field_name, args, context=None):
uom_obj = self.pool.get('product.uom')
res = {} res = {}
for move in self.browse(cr, uid, ids, context=context): for move in self.browse(cr, uid, ids, context=context):
qty = move.product_qty qty = move.product_qty
@ -1867,7 +1890,7 @@ class stock_move(osv.osv):
for m2 in move.move_orig_ids: for m2 in move.move_orig_ids:
for q in m2.quant_ids: for q in m2.quant_ids:
prev_quant_ids.append(q.id) prev_quant_ids.append(q.id)
prefered_domain = prev_quant_ids and [(('id', 'in', prev_quant_ids)] or [] prefered_domain = prev_quant_ids and [('id', 'in', prev_quant_ids)] or []
fallback_domain = prev_quant_ids and [('id', 'not in', prev_quant_ids)] or [] fallback_domain = prev_quant_ids and [('id', 'not in', prev_quant_ids)] or []
quants = quant_obj.quants_get_prefered_domain(cr, uid, move.location_id, move.product_id, qty, domain=domain, prefered_domain=prefered_domain, fallback_domain=fallback_domain, restrict_lot_id=move.restrict_lot_id.id, restrict_partner_id=move.restrict_partner_id.id, context=context) quants = quant_obj.quants_get_prefered_domain(cr, uid, move.location_id, move.product_id, qty, domain=domain, prefered_domain=prefered_domain, fallback_domain=fallback_domain, restrict_lot_id=move.restrict_lot_id.id, restrict_partner_id=move.restrict_partner_id.id, context=context)
#Will only reserve physical quants, no negative #Will only reserve physical quants, no negative
@ -1879,7 +1902,6 @@ class stock_move(osv.osv):
self._putaway_apply(cr, uid, ids, context=context) self._putaway_apply(cr, uid, ids, context=context)
return done return done
# #
# Cancel move => cancel others move and pickings # Cancel move => cancel others move and pickings
# #
@ -3269,12 +3291,12 @@ class stock_package(osv.osv):
total += quant.qty total += quant.qty
return total return total
def _get_all_products_quantities(cr, uid, package_id, context=None): def _get_all_products_quantities(self, cr, uid, package_id, context=None):
'''This function computes the different product quantities for the given package '''This function computes the different product quantities for the given package
''' '''
quant_obj = self.pool.get('stock.quant') quant_obj = self.pool.get('stock.quant')
res = {} res = {}
for quant in quant_obj.browse(cr, uid, self._get_content_package(cr, uid, package_id, context=context)) for quant in quant_obj.browse(cr, uid, self._get_content_package(cr, uid, package_id, context=context)):
if quant.product_id.id not in res: if quant.product_id.id not in res:
res[quant.product_id.id] = 0 res[quant.product_id.id] = 0
res[quant.product_id.id] += quant.qty res[quant.product_id.id] += quant.qty
@ -3284,13 +3306,13 @@ class stock_pack_operation(osv.osv):
_name = "stock.pack.operation" _name = "stock.pack.operation"
_description = "Packing Operation" _description = "Packing Operation"
def _get_remaining_prod_quantities(cr, uid, operation, context=None): def _get_remaining_prod_quantities(self, cr, uid, operation, context=None):
'''Get the remaining quantities per product on an operation with a package. This function returns a dictionary''' '''Get the remaining quantities per product on an operation with a package. This function returns a dictionary'''
#if the operation doesn't concern a package, it's not relevant to call this function #if the operation doesn't concern a package, it's not relevant to call this function
if not operation.package_id: if not operation.package_id:
return return {operation.product_id.id: operation.remaining_qty}
#get the total of products the package contains #get the total of products the package contains
res = self.pool.get('stock.quant.package')._get_all_products_quantities(cr, uid operation.package_id.id, context=context) res = self.pool.get('stock.quant.package')._get_all_products_quantities(cr, uid, operation.package_id.id, context=context)
#reduce by the quantities linked to a move #reduce by the quantities linked to a move
for record in operation.linked_move_operation_ids: for record in operation.linked_move_operation_ids:
if record.product_id.id not in res: if record.product_id.id not in res:
@ -3299,17 +3321,18 @@ class stock_pack_operation(osv.osv):
return res return res
def _get_remaining_qty(self, cr, uid, ids, name, args, context=None): def _get_remaining_qty(self, cr, uid, ids, name, args, context=None):
uom_obj = self.pool.get('product.uom')
res = {} res = {}
for ops in self.browse(cr, uid, ids, context=context): for ops in self.browse(cr, uid, ids, context=context):
if ops.package_id or ops.quant_id: if ops.package_id:
#dont try to compute the remaining quantity for packages because it's not relevant (a package could include different products). #dont try to compute the remaining quantity for packages because it's not relevant (a package could include different products).
#should use #should use _get_remaining_prod_quantities instead
res[ops.id] = 0 res[ops.id] = 0
continue continue
qty = ops.product_qty elif ops.product_id and ops.product_uom_id:
qty = uom_obj._compute_qty(cr, uid, ops.product_uom_id.id, ops.product_qty, ops.product_id.uom_id.id)
for record in ops.linked_move_operation_ids: for record in ops.linked_move_operation_ids:
qty -= record.qty qty -= record.qty
if ops.product_id and ops.product_uom_id:
#converting the remaining quantity in the pack operation UoM #converting the remaining quantity in the pack operation UoM
qty = uom_obj._compute_qty(cr, uid, ops.product_id.uom_id.id, qty, ops.product_uom_id.id) qty = uom_obj._compute_qty(cr, uid, ops.product_id.uom_id.id, qty, ops.product_uom_id.id)
res[ops.id] = qty res[ops.id] = qty
@ -3434,7 +3457,7 @@ class stock_move_operation_link(osv.osv):
_columns = { _columns = {
'qty': fields.float('Quantity', help="Quantity of products to consider when talking about the contribution of this pack operation towards the remaining quantity of the move (and inverse). Given in the product main uom."), 'qty': fields.float('Quantity', help="Quantity of products to consider when talking about the contribution of this pack operation towards the remaining quantity of the move (and inverse). Given in the product main uom."),
'operation_id': fields.many2one('stock.warehouse', 'Warehouse', required=True, ondelete="cascade"), 'operation_id': fields.many2one('stock.pack.operation', 'Operation', required=True, ondelete="cascade"),
'move_id': fields.many2one('stock.move', 'Move', required=True, ondelete="cascade"), 'move_id': fields.many2one('stock.move', 'Move', required=True, ondelete="cascade"),
} }

View File

@ -229,9 +229,9 @@ class stock_quant(osv.osv):
class stock_move(osv.osv): class stock_move(osv.osv):
_inherit = "stock.move" _inherit = "stock.move"
def action_done(self, cr, uid, ids, negatives = False, context=None): def action_done(self, cr, uid, ids, context=None):
self.product_price_update_before_done(cr, uid, ids, context=context) self.product_price_update_before_done(cr, uid, ids, context=context)
super(stock_move, self).action_done(cr, uid, ids, negatives=negatives, context=context) super(stock_move, self).action_done(cr, uid, ids, context=context)
self.product_price_update_after_done(cr, uid, ids, context=context) self.product_price_update_after_done(cr, uid, ids, context=context)
def _store_average_cost_price(self, cr, uid, move, context=None): def _store_average_cost_price(self, cr, uid, move, context=None):