[FIX] stock_account: Performance of _compute_stock_value

On the ticket 1961412, the custommer has more than 12 millions
of stock moves. Before this commit, the search request  does
not take too much time to execute but fetching the fields on the
recordset takes a lot of time due to the 'in' in the where clause
of the associated SQL request.

This optimization permit to avoid this 'where clause' and decrease
the time to gather all the different fields. The time has been reduce
to less than one minutes where it takes approximately 20 minutes before.

closes odoo/odoo#32520

Signed-off-by: Simon Lejeune (sle) <sle@openerp.com>
This commit is contained in:
Nathan de Pryck
2019-04-11 11:41:02 +00:00
parent 6cbecced3d
commit 62f98e34c8
+24 -12
View File
@@ -201,18 +201,30 @@ class ProductProduct(models.Model):
for row in res:
fifo_automated_values[(row[0], row[1])] = (row[2], row[3], list(row[4]))
product_values = {product: 0 for product in self}
product_move_ids = {product: [] for product in self}
product_values = {product.id: 0 for product in self}
product_move_ids = {product.id: [] for product in self}
if to_date:
domain = [('product_id', 'in', self.ids), ('date', '<=', to_date)] + StockMove._get_all_base_domain()
for move in StockMove.search(domain).with_context(prefetch_fields=False):
product_values[move.product_id] += move.value
product_move_ids[move.product_id].append(move.id)
value_field_name = 'value'
else:
domain = [('product_id', 'in', self.ids)] + StockMove._get_all_base_domain()
for move in StockMove.search(domain).with_context(prefetch_fields=False):
product_values[move.product_id] += move.remaining_value
product_move_ids[move.product_id].append(move.id)
value_field_name = 'remaining_value'
StockMove.check_access_rights('read')
query = StockMove._where_calc(domain)
StockMove._apply_ir_rules(query, 'read')
from_clause, where_clause, params = query.get_sql()
query_str = """
SELECT stock_move.product_id, SUM(COALESCE(stock_move.{}, 0.0)), ARRAY_AGG(stock_move.id)
FROM {}
WHERE {}
GROUP BY stock_move.product_id
""".format(value_field_name, from_clause, where_clause)
self.env.cr.execute(query_str, params)
for product_id, value, move_ids in self.env.cr.fetchall():
product_values[product_id] = value
product_move_ids[product_id] = move_ids
for product in self:
if product.cost_method in ['standard', 'average']:
@@ -228,9 +240,9 @@ class ProductProduct(models.Model):
elif product.cost_method == 'fifo':
if to_date:
if product.product_tmpl_id.valuation == 'manual_periodic':
product.stock_value = product_values[product]
product.stock_value = product_values[product.id]
product.qty_at_date = product.with_context(company_owned=True, owner_id=False).qty_available
product.stock_fifo_manual_move_ids = StockMove.browse(product_move_ids[product])
product.stock_fifo_manual_move_ids = StockMove.browse(product_move_ids[product.id])
elif product.product_tmpl_id.valuation == 'real_time':
valuation_account_id = product.categ_id.property_stock_valuation_account_id.id
value, quantity, aml_ids = fifo_automated_values.get((product.id, valuation_account_id)) or (0, 0, [])
@@ -238,10 +250,10 @@ class ProductProduct(models.Model):
product.qty_at_date = quantity
product.stock_fifo_real_time_aml_ids = self.env['account.move.line'].browse(aml_ids)
else:
product.stock_value, moves = product_values[product], StockMove.browse(product_move_ids[product])
product.stock_value = product_values[product.id]
product.qty_at_date = product.with_context(company_owned=True, owner_id=False).qty_available
if product.product_tmpl_id.valuation == 'manual_periodic':
product.stock_fifo_manual_move_ids = moves
product.stock_fifo_manual_move_ids = StockMove.browse(product_move_ids[product.id])
elif product.product_tmpl_id.valuation == 'real_time':
valuation_account_id = product.categ_id.property_stock_valuation_account_id.id
value, quantity, aml_ids = fifo_automated_values.get((product.id, valuation_account_id)) or (0, 0, [])