From a763059d3301c4fe41548067765de2006cc3fc4f Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Fri, 28 Jun 2013 17:40:36 +0200 Subject: [PATCH 1/5] [WIP] stock: packaging bzr revid: qdp-launchpad@openerp.com-20130628154036-nss4uj17zj9zrr2g --- addons/stock/stock.py | 119 +++++++++++++++++++++++++++++------------- 1 file changed, 84 insertions(+), 35 deletions(-) diff --git a/addons/stock/stock.py b/addons/stock/stock.py index 48ef01a0634..db3923acbbb 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -1480,8 +1480,57 @@ class stock_picking(osv.osv): return super(stock_picking, self).unlink(cr, uid, ids, context=context) + #TODO move this in another class? + def get_done_reserved_quants(self, cr, uid, picking_id, move, context=None): + stock_operation_obj = self.pool.get('stock.pack.operation') + quant_obj = self.pool.get('stock.quant') + possible_quants = [x.id for x in move.reserved_quant_ids] + operation_ids = stock_operation_obj.find_packaging_op_from_product(cr, uid, move.product_id, picking_id, context=context) + todo_later = [] + possible_quants = [quant.id for quant in move.reserved_quant_ids] + done_reserved_quants = set() + for op in stock_operation_obj.browse(cr, uid, operation_ids, context=context): + if op.product_id: + #TODO: document me + todo_later += [op.id] + elif op.quant_id: + #split for partial and take care of reserved quants + 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) + done_reserved_quants = done_reserved_quants.union(set([qt[O] for qt in quant_tuples])) + elif op.package_id: + #moving a package never splits quants but we need to take care of the reserved_quant_ids + all_children_quants = self.pool.get('stock.quant.package').find_all_quants(cr, uid, op.package_id, context=context) + done_reserved_quants = done_reserved_quants.union(set(all_chilren_quants)) + #finish the partial split by operation that leaves the choice of quant to move + for op in stock_operation_obj.browse(cr, uid, todo_later, context=context): + 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) + done_reserved_quants = done_reserved_quants.union(set([qt[O] for qt in quant_tuples])) + return done_reserved_quants + + #TODO move this in another class? + def make_packaging(self, cr, uid, picking_id, move, possible_quants, context=None): + stock_operation_obj = self.pool.get('stock.pack.operation') + quant_obj = self.pool.get('stock.quant') + operation_ids = stock_operation_obj.find_packaging_op_from_product(cr, uid, move.product_id, picking_id, context=context) + for op in stock_operation_obj.browse(cr, uid, operation_ids, context=context): + if not op.result_package_id: + continue + 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) + def do_partial(self, cr, uid, ids, partial_datas, context=None): """ Makes partial picking and moves done. @@ -1547,10 +1596,10 @@ class stock_picking(osv.osv): 'pack_operation_ids': unlink_operation_order }) if product_qty != 0: + #take care of partial picking in reserved quants + done_reserved_quants = self.get_done_reserved_quants(cr, uid, picking_id, move, context=context) #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 @@ -1559,12 +1608,13 @@ class stock_picking(osv.osv): 'move_dest_id': False, 'price_unit': product_price, 'product_uom': product_uoms[move.id], - 'reserved_quant_ids': done_quant_ids + 'reserved_quant_ids': [] #free the reserved_quant_ids that moved } prodlot_id = prodlot_ids[move.id] if prodlot_id: defaults.update(prodlot_id=prodlot_id) - move_obj.copy(cr, uid, move.id, defaults) + backorder_move_id = move_obj.copy(cr, uid, move.id, defaults) + self.make_packaging(cr, uid, picking_id, move_obj.browse(cr, uid, backorder_move_id, context=context), list(done_reserved_quants), context=context) #modify the existing stock move move_obj.write(cr, uid, [move.id], { @@ -1572,7 +1622,7 @@ class stock_picking(osv.osv): '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 + 'reserved_quant_ids': list(set(possible_quants) - done_reserved_quants), }) if new_picking: @@ -1584,24 +1634,9 @@ class stock_picking(osv.osv): move_obj.write(cr, uid, [move.id], defaults) + #take care of packaging for completed moves 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) - + self.make_packaging(cr, uid, picking_id, move, possible_quants, context=context) @@ -1619,6 +1654,8 @@ class stock_picking(osv.osv): defaults.update(picking_id=new_picking) move_obj.write(cr, uid, [move.id], defaults) + possible_quants = [x.id for x in move.reserved_quant_ids] + self.make_packaging(cr, uid, picking_id, move, possible_quants, context=context) # At first we confirm the new picking (if necessary) if new_picking: self.signal_button_confirm(cr, uid, [new_picking]) @@ -1730,6 +1767,7 @@ class stock_picking(osv.osv): return self._get_picking_for_packing_ui(cr, uid, context=context) def action_pack(self, cr, uid, picking_id, context=None): + #put all the operations of the picking that aren't yet assigned to a package to this new one stock_operation_obj = self.pool.get('stock.pack.operation') package_obj = self.pool.get('stock.quant.package') #create a new empty stock.quant.package @@ -2062,7 +2100,7 @@ class stock_move(osv.osv): 'scrapped': fields.related('location_dest_id','scrap_location',type='boolean',relation='stock.location',string='Scrapped', readonly=True), 'type': fields.related('picking_id', 'type', type='selection', selection=[('out', 'Sending Goods'), ('in', 'Getting Goods'), ('internal', 'Internal')], string='Shipping Type'), 'reserved_quant_ids': fields.one2many('stock.quant', 'reservation_id', 'Reserved quants'), - 'remaining_qty': fields.float('Remaining Quantity', digits_compute=dp.get_precision('Product Unit of Measure'), states={'done': [('readonly', True)]}), # to be used in pick/pack new interface + 'remaining_qty': fields.float('Remaining Quantity', digits_compute=dp.get_precision('Product Unit of Measure'), states={'done': [('readonly', True)]}), # to be used in pick/pack new interface # TODO change this in a functional field to ease the handling } def _check_location(self, cr, uid, ids, context=None): @@ -3802,23 +3840,33 @@ class stock_package(osv.osv): def action_copy(self, cr, uid, ids, context=None): quant_obj = self.pool.get('stock.quant') stock_operation_obj = self.pool.get('stock.pack.operation') - #put all the operations of the picking that aren't yet assigned to a package to this new one + #search all the operations of given package operation_ids = stock_operation_obj.search(cr, uid, [('result_package_id', 'in', ids)], context=context) #create a new empty stock.quant.package package_id = self.create(cr, uid, {}, context=context) new_ops = [] + #copy all operation and set the newly created package as result_package_id for op in operation_ids: new_ops += [stock_operation_obj.copy(cr, uid, op, {'result_package_id': package_id}, context=context)] - for operation in stock_operation_obj.browse(cr, uid, new_ops, context=context): - if operation.product_id: - todo_on_moves, todo_on_operations = stock_operation_obj._search_and_increment(cr, uid, operation.picking_id.id, ('product_id', '=', operation.product_id.id), context=context) - elif operation.quant_id: - todo_on_moves, todo_on_operations = self._deal_with_quants(cr, uid, operation.picking_id, [operation.quant_id.id], context=context) - elif operation.package_id: - included_package_ids = self.search(cr, uid, [('parent_id', 'child_of', [operation.package_id.id])], context=context) - included_quant_ids = quant_obj.search(cr, uid, [('package_id', 'in', included_package_ids)], context=context) - todo_on_moves, todo_on_operations = self._deal_with_quants(cr, uid, operation.picking_id.id, included_quant_ids, context=context) - return {'warnings': '', 'moves_to_update': todo_on_moves, 'operations_to_update': todo_on_operations} + + # for operation in stock_operation_obj.browse(cr, uid, new_ops, context=context): + # if operation.product_id: + # todo_on_moves, todo_on_operations = stock_operation_obj._search_and_increment(cr, uid, operation.picking_id.id, ('product_id', '=', operation.product_id.id), context=context) + # elif operation.quant_id: + # todo_on_moves, todo_on_operations = self._deal_with_quants(cr, uid, operation.picking_id, [operation.quant_id.id], context=context) + # elif operation.package_id: + # included_package_ids = self.search(cr, uid, [('parent_id', 'child_of', [operation.package_id.id])], context=context) + # included_quant_ids = quant_obj.search(cr, uid, [('package_id', 'in', included_package_ids)], context=context) + # todo_on_moves, todo_on_operations = self._deal_with_quants(cr, uid, operation.picking_id.id, included_quant_ids, context=context) + # return {'warnings': '', 'moves_to_update': todo_on_moves, 'operations_to_update': todo_on_operations} + + def find_all_quants(self, cr, uid, package_record, context=None): + ''' find all the quants in the given package (browse record) recursively''' + res = [] + for child in package_record.children_ids: + res += self.find_all_quants(cr, uid, child, context=context) + res += [qt.id for qt in package_record.quant_ids] + return res #def action_delete(self, cr, uid, ids, context=None): # #no need, we use unlink of ids and with the ondelete = cascade it will work flawlessly @@ -3854,6 +3902,8 @@ class stock_pack_operation(osv.osv): 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): + #returns all ops that touches this product + #TOCHECK: don't we need to take only the ops with a result_package_id != False ? res = [] op_ids = self.search(cr, uid, [('picking_id', '=', picking_id)], context=context) for operation in self.browse(cr, uid, op_id, context=context): @@ -3865,7 +3915,6 @@ class stock_pack_operation(osv.osv): 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): From e84f7798096bf417759a9d842dbf5cd846883ce6 Mon Sep 17 00:00:00 2001 From: Josse Colpaert Date: Fri, 28 Jun 2013 17:48:21 +0200 Subject: [PATCH 2/5] [IMP] Pass quants to chained moved as reserved quants + rebrowse move in negative quants bzr revid: jco@openerp.com-20130628154821-pj3ala9gynrz53pb --- addons/stock/stock.py | 44 +++++++++++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/addons/stock/stock.py b/addons/stock/stock.py index db3923acbbb..bcf04c56124 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -1027,7 +1027,7 @@ class stock_picking(osv.osv): # TODO: Check locations to see if in the same location ? return True - def check_assign(self, cr, uid, ids, *args): + def action_assign(self, cr, uid, ids, *args): """ Changes state of picking to available if all moves are confirmed. @return: True """ @@ -1088,8 +1088,6 @@ class stock_picking(osv.osv): """ Changes picking state to assigned. @return: True """ - for picking in self.browse(cr, uid, ids, context=context): - self.pool.get('stock.move').action_assign(cr, uid, [move.id for move in picking.move_lines]) self.write(cr, uid, ids, {'state': 'assigned'}) return True @@ -1600,6 +1598,7 @@ class stock_picking(osv.osv): done_reserved_quants = self.get_done_reserved_quants(cr, uid, picking_id, move, context=context) #copy the stock move new_picking_record = self.browse(cr, uid, new_picking, context=context) + defaults = { 'product_qty' : product_qty, 'product_uos_qty': product_qty, #TODO: put correct uos_qty @@ -1636,6 +1635,7 @@ class stock_picking(osv.osv): #take care of packaging for completed moves possible_quants = [x.id for x in move.reserved_quant_ids] + self.make_packaging(cr, uid, picking_id, move, possible_quants, context=context) @@ -2633,13 +2633,26 @@ class stock_move(osv.osv): #Convert UoM qty -> check rounding now in product_reserver #Split for source locations qty = uom_obj._compute_qty(cr, uid, move.product_uom.id, move.product_qty, move.product_id.uom_id.id) - res2 = quant_obj.choose_quants(cr, uid, move.location_id.id, move.product_id.id, qty, prodlot_id = move.prodlot_id.id, context=context) - print "Choose quants:", res2 - if res2: - quant_obj.split_and_assign_quants(cr, uid, res2, move, context=context) - #self.write(cr, uid, [move.id], {'state':'assigned'}) + + # Check if this move has not been chained from another move + moves_from = self.search(cr, uid, [('move_dest_id', '=', move.id)], context=context) + if moves_from and len(moves_from) == 1: + move_from = moves_from[0] + quants = quant_obj.search(cr, uid, [('history_ids', 'in', move_from), ('location_id', '=', move.location_id.id), ('reservation_id', '=', False)], context=context) + if quants: + quant_obj.write(cr, uid, quants, {'reservation_id':move.id}, context=context) + else: done.append(move.id) pickings[move.picking_id.id] = 1 + else: + + res2 = quant_obj.choose_quants(cr, uid, move.location_id.id, move.product_id.id, qty, prodlot_id = move.prodlot_id.id, context=context) + print "Choose quants:", res2 + if res2: + quant_obj.split_and_assign_quants(cr, uid, res2, move, context=context) + #self.write(cr, uid, [move.id], {'state':'assigned'}) + done.append(move.id) + pickings[move.picking_id.id] = 1 print "Reserved quants:", move.reserved_quant_ids if done: count += len(done) @@ -2883,10 +2896,13 @@ class stock_move(osv.osv): #Check if the entire quantity has been transformed in to quants if qty_from_move > product_qty: quant_tuples = quant_obj.choose_quants(cr, uid, move.location_id.id, move.product_id.id, qty_from_move - product_qty, prodlot_id = move.prodlot_id.id, context=context) + print quant_tuples create_neg_quant = True if quant_tuples: quant_obj.split_and_assign_quants(cr, uid, quant_tuples, move, context=context) product_qty = 0.0 + #Reread move: + move = self.browse(cr, uid, move.id, context=context) for quant in move.reserved_quant_ids: product_qty += quant.qty if qty_from_move <= product_qty: @@ -2931,6 +2947,7 @@ class stock_move(osv.osv): todo = [] uom_obj = self.pool.get("product.uom") + quant_obj = self.pool.get("stock.quant") #Do price calc on move quants = {} for move in self.browse(cr, uid, ids, context=context): @@ -2942,11 +2959,12 @@ class stock_move(osv.osv): else: #move quants should resolve negative quants in destination self.check_total_qty(cr, uid, ids, context=context) + move = self.browse(cr, uid, move.id, context=context) reconciled_quants = self.pool.get("stock.quant").move_quants(cr, uid, [x.id for x in move.reserved_quant_ids], move, context=context) quants[move.id] += reconciled_quants self.splitforputaway(cr, uid, ids, context=context) - #Do price calculation on move -> Should pass Quants here -> is a dictionary + #Do price calculation on move -> Should pass reconciled Quants -> is a dictionary matchresults = self.price_calculation(cr, uid, ids, quants, context=context) for move in self.browse(cr, uid, ids, context=context): @@ -2964,6 +2982,12 @@ class stock_move(osv.osv): self.write(cr, uid, [move.id], {'move_history_ids': [(4, move.move_dest_id.id)]}) if move.move_dest_id.state in ('waiting', 'confirmed'): self.force_assign(cr, uid, [move.move_dest_id.id], context=context) + #We can take over used quants in this move to be propagated to next move + #TODO should take into account split quantities? + quants = quant_obj.search(cr, uid, [('history_ids', 'in', move.id), ('location_id', '=', move.location_dest_id.id), ('reservation_id', '=', False)], context=context) + if quants: + print "PROPAGATE QUANTS: ", quants + quant_obj.write(cr, uid, quants, {'reservation_id':move.move_dest_id.id}, context=context) if move.move_dest_id.picking_id: wf_service.trg_write(uid, 'stock.picking', move.move_dest_id.picking_id.id, cr) if move.move_dest_id.auto_validate: @@ -3906,7 +3930,7 @@ class stock_pack_operation(osv.osv): #TOCHECK: don't we need to take only the ops with a result_package_id != False ? res = [] op_ids = self.search(cr, uid, [('picking_id', '=', picking_id)], context=context) - for operation in self.browse(cr, uid, op_id, context=context): + for operation in self.browse(cr, uid, op_ids, 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: From 382047708851e29738ad6ff9f87e5be6c5f2e4c1 Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Fri, 28 Jun 2013 17:57:32 +0200 Subject: [PATCH 3/5] [WIP] stock:partial picking bzr revid: qdp-launchpad@openerp.com-20130628155732-3zguaqbouu16vdt1 --- addons/stock/static/src/js/widgets.js | 2 +- addons/stock/stock.py | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/addons/stock/static/src/js/widgets.js b/addons/stock/static/src/js/widgets.js index a8dc6143c69..ae773bc0a37 100644 --- a/addons/stock/static/src/js/widgets.js +++ b/addons/stock/static/src/js/widgets.js @@ -221,7 +221,7 @@ function openerp_picking_widgets(instance){ var self = this; console.log('Done'); new instance.web.Model('stock.picking') - .call('action_done_from_packing_ui',[[self.picking.id]]) + .call('action_done_from_packing_ui',[self.picking.id]) .then(function(new_picking_id){ console.log('New picking id:',new_picking_id); //return self.refresh_ui(new_picking_id); diff --git a/addons/stock/stock.py b/addons/stock/stock.py index bcf04c56124..be2bd3f965e 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -1580,6 +1580,10 @@ class stock_picking(osv.osv): 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, @@ -1589,10 +1593,10 @@ class stock_picking(osv.osv): #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 }) + done_reserved_quants = set() if product_qty != 0: #take care of partial picking in reserved quants done_reserved_quants = self.get_done_reserved_quants(cr, uid, picking_id, move, context=context) @@ -1615,6 +1619,7 @@ class stock_picking(osv.osv): backorder_move_id = move_obj.copy(cr, uid, move.id, defaults) self.make_packaging(cr, uid, picking_id, move_obj.browse(cr, uid, backorder_move_id, context=context), list(done_reserved_quants), context=context) #modify the existing stock move + possible_quants = [x.id for x in move.reserved_quant_ids] move_obj.write(cr, uid, [move.id], { 'product_qty': move.product_qty - partial_qty[move.id], From 590ca334283a209daf16857e86fd55dd4ec356d9 Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Fri, 28 Jun 2013 17:58:56 +0200 Subject: [PATCH 4/5] [WIP] stock:partial picking bzr revid: qdp-launchpad@openerp.com-20130628155856-g4cdgeuqxaq62n9x --- addons/stock/stock.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/addons/stock/stock.py b/addons/stock/stock.py index be2bd3f965e..2555477082e 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -1699,7 +1699,8 @@ class stock_picking(osv.osv): return res and res[1] or False def _get_picking_for_packing_ui(self, cr, uid, context=None): - return self.search(cr, uid, [('state', '=', 'assigned')], limit=1, context=context)[0] + res = self.search(cr, uid, [('state', '=', 'assigned')], limit=1, context=context) + return res and res[0] or False # TODO: what to do if nothing is left to do? def action_done_from_packing_ui(self, cr, uid, picking_id, context=None): if context is None: From 3bef5925a4dd1d15a553b281221591ca10d32ac5 Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Fri, 28 Jun 2013 18:08:44 +0200 Subject: [PATCH 5/5] [WIP] stock:partial picking bzr revid: qdp-launchpad@openerp.com-20130628160844-87o0zhfpeut4g3ya --- addons/stock/stock.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/addons/stock/stock.py b/addons/stock/stock.py index 2555477082e..c2fec100806 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -1599,7 +1599,7 @@ class stock_picking(osv.osv): done_reserved_quants = set() if product_qty != 0: #take care of partial picking in reserved quants - done_reserved_quants = self.get_done_reserved_quants(cr, uid, picking_id, move, context=context) + done_reserved_quants = self.get_done_reserved_quants(cr, uid, pick.id, move, context=context) #copy the stock move new_picking_record = self.browse(cr, uid, new_picking, context=context) @@ -1611,13 +1611,13 @@ class stock_picking(osv.osv): 'move_dest_id': False, 'price_unit': product_price, 'product_uom': product_uoms[move.id], - 'reserved_quant_ids': [] #free the reserved_quant_ids that moved + 'reserved_quant_ids': list(done_reserved_quants) } prodlot_id = prodlot_ids[move.id] if prodlot_id: defaults.update(prodlot_id=prodlot_id) backorder_move_id = move_obj.copy(cr, uid, move.id, defaults) - self.make_packaging(cr, uid, picking_id, move_obj.browse(cr, uid, backorder_move_id, context=context), list(done_reserved_quants), context=context) + self.make_packaging(cr, uid, pick.id, move_obj.browse(cr, uid, backorder_move_id, context=context), list(done_reserved_quants), context=context) #modify the existing stock move possible_quants = [x.id for x in move.reserved_quant_ids] move_obj.write(cr, uid, [move.id], @@ -2647,7 +2647,6 @@ class stock_move(osv.osv): quants = quant_obj.search(cr, uid, [('history_ids', 'in', move_from), ('location_id', '=', move.location_id.id), ('reservation_id', '=', False)], context=context) if quants: quant_obj.write(cr, uid, quants, {'reservation_id':move.id}, context=context) - else: done.append(move.id) pickings[move.picking_id.id] = 1 else: