[WIP] stock: packaging

bzr revid: qdp-launchpad@openerp.com-20130627233058-xdouvv6ir6gwpy4s
This commit is contained in:
Quentin (OpenERP) 2013-06-28 01:30:58 +02:00
parent b54dbe73e9
commit 51c679af9f
3 changed files with 162 additions and 52 deletions

View File

@ -43,9 +43,10 @@ function openerp_picking_widgets(instance){
var current_package_id = instance.session.user_context.current_package_id;
var model = this.getParent();
var rows = [];
console.log('package id',current_package_id)
_.each( model.operations, function(op){
if(current_package_id && op.package_id !== current_package_id){
if((typeof current_package_id !== 'undefined') && op.result_package_id !== current_package_id){
return;
}
rows.push({

View File

@ -522,15 +522,8 @@ class stock_quant(osv.osv):
def split_and_assign_quants(self, cr, uid, quant_tuples, move, context=None):
"""
This method will split off the quants with the specified quantity
and assign the move to this new quant by using reserved_id
Should be triggered when assigning the move
Should be executed on move only
:param quant_tuples: are the tuples from choose_quants (quant_id, qty)
"""
def real_split_quants(self, cr, uid, quant_tuples, context=None):
#TODO quants_to_reserve could be moved out of this function... maybe
quants_to_reserve = []
for quant_tuple in quant_tuples:
@ -543,6 +536,18 @@ class stock_quant(osv.osv):
new_qty = quant.qty - quant_tuple[1]
self.write(cr, uid, quant.id, {'qty': new_qty}, context=context)
quants_to_reserve.append(new_quant)
return quants_to_reserve
def split_and_assign_quants(self, cr, uid, quant_tuples, move, context=None):
"""
This method will split off the quants with the specified quantity
and assign the move to this new quant by using reserved_id
Should be triggered when assigning the move
Should be executed on move only
:param quant_tuples: are the tuples from choose_quants (quant_id, qty)
"""
quants_to_reserve = self.real_split_quants(cr, uid, quant_tuples, context=context)
self.write(cr, uid, quants_to_reserve, {'reservation_id': move.id}, context=context)
self.pool.get("stock.move").write(cr, uid, [move.id], {'reserved_quant_ids': [(4, x) for x in quants_to_reserve]}, context=context)
@ -690,19 +695,7 @@ class stock_quant(osv.osv):
return self.filter_quants_with_out_history(cr, uid, quants_rec, context=context)
def choose_quants(self, cr, uid, location_id, product_id, qty, prodlot_id=False, context=None):
"""
Use the removal strategies of product to search for the correct quants
:param location_id: child_of this location_id
:param product_id: id of product
:param qty in UoM of product
:TODOparam prodlot_id
:returns: tuples of (quant_id, qty)
"""
def _get_possible_quants(self, cr, uid, location_id, product_id, prodlot_id=False, context=None):
if self.pool.get('stock.location').get_removal_strategy(cr, uid, location_id, product_id, context=context) == 'lifo':
if prodlot_id:
possible_quants = self.search(cr, uid, [('location_id', 'child_of', location_id), ('product_id','=',product_id),
@ -719,6 +712,22 @@ class stock_quant(osv.osv):
else:
possible_quants = self.search(cr, uid, [('location_id', 'child_of', location_id), ('product_id','=',product_id),
('qty', '>', 0.0), ('reservation_id', '=', False)], order = 'in_date, id', context=context)
return possible_quants
def choose_quants(self, cr, uid, location_id, product_id, qty, prodlot_id=False, context=None):
"""
Use the removal strategies of product to search for the correct quants
:param location_id: child_of this location_id
:param product_id: id of product
:param qty in UoM of product
:TODOparam prodlot_id
:returns: tuples of (quant_id, qty)
"""
possible_quants = self._get_possible_quants(cr, uid, location_id, product_id, prodlot_id=prodlot_id, context=context)
return self._get_quant_tuples(cr, uid, possible_quants, qty, context=context)
def _get_quant_tuples(self, cr, uid, possible_quants, qty, context=None):
qty_todo = qty
res = []
for quant in self.browse(cr, uid, possible_quants, context=context):
@ -1519,20 +1528,29 @@ class stock_picking(osv.osv):
for move in too_few:
#create a backorder stock move with the remaining quantity
product_qty = move_product_qty[move.id]
if not new_picking:
#a backorder picking doesn't exist yet, create a new one
new_picking_name = pick.name
self.write(cr, uid, [pick.id],
{'name': sequence_obj.get(cr, uid,
'stock.picking.%s'%(pick.type)),
})
new_picking = self.copy(cr, uid, pick.id,
{
'name': new_picking_name,
'move_lines' : [],
'state':'draft',
})
#modify the existing picking (this trick is needed to keep the eventual workflows pointing on the first picking)
unlink_operation_order = [(2, op.id) for op in pick.pack_operation_ids]
self.write(cr, uid, [pick.id],
{'name': sequence_obj.get(cr, uid,
'stock.picking.%s'%(pick.type)),
'pack_operation_ids': unlink_operation_order
})
if product_qty != 0:
#copy the stock move
new_picking_record = self.browse(cr, uid, new_picking, context=context)
possible_quants = move.reserved_quant_ids
done_quant_ids
defaults = {
'product_qty' : product_qty,
'product_uos_qty': product_qty, #TODO: put correct uos_qty
@ -1540,18 +1558,21 @@ class stock_picking(osv.osv):
'state': 'assigned',
'move_dest_id': False,
'price_unit': product_price,
'product_uom': product_uoms[move.id]
'product_uom': product_uoms[move.id],
'reserved_quant_ids': done_quant_ids
}
prodlot_id = prodlot_ids[move.id]
if prodlot_id:
defaults.update(prodlot_id=prodlot_id)
move_obj.copy(cr, uid, move.id, defaults)
#modify the existing stock move
move_obj.write(cr, uid, [move.id],
{
'product_qty': move.product_qty - partial_qty[move.id],
'product_uos_qty': move.product_qty - partial_qty[move.id], #TODO: put correct uos_qty
'prodlot_id': False,
'tracking_id': False,
'reserved_quant_ids': quant_ids
})
if new_picking:
@ -1561,6 +1582,29 @@ class stock_picking(osv.osv):
if prodlot_ids.get(move.id):
defaults.update({'prodlot_id': prodlot_ids[move.id]})
move_obj.write(cr, uid, [move.id], defaults)
possible_quants = [x.id for x in move.reserved_quant_ids]
#TODO define find_packaing_op_from_product (returns all ops with a result_package_id that touch this product)
stock_operation_obj = self.pool.get('stock.pack.operation')
operation_ids = stock_operation_obj.find_packaging_op_from_product(cr, uid, move.product_id, picking_id, context=context)
quant_obj = self.pool.get('stock.quant')
for op in stock_operation_obj.browse(cr, uid, operation_ids, context=context):
if op.product_id:
quant_tuples = quant_obj._get_quant_tuples(cr, uid, possible_quants, op.product_qty, context=context)
quant_obj.real_split_quants(cr, uid, quant_tuples, context=context)
quant_obj.write(cr, uid, [qt[O] for qt in quant_tuples], {'package_id': op.result_package_id.id}, context=context)
elif op.quant_id:
quant_tuples = quant_obj._get_quant_tuples(cr, uid, [op.quant_id.id], op.product_qty, context=context)
quant_obj.real_split_quants(cr, uid, quant_tuples, context=context)
quant_obj.write(cr, uid, [qt[O] for qt in quant_tuples], {'package_id': op.result_package_id.id}, context=context)
elif op.package_id:
#pack existing packs
self.pool.get('stock.quant.package').write(cr, uid, op.package_id.id, {'parent_id': op.result_package_id.id}, context=context)
for move in too_many:
product_qty = move_product_qty[move.id]
defaults = {
@ -1592,7 +1636,7 @@ class stock_picking(osv.osv):
delivered_pack_id = pick.id
delivered_pack = self.browse(cr, uid, delivered_pack_id, context=context)
res[pick.id] = {'delivered_picking': delivered_pack.id or False}
res[pick.id] = {'delivered_picking': delivered_pack.id}
return res
@ -1616,22 +1660,72 @@ class stock_picking(osv.osv):
return self.search(cr, uid, [('state', '=', 'assigned')], limit=1, context=context)[0]
def action_done_from_packing_ui(self, cr, uid, picking_id, context=None):
#fill all the packages with assigned operations
for operation in self.browse(cr, uid, picking_id, context=context).pack_operation_ids:
if operation.result_package_id:
if operation.package_id:
#pack existing packs
self.pool.get('stock.quant.package').write(cr, uid, operation.package_id.id, {'parent_id': operation.result_package_id.id}, context=context)
elif operation.quant_id:
if operation.quant_id.parent_id:
# decide what to do
pass
#assign_pack may split the quant and write the package on it (above test should be in that method instead)
self.pool.get('stock.quant').assign_pack(cr, uid, operation.quant_id.id, operation.product_qty, operation.result_package_id.id, context=context)
elif operation.product_id:
pass
#don't call action_done of picking because it will make all moves don, but make a partial delivery
#self.action_done(cr, uid, picking_id, context=context)
if context is None:
context = {}
#create partial picking wizard that handles the split of stock moves and the backorder if needed
ctx = context.copy()
ctx['active_ids'] = [picking_id]
ctx['active_model'] = 'stock.picking'
partial_picking_obj = self.pool.get('stock.partial.picking')
partial_wizard_id = partial_picking_obj.create(cr, uid, {}, context=ctx)
partial_wizard_result = partial_picking_obj.do_partial(cr, uid, [partial_wizard_id], context=context)
#todo_picking_id = picking_id if picking was total, it's the backorder if the picking was partial
#todo_picking_id = partial_wizard_result[picking_id]['delivered_picking']
#all stuff below should be removed except the parent packaging /!\
# all_done_quants = []
# for move in self.browse(cr, uid, todo_picking_id, context=context).move_lines:
# all_done_quants += [quant.id for quant in move.reserved_quant_ids]
#
# for operation in self.browse(cr, uid, todo_picking_id, context=context).pack_operation_ids:
# if operation.result_package_id:
# if operation.package_id:
# if operation.package_id.parent_id:
# # decide what to do ?
# pass
# #pack existing packs
# self.pool.get('stock.quant.package').write(cr, uid, operation.package_id.id, {'parent_id': operation.result_package_id.id}, context=context)
# elif operation.product_id:
# #self.split_and_assign_quants(
# pass
#
#
#
#
# if self.pool.get('stock.pack.operation').search(cr, uid, [('picking_id', '=', todo_picking_id), ('result_package_id', '!=', False)]
# pass
# #def split_and_assign_quants(self, cr, uid, quant_tuples, move, context=None):
# #fill all the packages with assigned operations
# for operation in self.browse(cr, uid, todo_picking_id, context=context).pack_operation_ids:
# if operation.result_package_id:
# if operation.package_id:
# #pack existing packs
# self.pool.get('stock.quant.package').write(cr, uid, operation.package_id.id, {'parent_id': operation.result_package_id.id}, context=context)
# elif operation.quant_id:
# if operation.quant_id.parent_id:
# # decide what to do
# pass
# #assign_pack may split the quant and write the package on it (above test should be in that method instead)
# self.pool.get('stock.quant').assign_pack(cr, uid, operation.quant_id.id, operation.product_qty, operation.result_package_id.id, context=context)
# elif operation.product_id:
# pass
# #don't call action_done of picking because it will make all moves don, but make a partial delivery
# line_ids = []
# for move in self.browse(cr, uid, picking_id, context=context).move_lines:
# line += [{
# 'product_id': move.product_id.id,
# 'quantity': move.product_qty - move.remaining_qty,
# 'product_uom': move.product_uom_id.id,
#
# }]
#
# #self.action_done(cr, uid, picking_id, context=context)
#return id of next picking to work on
return self._get_picking_for_packing_ui(cr, uid, context=context)
@ -3782,6 +3876,21 @@ class stock_pack_operation(osv.osv):
included_quant_ids = quant_obj.search(cr, uid, [('package_id', 'in', included_package_ids)], context=context)
return [quant.product_id.id for quant in quant_obj.browse(cr, uid, included_quant_ids, context=context)]
def find_packaging_op_from_product(self, cr, uid, product_id, picking_id, context=None):
res = []
op_ids = self.search(cr, uid, [('picking_id', '=', picking_id)], context=context)
for operation in self.browse(cr, uid, op_id, context=context):
if operation.product_id and operation.product_id.id == product_id:
res += [operation.id]
if operation.quant_id and operation.quant_id.product_id.id == product_id:
res += [operation.id]
if operation.package_id:
all_quants = self.pool.get('stock.quant.package').search(cr, uid, [('parent_id', 'child_of', [operation.package_id.id])], context=context)
if any([self.pool.get('stock.quant').browse(cr, uid, quant, context=context).product_id.id == product_id for quant in all_quants]):
res += [operation.id]
return res
def _search_and_increment(self, cr, uid, picking_id, key, context=None):
'''Search for an operation on an existing key in a picking, if it exists increment the qty (+1) otherwise create it

View File

@ -145,13 +145,13 @@ class stock_partial_picking(osv.osv_memory):
def _partial_move_for(self, cr, uid, move):
partial_move = {
'product_id' : move.product_id.id,
'quantity' : move.product_qty if move.state == 'assigned' else 0,
'product_uom' : move.product_uom.id,
'prodlot_id' : move.prodlot_id.id,
'move_id' : move.id,
'location_id' : move.location_id.id,
'location_dest_id' : move.location_dest_id.id,
'product_id': move.product_id.id,
'quantity': move.product_qty - move.remaining_qty if move.state == 'assigned' else 0,
'product_uom': move.product_uom.id,
'prodlot_id': move.prodlot_id.id,
'move_id': move.id,
'location_id': move.location_id.id,
'location_dest_id': move.location_dest_id.id,
}
if move.picking_id.type == 'in' and move.product_id.cost_method != 'standard':
partial_move.update(update_cost=True, **self._product_cost_for_average_update(cr, uid, move))