From b5c8ced8ecd7cf6a270565ee70d88ff6f53dcd54 Mon Sep 17 00:00:00 2001 From: Guewen Baconnier Date: Tue, 16 Sep 2014 15:21:07 +0200 Subject: [PATCH] [IMP] stock: Optimize stock_move.setlast_tracking() When setlast_tracking is called on a large number of moves in a picking (e.g. when splitting moves in a picking), the time to complete grows exponentially. The reason is that it loops over all the moves of a picking, even if it keeps only the last tracking. The method now uses a search() with a limit so it doesn't need to browse all the moves. Added test to check the behaviour of setlast_tracking Fixes #2448 --- addons/stock/__openerp__.py | 1 + addons/stock/stock.py | 26 +++++++++------ addons/stock/test/setlast_tracking.yml | 44 ++++++++++++++++++++++++++ 3 files changed, 62 insertions(+), 9 deletions(-) create mode 100644 addons/stock/test/setlast_tracking.yml diff --git a/addons/stock/__openerp__.py b/addons/stock/__openerp__.py index dd2a996f6dd..12f42a4c2e2 100644 --- a/addons/stock/__openerp__.py +++ b/addons/stock/__openerp__.py @@ -95,6 +95,7 @@ Dashboard / Reports for Warehouse Management will include: 'test/opening_stock.yml', 'test/shipment.yml', 'test/stock_report.yml', + 'test/setlast_tracking.yml', ], 'installable': True, 'application': True, diff --git a/addons/stock/stock.py b/addons/stock/stock.py index 4535b51dd8f..f117bdbc27d 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -2214,16 +2214,24 @@ class stock_move(osv.osv): return count def setlast_tracking(self, cr, uid, ids, context=None): - tracking_obj = self.pool.get('stock.tracking') - picking = self.browse(cr, uid, ids, context=context)[0].picking_id - if picking: - last_track = [line.tracking_id.id for line in picking.move_lines if line.tracking_id] - if not last_track: - last_track = tracking_obj.create(cr, uid, {}, context=context) + assert len(ids) == 1, "1 ID expected, got %s" % (ids, ) + tracking_obj = self.pool['stock.tracking'] + move = self.browse(cr, uid, ids[0], context=context) + picking_id = move.picking_id.id + if picking_id: + move_ids = self.search(cr, uid, [ + ('picking_id', '=', picking_id), + ('tracking_id', '!=', False) + ], limit=1, order='tracking_id DESC', context=context) + if move_ids: + tracking_move = self.browse(cr, uid, move_ids[0], + context=context) + tracking_id = tracking_move.tracking_id.id else: - last_track.sort() - last_track = last_track[-1] - self.write(cr, uid, ids, {'tracking_id': last_track}) + tracking_id = tracking_obj.create(cr, uid, {}, context=context) + self.write(cr, uid, move.id, + {'tracking_id': tracking_id}, + context=context) return True # diff --git a/addons/stock/test/setlast_tracking.yml b/addons/stock/test/setlast_tracking.yml new file mode 100644 index 00000000000..eae25b05ec4 --- /dev/null +++ b/addons/stock/test/setlast_tracking.yml @@ -0,0 +1,44 @@ +- + In order to check if the last tracking is set on moves, I create a picking +- + !record {model: stock.picking, id: shipment_tracking}: + type: out + location_dest_id: stock_location_output +- + !record {model: stock.move, id: shipment_tracking_move1}: + picking_id: shipment_tracking + product_id: product_product_6 + product_uom: product.product_uom_unit + product_qty: 10.0 + location_id: location_monitor + location_dest_id: stock_location_output +- + !record {model: stock.move, id: shipment_tracking_move2}: + picking_id: shipment_tracking + product_id: product_product_6 + product_uom: product.product_uom_unit + product_qty: 10.0 + location_id: location_monitor + location_dest_id: stock_location_output +- + Then I call setlast_tracking on the moves and check if the tracking is correct +- + !python {model: stock.move}: | + move_id = ref('shipment_tracking_move1') + move = self.browse(cr, uid, move_id) + assert not move.tracking_id, "Move1 must not have a tracking at this point" + tracking_ids = self.pool['stock.tracking'].search(cr, uid, []) + self.setlast_tracking(cr, uid, [move_id]) + move.refresh() + tracking_id = move.tracking_id.id + assert tracking_id, "The move must have a tracking_id" + assert tracking_id not in tracking_ids, "The tracking must be a new one" + + move2_id = ref('shipment_tracking_move2') + move2 = self.browse(cr, uid, move2_id) + assert not move2.tracking_id, "Move2 must not have a tracking at this point" + self.setlast_tracking(cr, uid, [move2_id]) + move2.refresh() + tracking2_id = move2.tracking_id.id + assert tracking2_id, "Move2 must have a tracking_id" + assert tracking2_id == tracking_id, "The second move must have the same tracking than the previous one"