From 9ac8d9830ef0d0c3616de3cdf99386fc8a812c0e Mon Sep 17 00:00:00 2001 From: Josse Colpaert Date: Mon, 14 Sep 2015 14:55:33 +0200 Subject: [PATCH] [FIX] Change price history and stock valuation report to standard_price on variant As the standard price on the product template changed towards the product variant, we should also change the product price history to be by variant. Also the inventory value calculated in the Stock Valuation report should be by variant. --- addons/product/product.py | 71 ++++++++++--------- addons/stock_account/stock_account.py | 2 +- .../wizard/stock_valuation_history.py | 16 ++--- 3 files changed, 46 insertions(+), 43 deletions(-) diff --git a/addons/product/product.py b/addons/product/product.py index 73273f85cf3..b65c53757ef 100644 --- a/addons/product/product.py +++ b/addons/product/product.py @@ -232,7 +232,7 @@ class produce_price_history(osv.osv): _columns = { 'company_id': fields.many2one('res.company', required=True), - 'product_template_id': fields.many2one('product.template', 'Product Template', required=True, ondelete='cascade'), + 'product_id': fields.many2one('product.product', 'Product', required=True, ondelete='cascade'), 'datetime': fields.datetime('Date'), 'cost': fields.float('Cost'), } @@ -418,30 +418,6 @@ class product_template(osv.osv): return product.write({'list_price': value}) - def get_history_price(self, cr, uid, product_tmpl, company_id, date=None, context=None): - if context is None: - context = {} - if date is None: - date = time.strftime(DEFAULT_SERVER_DATETIME_FORMAT) - price_history_obj = self.pool.get('product.price.history') - history_ids = price_history_obj.search(cr, uid, [('company_id', '=', company_id), ('product_template_id', '=', product_tmpl), ('datetime', '<=', date)], limit=1) - if history_ids: - return price_history_obj.read(cr, uid, history_ids[0], ['cost'], context=context)['cost'] - return 0.0 - - def _set_standard_price(self, cr, uid, product_tmpl_id, value, context=None): - ''' Store the standard price change in order to be able to retrieve the cost of a product template for a given date''' - if context is None: - context = {} - price_history_obj = self.pool['product.price.history'] - user_company = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.id - company_id = context.get('force_company', user_company) - price_history_obj.create(cr, uid, { - 'product_template_id': product_tmpl_id, - 'cost': value, - 'company_id': company_id, - }, context=context) - def _get_product_variant_count(self, cr, uid, ids, name, arg, context=None): res = {} for product in self.browse(cr, uid, ids, context=context): @@ -724,7 +700,6 @@ class product_template(osv.osv): product_template_id = super(product_template, self).create(cr, uid, vals, context=context) if not context or "create_product_product" not in context: self.create_variant_ids(cr, uid, [product_template_id], context=context) - self._set_standard_price(cr, uid, product_template_id, vals.get('standard_price', 0.0), context=context) # TODO: this is needed to set given values to first variant after creation # these fields should be moved to product as lead to confusion @@ -745,12 +720,6 @@ class product_template(osv.osv): return product_template_id def write(self, cr, uid, ids, vals, context=None): - ''' Store the standard price change in order to be able to retrieve the cost of a product template for a given date''' - if isinstance(ids, (int, long)): - ids = [ids] - if 'standard_price' in vals: - for prod_template_id in ids: - self._set_standard_price(cr, uid, prod_template_id, vals['standard_price'], context=context) res = super(product_template, self).write(cr, uid, ids, vals, context=context) if 'attribute_line_ids' in vals or vals.get('active'): self.create_variant_ids(cr, uid, ids, context=context) @@ -1184,10 +1153,44 @@ class product_product(osv.osv): 'target': 'new'} def create(self, cr, uid, vals, context=None): + ctx = dict(context or {}, create_product_product=True) + product_id = super(product_product, self).create(cr, uid, vals, context=ctx) + self._set_standard_price(cr, uid, product_id, vals.get('standard_price', 0.0), context=context) + return product_id + + def write(self, cr, uid, ids, vals, context=None): + ''' Store the standard price change in order to be able to retrieve the cost of a product for a given date''' + if isinstance(ids, (int, long)): + ids = [ids] + res = super(product_product, self).write(cr, uid, ids, vals, context=context) + if 'standard_price' in vals: + for product_id in ids: + self._set_standard_price(cr, uid, product_id, vals['standard_price'], context=context) + return res + + def _set_standard_price(self, cr, uid, product_id, value, context=None): + ''' Store the standard price change in order to be able to retrieve the cost of a product for a given date''' if context is None: context = {} - ctx = dict(context or {}, create_product_product=True) - return super(product_product, self).create(cr, uid, vals, context=ctx) + price_history_obj = self.pool['product.price.history'] + user_company = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.id + company_id = context.get('force_company', user_company) + price_history_obj.create(cr, uid, { + 'product_id': product_id, + 'cost': value, + 'company_id': company_id, + }, context=context) + + def get_history_price(self, cr, uid, product_id, company_id, date=None, context=None): + if context is None: + context = {} + if date is None: + date = time.strftime(DEFAULT_SERVER_DATETIME_FORMAT) + price_history_obj = self.pool.get('product.price.history') + history_ids = price_history_obj.search(cr, uid, [('company_id', '=', company_id), ('product_id', '=', product_id), ('datetime', '<=', date)], limit=1) + if history_ids: + return price_history_obj.read(cr, uid, history_ids[0], ['cost'], context=context)['cost'] + return 0.0 class product_packaging(osv.osv): diff --git a/addons/stock_account/stock_account.py b/addons/stock_account/stock_account.py index 3b61bcadd12..6e5a9e9830d 100644 --- a/addons/stock_account/stock_account.py +++ b/addons/stock_account/stock_account.py @@ -83,7 +83,7 @@ class account_invoice_line(osv.osv): to_unit = i_line.move_id.product_uom.id price_unit = self.pool['product.uom']._compute_price(cr, uid, from_unit, price, to_uom_id=to_unit) else: - price_unit = i_line.product_id.standard_pric + price_unit = i_line.product_id.standard_price return [ { 'type':'src', diff --git a/addons/stock_account/wizard/stock_valuation_history.py b/addons/stock_account/wizard/stock_valuation_history.py index bfbbf1d5641..cdc2016c9af 100644 --- a/addons/stock_account/wizard/stock_valuation_history.py +++ b/addons/stock_account/wizard/stock_valuation_history.py @@ -62,16 +62,16 @@ class stock_history(osv.osv): 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_rec = self.pool['product.product'].read(cr, uid, product_ids, ['cost_method', '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')) + cost_method_product_ids = list(set(product['id'] for product in products_rec if product['cost_method'] != 'real')) histories = [] - if cost_method_product_tmpl_ids: - 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)) + if cost_method_product_ids: + cr.execute('SELECT DISTINCT ON (product_id, company_id) product_id, company_id, cost FROM product_price_history WHERE product_id in %s AND datetime <= %s ORDER BY product_id, company_id, datetime DESC', (tuple(cost_method_product_ids), date)) histories = cr.dictfetchall() histories_dict = {} for history in histories: - histories_dict[(history['product_template_id'], history['company_id'])] = history['cost'] + histories_dict[(history['product_id'], history['company_id'])] = history['cost'] for line in res: inv_value = 0.0 lines = group_lines.get(str(line.get('__domain', []))) @@ -81,7 +81,7 @@ class stock_history(osv.osv): if product['cost_method'] == 'real': price = line_rec['price_unit_on_quant'] else: - price = histories_dict.get((product['product_tmpl_id'][0], line_rec['company_id']), 0.0) + price = histories_dict.get((product['id'], line_rec['company_id']), 0.0) inv_value += price * line_rec['quantity'] line['inventory_value'] = inv_value return res @@ -90,13 +90,13 @@ class stock_history(osv.osv): if context is None: context = {} date = context.get('history_date') - product_tmpl_obj = self.pool.get("product.template") + product_obj = self.pool.get("product.product") res = {} for line in self.browse(cr, uid, ids, context=context): if line.product_id.cost_method == 'real': res[line.id] = line.quantity * line.price_unit_on_quant else: - res[line.id] = line.quantity * product_tmpl_obj.get_history_price(cr, uid, line.product_id.product_tmpl_id.id, line.company_id.id, date=date, context=context) + res[line.id] = line.quantity * product_obj.get_history_price(cr, uid, line.product_id.id, line.company_id.id, date=date, context=context) return res _columns = {