From 277c870de711d877e72e4fd5d28540ffd19f891f Mon Sep 17 00:00:00 2001 From: Josse Colpaert Date: Thu, 18 Sep 2014 15:50:41 +0200 Subject: [PATCH 1/2] [FIX] Previous move subtleties --- addons/mrp/mrp.py | 9 +++++---- addons/stock/stock.py | 21 ++++++++++----------- addons/stock/test/packing.yml | 2 +- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/addons/mrp/mrp.py b/addons/mrp/mrp.py index 5add8703614..db62e265430 100644 --- a/addons/mrp/mrp.py +++ b/addons/mrp/mrp.py @@ -1074,12 +1074,13 @@ class mrp_production(osv.osv): type_obj = self.pool.get('stock.picking.type') # Need to search for a picking type move = stock_move.browse(cr, uid, move_id, context=context) - code = stock_move.get_code_from_locs(cr, uid, move, context=context) + src_loc = loc_obj.browse(cr, uid, source_location_id, context=context) + dest_loc = loc_obj.browse(cr, uid, dest_location_id, context=context) + code = stock_move.get_code_from_locs(cr, uid, move, src_loc, dest_loc, context=context) if code == 'outgoing': - check_loc_id = source_location_id + check_loc = src_loc else: - check_loc_id = dest_location_id - check_loc = loc_obj.browse(cr, uid, check_loc_id, context=context) + check_loc = dest_loc wh = loc_obj.get_warehouse(cr, uid, check_loc, context=context) domain = [('code', '=', code)] if wh: diff --git a/addons/stock/stock.py b/addons/stock/stock.py index 9e3c8cf69ea..83b7977cc4b 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -383,7 +383,7 @@ class stock_quant(osv.osv): self.pool.get('stock.move').write(cr, uid, [move.id], {'partially_available': True}, context=context) def quants_move(self, cr, uid, quants, move, location_to, location_from=False, lot_id=False, owner_id=False, src_package_id=False, dest_package_id=False, context=None): - """Moves all given stock.quant in the given destination location. + """Moves all given stock.quant in the given destination location. Unreserve from current move. :param quants: list of tuple(browse record(stock.quant) or None, quantity to move) :param move: browse record (stock.move) :param location_to: browse record (stock.location) depicting where the quants have to be moved @@ -418,7 +418,8 @@ class stock_quant(osv.osv): def move_quants_write(self, cr, uid, quants, move, location_dest_id, dest_package_id, context=None): vals = {'location_id': location_dest_id.id, 'history_ids': [(4, move.id)], - 'package_id': dest_package_id} + 'package_id': dest_package_id, + 'reservation_id': False} self.write(cr, SUPERUSER_ID, [q.id for q in quants], vals, context=context) def quants_get_prefered_domain(self, cr, uid, location, product, qty, domain=None, prefered_domain_list=[], restrict_lot_id=False, restrict_partner_id=False, context=None): @@ -2304,15 +2305,10 @@ class stock_move(osv.osv): qty = move_qty[move.id] quants = quant_obj.quants_get_prefered_domain(cr, uid, move.location_id, move.product_id, qty, domain=main_domain, prefered_domain_list=prefered_domain_list, restrict_lot_id=move.restrict_lot_id.id, restrict_partner_id=move.restrict_partner_id.id, context=context) quant_obj.quants_move(cr, uid, quants, move, move.location_dest_id, lot_id=move.restrict_lot_id.id, owner_id=move.restrict_partner_id.id, context=context) - #unreserve the quants and make them available for other operations/moves - quant_obj.quants_unreserve(cr, uid, move, context=context) #Check moves that were pushed if move.move_dest_id.state in ('waiting', 'confirmed'): - # FIXME is opw 607970 still present with new WMS? - # (see commits 1ef2c181033bd200906fb1e5ce35e234bf566ac6 - # and 41c5ceb8ebb95c1b4e98d8dd1f12b8e547a24b1d) - other_upstream_move_ids = self.search(cr, uid, [('id', '!=', move.id), ('state', 'not in', ['done', 'cancel']), + other_upstream_move_ids = self.search(cr, uid, [('id', 'not in', ids), ('state', 'not in', ['done', 'cancel']), ('move_dest_id', '=', move.move_dest_id.id)], context=context) #If no other moves for the move that got pushed: if not other_upstream_move_ids and move.move_dest_id.state in ('waiting', 'confirmed'): @@ -2320,6 +2316,8 @@ class stock_move(osv.osv): if move.procurement_id: procurement_ids.append(move.procurement_id.id) + #unreserve the quants and make them available for other operations/moves + quant_obj.quants_unreserve(cr, uid, move, context=context) # Check the packages have been placed in the correct locations self._check_package_from_moves(cr, uid, ids, context=context) #set the move as done @@ -2443,14 +2441,15 @@ class stock_move(osv.osv): return self.action_confirm(cr, uid, [new_move], context=context)[0] - def get_code_from_locs(self, cr, uid, move, context=None): + def get_code_from_locs(self, cr, uid, move, location_id=False, location_dest_id=False, context=None): """ Returns the code the picking type should have. This can easily be used to check if a move is internal or not + move, location_id and location_dest_id are browse records """ code = 'internal' - src_loc = move.location_id - dest_loc = move.location_dest_id + src_loc = location_id or move.location_id + dest_loc = location_dest_id or move.location_dest_id if src_loc.usage == 'internal' and dest_loc.usage != 'internal': code = 'outgoing' if src_loc.usage != 'internal' and dest_loc.usage == 'internal': diff --git a/addons/stock/test/packing.yml b/addons/stock/test/packing.yml index b889d93419d..22be2e82220 100644 --- a/addons/stock/test/packing.yml +++ b/addons/stock/test/packing.yml @@ -138,13 +138,13 @@ !python {model: stock.picking}: | backorder_ids = self.search(cr, uid, [('backorder_id', '=', ref('delivery_order1'))], context=context) assert backorder_ids, "Backorder should have been created" + self.action_assign(cr, uid, backorder_ids, context=context) self.do_prepare_partial(cr, uid, backorder_ids, context=context) picking = self.browse(cr, uid, backorder_ids[0]) assert len(picking.pack_operation_ids) == 2, "Wrong number of pack operation" for pack_op in picking.pack_operation_ids: assert pack_op.product_qty == 1, "Wrong quantity in pack operation (%s found instead of 1)" % (pack_op.product_qty) assert pack_op.package_id.name in ('Pallet 2', 'Pallet 3'), "Wrong pallet info in pack operation (%s found)" % (pack_op.package_id.name) - self.action_assign(cr, uid, backorder_ids, context=context) self.do_transfer(cr, uid, backorder_ids, context=context) - Check there are still 0 pieces in stock From ac2d50d27aa2113c6e547626415d67d32d2d336a Mon Sep 17 00:00:00 2001 From: Josse Colpaert Date: Fri, 19 Sep 2014 09:35:23 +0200 Subject: [PATCH 2/2] [IMP] Assign all destination moves at once, add packaging --- addons/delivery/stock.py | 8 +++--- addons/product/product_view.xml | 41 +++++++++++++++++++++++++++ addons/sale_stock/sale_stock_view.xml | 2 +- addons/stock/stock.py | 21 +++++++------- 4 files changed, 57 insertions(+), 15 deletions(-) diff --git a/addons/delivery/stock.py b/addons/delivery/stock.py index 6f2d2a07ca0..7bfd52df420 100644 --- a/addons/delivery/stock.py +++ b/addons/delivery/stock.py @@ -56,13 +56,13 @@ class stock_picking(osv.osv): 'volume': fields.float('Volume'), 'weight': fields.function(_cal_weight, type='float', string='Weight', digits_compute= dp.get_precision('Stock Weight'), multi='_cal_weight', store={ - 'stock.picking': (lambda self, cr, uid, ids, c={}: ids, ['move_lines'], 20), - 'stock.move': (_get_picking_line, ['product_id','product_qty','product_uom','product_uos_qty'], 20), + 'stock.picking': (lambda self, cr, uid, ids, c={}: ids, ['move_lines'], 40), + 'stock.move': (_get_picking_line, ['picking_id', 'product_id','product_uom_qty','product_uom'], 40), }), 'weight_net': fields.function(_cal_weight, type='float', string='Net Weight', digits_compute= dp.get_precision('Stock Weight'), multi='_cal_weight', store={ - 'stock.picking': (lambda self, cr, uid, ids, c={}: ids, ['move_lines'], 20), - 'stock.move': (_get_picking_line, ['product_id','product_qty','product_uom','product_uos_qty'], 20), + 'stock.picking': (lambda self, cr, uid, ids, c={}: ids, ['move_lines'], 40), + 'stock.move': (_get_picking_line, ['picking_id', 'product_id','product_uom_qty','product_uom'], 40), }), 'carrier_tracking_ref': fields.char('Carrier Tracking Ref'), 'number_of_packages': fields.integer('Number of Packages'), diff --git a/addons/product/product_view.xml b/addons/product/product_view.xml index 482f31b22eb..4dd3f47776d 100644 --- a/addons/product/product_view.xml +++ b/addons/product/product_view.xml @@ -113,6 +113,9 @@ + + + @@ -704,6 +707,7 @@ + @@ -712,6 +716,20 @@ + + product.packaging.tree.view.product + product.packaging + + + + + + + + + + + product.packaging.form.view product.packaging @@ -737,6 +755,29 @@ + + product.packaging.form.view.without.product + product.packaging + +
+ + + + + + + + + + + + + + +
+
+
+ product.supplierinfo.form.view product.supplierinfo diff --git a/addons/sale_stock/sale_stock_view.xml b/addons/sale_stock/sale_stock_view.xml index b754a8d0c7f..0d5223a03c8 100644 --- a/addons/sale_stock/sale_stock_view.xml +++ b/addons/sale_stock/sale_stock_view.xml @@ -64,7 +64,7 @@ - + diff --git a/addons/stock/stock.py b/addons/stock/stock.py index 83b7977cc4b..973136c1ed7 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -2243,7 +2243,7 @@ class stock_move(osv.osv): self.write(cr, uid, [move.id], vals, context=context) def action_done(self, cr, uid, ids, context=None): - """ Process completly the moves given as ids and if all moves are done, it will finish the picking. + """ Process completely the moves given as ids and if all moves are done, it will finish the picking. """ context = context or {} picking_obj = self.pool.get("stock.picking") @@ -2294,6 +2294,7 @@ class stock_move(osv.osv): self.pool.get('stock.quant.package').write(cr, SUPERUSER_ID, [ops.package_id.id], {'parent_id': ops.result_package_id.id}, context=context) move_qty[move.id] -= record.qty #Check for remaining qtys and unreserve/check move_dest_id in + move_dest_ids = set() for move in self.browse(cr, uid, ids, context=context): if move_qty[move.id] > 0: # (=In case no pack operations in picking) main_domain = [('qty', '>', 0)] @@ -2306,23 +2307,23 @@ class stock_move(osv.osv): quants = quant_obj.quants_get_prefered_domain(cr, uid, move.location_id, move.product_id, qty, domain=main_domain, prefered_domain_list=prefered_domain_list, restrict_lot_id=move.restrict_lot_id.id, restrict_partner_id=move.restrict_partner_id.id, context=context) quant_obj.quants_move(cr, uid, quants, move, move.location_dest_id, lot_id=move.restrict_lot_id.id, owner_id=move.restrict_partner_id.id, context=context) - #Check moves that were pushed - if move.move_dest_id.state in ('waiting', 'confirmed'): - other_upstream_move_ids = self.search(cr, uid, [('id', 'not in', ids), ('state', 'not in', ['done', 'cancel']), - ('move_dest_id', '=', move.move_dest_id.id)], context=context) - #If no other moves for the move that got pushed: - if not other_upstream_move_ids and move.move_dest_id.state in ('waiting', 'confirmed'): - self.action_assign(cr, uid, [move.move_dest_id.id], context=context) + # If the move has a destination, add it to the list to reserve + if move.move_dest_id and move.move_dest_id.state in ('waiting', 'confirmed'): + move_dest_ids.add(move.move_dest_id.id) + if move.procurement_id: procurement_ids.append(move.procurement_id.id) - #unreserve the quants and make them available for other operations/moves - quant_obj.quants_unreserve(cr, uid, move, context=context) + #unreserve the quants and make them available for other operations/moves + quant_obj.quants_unreserve(cr, uid, move, context=context) # Check the packages have been placed in the correct locations self._check_package_from_moves(cr, uid, ids, context=context) #set the move as done self.write(cr, uid, ids, {'state': 'done', 'date': time.strftime(DEFAULT_SERVER_DATETIME_FORMAT)}, context=context) self.pool.get('procurement.order').check(cr, uid, procurement_ids, context=context) + #assign destination moves + if move_dest_ids: + self.action_assign(cr, uid, list(move_dest_ids), context=context) #check picking state to set the date_done is needed done_picking = [] for picking in picking_obj.browse(cr, uid, list(pickings), context=context):