Skip to content
Permalink
Browse files

[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 #32520

Signed-off-by: Simon Lejeune (sle) <sle@openerp.com>
  • Loading branch information...
ndeodoo committed Apr 8, 2019
1 parent 6cbecce commit 62f98e34c8aa0fbc1755fec9919396c853c171dc
Showing with 24 additions and 12 deletions.
  1. +24 −12 addons/stock_account/models/product.py
@@ -201,18 +201,30 @@ def _compute_stock_value(self):
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,20 +240,20 @@ def _compute_stock_value(self):
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, [])
product.stock_value = value
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, [])

0 comments on commit 62f98e3

Please sign in to comment.
You can’t perform that action at this time.