Merge lp:~camptocamp/margin-analysis/7.0-product_cost_incl_bom_price_history-mismatch-product-template into lp:~margin-analysis-core-editors/margin-analysis/7.0

Proposed by Guewen Baconnier @ Camptocamp
Status: Merged
Merged at revision: 57
Proposed branch: lp:~camptocamp/margin-analysis/7.0-product_cost_incl_bom_price_history-mismatch-product-template
Merge into: lp:~margin-analysis-core-editors/margin-analysis/7.0
Diff against target: 304 lines (+115/-46)
6 files modified
product_cost_incl_bom_price_history/product.py (+42/-33)
product_historical_margin/account_invoice_view.xml (+28/-0)
product_price_history/product_price_history.py (+14/-1)
product_price_history/product_price_history_view.xml (+26/-10)
product_price_history/wizard/historic_prices.py (+5/-1)
product_price_history/wizard/historic_prices_view.xml (+0/-1)
To merge this branch: bzr merge lp:~camptocamp/margin-analysis/7.0-product_cost_incl_bom_price_history-mismatch-product-template
Reviewer Review Type Date Requested Status
Joël Grand-Guillaume @ camptocamp code review + test Approve
Review via email: mp+201447@code.launchpad.net

Description of the change

Fixes lp:1268638

Mismatch between product.product and product.template

It expects product.template ids but receive product.product ids.

To post a comment you must log in.
58. By Guewen Baconnier @ Camptocamp

[MRG] from lp:~camptocamp/margin-analysis/7.0-product_cost_incl_bom_price_history-mismatch-product-template

59. By Joël Grand-Guillaume @ camptocamp

[FIX] The open price history button now display the product correctly by adding domain on template, not product
[IMP] Historic price view now display an inteliggent group by by default

Revision history for this message
Joël Grand-Guillaume @ camptocamp (jgrandguillaume-c2c) wrote :

Hi,

LGTM, thanks !

Just added the same support to open historic price from product form.

Regards

review: Approve (code review + test)
60. By Joël Grand-Guillaume @ camptocamp

[FIX] Add a form view on margin details to avoid a keyerror bug

Revision history for this message
Joël Grand-Guillaume @ camptocamp (jgrandguillaume-c2c) wrote :

Add a little fix in the meanwhile

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'product_cost_incl_bom_price_history/product.py'
2--- product_cost_incl_bom_price_history/product.py 2013-12-12 10:09:02 +0000
3+++ product_cost_incl_bom_price_history/product.py 2014-02-05 09:14:09 +0000
4@@ -21,11 +21,9 @@
5
6 from openerp.osv import orm, fields
7 import decimal_precision as dp
8-import openerp
9 from openerp.addons.product_price_history.product_price_history import (
10 PRODUCT_FIELD_HISTORIZE
11 )
12-from openerp import SUPERUSER_ID
13 import time
14 from datetime import datetime, timedelta
15 import logging
16@@ -60,7 +58,7 @@
17 if not field_flag:
18 field_flag = True
19 if self._columns[field_name]._multi:
20- raise ValueError('multi is not supported on the cost_price field')
21+ raise ValueError('multi is not supported on the %s field' % field_name)
22 # use admin user for accessing objects having rules defined on
23 # store fields
24 result = self._columns[field_name].get(cr, self, ids,
25@@ -71,16 +69,12 @@
26 if r in field_dict.keys():
27 if field_name in field_dict[r]:
28 result.pop(r)
29- for id, value in result.items():
30- tpl_id = self.read(cr, uid, id,
31- ['product_tmpl_id'],
32- context=context)['product_tmpl_id']
33- _logger.debug("set price history: %s, product_tpl_id: %s, "
34- "context: %s",
35- value,
36- tpl_id,
37- context)
38- prod_tpl_obj._log_price_change(cr, uid, id,
39+ prods = self.read(cr, uid, result.keys(), ['product_tmpl_id'],
40+ context=context, load='_classic_write')
41+ tmpls = dict((row['id'], row['product_tmpl_id']) for row in prods)
42+ for prod_id, value in result.iteritems():
43+ tmpl_id = tmpls[prod_id]
44+ prod_tpl_obj._log_price_change(cr, uid, tmpl_id,
45 field_name,
46 value,
47 context=context)
48@@ -101,9 +95,6 @@
49 fields = list(set(fields))
50 fields.remove('cost_price')
51 self._set_field_name_values(cr, uid, ids, 'cost_price', context)
52- _logger.debug("call _store_set_values, ids %s, fields: %s",
53- ids,
54- fields)
55 res = super(product_product, self)._store_set_values(cr,
56 uid,
57 ids,
58@@ -138,37 +129,57 @@
59 context=None, load='_classic_read'):
60 if context is None:
61 context = {}
62- if fields:
63+ if not fields:
64+ fields = []
65+ else:
66+ fields = fields[:] # avoid to modify the callee's list
67+ if fields and not 'id' in fields:
68 fields.append('id')
69 pt_obj = self.pool.get('product.template')
70+
71+ historized_fields = [f for f in fields if f in PRODUCT_FIELD_HISTORIZE]
72+ remove_tmpl_field = False
73+ if fields and not 'product_tmpl_id' in fields and historized_fields:
74+ remove_tmpl_field = True
75+ fields.append('product_tmpl_id')
76+
77 results = super(product_product, self)._read_flat(cr, uid, ids,
78 fields,
79 context=context,
80 load=load)
81 # Note if fields is empty => read all, so look at history table
82- if not fields or any([f in PRODUCT_FIELD_HISTORIZE for f in fields]):
83+ if not fields or historized_fields:
84 date_crit = False
85 price_history = self.pool.get('product.price.history')
86 company_id = pt_obj._get_transaction_company_id(cr, uid,
87 context=context)
88 if context.get('to_date'):
89 date_crit = context['to_date']
90- # if fields is empty we read all price fields
91- if not fields:
92- price_fields = PRODUCT_FIELD_HISTORIZE
93- # Otherwise we filter on price fields asked in read
94+ if load == '_classic_write':
95+ # list of ids
96+ tmpl_ids = [row['product_tmpl_id'] for row in results]
97 else:
98- price_fields = [f for f in PRODUCT_FIELD_HISTORIZE
99- if f in fields]
100- prod_prices = price_history._get_historic_price(cr, uid,
101- ids,
102- company_id,
103- datetime=date_crit,
104- field_names=price_fields,
105- context=context)
106+ # list of (id, name)
107+ tmpl_ids = [row['product_tmpl_id'][0] for row in results]
108+ prod_prices = price_history._get_historic_price(
109+ cr, uid,
110+ tmpl_ids,
111+ company_id,
112+ datetime=date_crit,
113+ field_names=historized_fields or PRODUCT_FIELD_HISTORIZE,
114+ context=context)
115 for result in results:
116- dict_value = prod_prices[result['id']]
117+ if load == '_classic_write':
118+ tmpl_id = result['product_tmpl_id']
119+ else:
120+ tmpl_id = result['product_tmpl_id'][0]
121+ dict_value = prod_prices[tmpl_id]
122 result.update(dict_value)
123+
124+ if remove_tmpl_field:
125+ for row in results:
126+ # this field was not asked by the callee
127+ del row['product_tmpl_id']
128 return results
129
130 def _product_value(self, cr, uid, ids, field_names=None,
131@@ -184,8 +195,6 @@
132 products = self.read(cr, uid, ids,
133 ['id', 'qty_available', 'cost_price'],
134 context=context)
135- _logger.debug("product value get, result :%s, context: %s",
136- products, context)
137 for product in products:
138 res[product['id']] = product['qty_available'] * product['cost_price']
139 return res
140
141=== modified file 'product_historical_margin/account_invoice_view.xml'
142--- product_historical_margin/account_invoice_view.xml 2013-11-28 15:20:12 +0000
143+++ product_historical_margin/account_invoice_view.xml 2014-02-05 09:14:09 +0000
144@@ -31,6 +31,34 @@
145 </field>
146 </record>
147
148+ <record id="view_invoice_line_form_from_product" model="ir.ui.view">
149+ <field name="name">account.invoice.line.from.product.form</field>
150+ <field name="model">account.invoice.line</field>
151+ <field name="arch" type="xml">
152+ <form string="Invoice Line" create="false">
153+ <field name="invoice_type"/>
154+ <field name="partner_id"/>
155+ <field name="invoice_user_id"/>
156+ <field name="invoice_id"/>
157+ <field name="invoice_date"/>
158+ <field name="name" invisible="1"/>
159+ <field name="product_id"/>
160+ <field name="account_id" invisible="1"/>
161+ <field name="quantity"/>
162+ <field name="uos_id"/>
163+ <field name="price_unit" invisible="1"/>
164+ <field name="discount" invisible="1"/>
165+ <field name="price_subtotal" invisible="1"/>
166+ <field name="subtotal_cost_price" invisible="1"/>
167+ <field name="company_id" invisible="1"/>
168+ <field name="subtotal_company" sum="Total Net Sales "/>
169+ <field name="subtotal_cost_price_company" sum="Total Cost"/>
170+ <field name="margin_absolute" sum="Total Absolute Margin"/>
171+ <field name="margin_relative" />
172+ </form>
173+ </field>
174+ </record>
175+
176 <record id="view_account_invoice_line_filter" model="ir.ui.view">
177 <field name="name">account.invoice.line.select</field>
178 <field name="model">account.invoice.line</field>
179
180=== modified file 'product_price_history/product_price_history.py'
181--- product_price_history/product_price_history.py 2013-12-11 15:09:00 +0000
182+++ product_price_history/product_price_history.py 2014-02-05 09:14:09 +0000
183@@ -22,7 +22,7 @@
184
185 import logging
186 import time
187-from openerp.osv import orm, fields
188+from openerp.osv import orm, fields, expression
189 import openerp.addons.decimal_precision as dp
190 from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT
191
192@@ -140,6 +140,19 @@
193 "goods stored at this Location, or any of its children."),
194 }
195
196+ def open_product_historic_prices(self, cr, uid, ids, context=None):
197+ if context is None:
198+ context = {}
199+ prod_tpl_obj = self.pool.get('product.template')
200+ prod_tpl_ids = []
201+ for product in self.browse(cr, uid, ids, context=context):
202+ if product.product_tmpl_id.id not in prod_tpl_ids:
203+ prod_tpl_ids.append(product.product_tmpl_id.id)
204+ res = self.pool.get('ir.actions.act_window').for_xml_id(cr, uid,
205+ 'product_price_history', 'action_price_history', context=context)
206+ res['domain'] = expression.AND([res.get('domain', []),
207+ [('product_id', 'in', prod_tpl_ids)]])
208+ return res
209
210 class product_template(orm.Model):
211 _inherit = "product.template"
212
213=== modified file 'product_price_history/product_price_history_view.xml'
214--- product_price_history/product_price_history_view.xml 2013-12-10 13:52:28 +0000
215+++ product_price_history/product_price_history_view.xml 2014-02-05 09:14:09 +0000
216@@ -56,10 +56,10 @@
217 <field name="product_id"/>
218 <field name="company_id" groups="base.group_multi_company"/>
219 <group expand="0" string="Group By...">
220- <filter string="Date" icon="terp-go-month" domain="[]" context="{'group_by':'datetime'}"/>
221- <filter string="Product" domain="[]" context="{'group_by':'product_id'}"/>
222- <filter string="Name" domain="[]" context="{'group_by':'name'}"/>
223- <filter string="Company" domain="[]" context="{'group_by':'company_id'}" groups="base.group_multi_company"/>
224+ <filter string="Date" name="group_date" icon="terp-go-month" domain="[]" context="{'group_by':'datetime'}"/>
225+ <filter string="Product" name="group_product_id" domain="[]" context="{'group_by':'product_id'}"/>
226+ <filter string="Name" domain="[]" name="group_name" context="{'group_by':'name'}"/>
227+ <filter string="Company" domain="[]" name="group_company_id" context="{'group_by':'company_id'}" groups="base.group_multi_company"/>
228 </group>
229 </search>
230
231@@ -73,18 +73,34 @@
232 <field name="view_type">form</field>
233 <field name="view_id" ref="view_product_price_history_from_product"/>
234 <field name="search_view_id" ref="view_product_price_history_filter"/>
235+ <field name="context">{'search_default_group_product_id':1,'search_default_group_name': 1,'group_by':[]}</field>
236 </record>
237
238- <act_window
239+
240+ <menuitem action="action_price_history"
241+ id="menu_product_price_history_action_form"
242+ parent="stock.next_id_61" sequence="2"/>
243+
244+ <!-- <act_window
245 context="{'search_default_product_id': [active_id], 'default_product_id': active_id}"
246 id="act_product_prices_history_open"
247 name="Prices History"
248 res_model="product.price.history"
249- src_model="product.product"/>
250-
251- <menuitem action="action_price_history"
252- id="menu_product_price_history_action_form"
253- parent="stock.next_id_61" sequence="2"/>
254+ src_model="product.product"/> -->
255+
256+ <record id="product_search_form_view_stock" model="ir.ui.view">
257+ <field name="name">product.product.price_history.form</field>
258+ <field name="model">product.product</field>
259+ <field name="inherit_id" ref="product.product_normal_form_view"/>
260+ <field name="arch" type="xml">
261+ <div class="oe_right oe_button_box" name="buttons" position="inside">
262+ <button name="open_product_historic_prices"
263+ string="Prices History" groups="product.group_costing_method"
264+ type="object" />
265+ </div>
266+ </field>
267+ </record>
268+
269
270 </data>
271 </openerp>
272
273=== modified file 'product_price_history/wizard/historic_prices.py'
274--- product_price_history/wizard/historic_prices.py 2013-12-12 10:09:02 +0000
275+++ product_price_history/wizard/historic_prices.py 2014-02-05 09:14:09 +0000
276@@ -25,8 +25,11 @@
277
278
279 class historic_prices(orm.TransientModel):
280+ """ Will display an inventory valuation of the stock with quantity > 0
281+ at the given date.
282+ """
283 _name = 'historic.prices'
284- _description = 'Product historical prices'
285+ _description = 'Inventory Valuation'
286
287 def _default_location(self, cr, uid, ids, context=None):
288 try:
289@@ -159,3 +162,4 @@
290 'domain': domain,
291 'search_view_id': filter_id,
292 }
293+
294
295=== modified file 'product_price_history/wizard/historic_prices_view.xml'
296--- product_price_history/wizard/historic_prices_view.xml 2013-12-10 10:36:54 +0000
297+++ product_price_history/wizard/historic_prices_view.xml 2014-02-05 09:14:09 +0000
298@@ -32,6 +32,5 @@
299 id="menu_action_product_historic_prices_tree"
300 parent="stock.next_id_61" />
301
302-
303 </data>
304 </openerp>

Subscribers

People subscribed via source and target branches