Skip to content

Commit

Permalink
[FIX] stock_account: stock valuation report performances
Browse files Browse the repository at this point in the history
Basically, computation of the `inventory_value` is now done
in batch instead of one by one.

In a real use case, the computation of the stock valuation
passed from 20+ minutes to less than a minute.

This revision contains an unusual SQL request:
`SELECT DISTINCT ON`
Basically, it returns the most recent line of table
product_price_history for each tuple
`(product_template_id, company_id)`
which is actually what we want, with good performances.

See postgresql doc for more information:
http://www.postgresql.org/docs/9.0/static/sql-select.html#SQL-DISTINCT

opw-641154
  • Loading branch information
beledouxdenis committed Jun 15, 2015
1 parent 0d5b015 commit 55b7f15
Showing 1 changed file with 29 additions and 11 deletions.
40 changes: 29 additions & 11 deletions addons/stock_account/wizard/stock_valuation_history.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,21 +46,39 @@ def read_group(self, cr, uid, domain, fields, groupby, offset=0, limit=None, con
if context is None:
context = {}
date = context.get('history_date')
prod_dict = {}
if 'inventory_value' in fields:
group_lines = {}
for line in res:
domain = line.get('__domain', [])
group_lines.setdefault(str(domain), self.search(cr, uid, domain, context=context))
line_ids = set()
for ids in group_lines.values():
for product_id in ids:
line_ids.add(product_id)
line_ids = list(line_ids)
cr.execute('SELECT id, product_id, price_unit_on_quant, company_id, quantity FROM stock_history WHERE id in %s', (tuple(line_ids),))
lines_rec = cr.dictfetchall()
lines_dict = dict((line['id'], line) for line in lines_rec)
product_ids = list(set(line_rec['product_id'] for line_rec in lines_rec))
products_rec = self.pool['product.product'].read(cr, uid, product_ids, ['cost_method', 'product_tmpl_id'], context=context)
products_dict = dict((product['id'], product) for product in products_rec)
cost_method_product_tmpl_ids = list(set(product['product_tmpl_id'][0] for product in products_rec if product['cost_method'] != 'real'))
cr.execute('SELECT DISTINCT ON (product_template_id, company_id) product_template_id, company_id, cost FROM product_price_history WHERE product_template_id in %s AND datetime <= %s ORDER BY product_template_id, company_id, datetime DESC', (tuple(cost_method_product_tmpl_ids), date))
histories = cr.dictfetchall()
histories_dict = {}
for history in histories:
histories_dict[(history['product_template_id'], history['company_id'])] = history['cost']
for line in res:
lines = self.search(cr, uid, line.get('__domain', []), context=context)
inv_value = 0.0
product_tmpl_obj = self.pool.get("product.template")
lines_rec = self.browse(cr, uid, lines, context=context)
for line_rec in lines_rec:
if line_rec.product_id.cost_method == 'real':
price = line_rec.price_unit_on_quant
lines = group_lines.get(str(line.get('__domain', [])))
for line_id in lines:
line_rec = lines_dict[line_id]
product = products_dict[line_rec['product_id']]
if product['cost_method'] == 'real':
price = line_rec['price_unit_on_quant']
else:
if not line_rec.product_id.id in prod_dict:
prod_dict[line_rec.product_id.id] = product_tmpl_obj.get_history_price(cr, uid, line_rec.product_id.product_tmpl_id.id, line_rec.company_id.id, date=date, context=context)
price = prod_dict[line_rec.product_id.id]
inv_value += price * line_rec.quantity
price = histories_dict.get((product['product_tmpl_id'][0], line_rec['company_id']), 0.0)
inv_value += price * line_rec['quantity']
line['inventory_value'] = inv_value
return res

Expand Down

0 comments on commit 55b7f15

Please sign in to comment.