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
=== modified file 'product_cost_incl_bom_price_history/product.py'
--- product_cost_incl_bom_price_history/product.py 2013-12-12 10:09:02 +0000
+++ product_cost_incl_bom_price_history/product.py 2014-02-05 09:14:09 +0000
@@ -21,11 +21,9 @@
2121
22from openerp.osv import orm, fields22from openerp.osv import orm, fields
23import decimal_precision as dp23import decimal_precision as dp
24import openerp
25from openerp.addons.product_price_history.product_price_history import (24from openerp.addons.product_price_history.product_price_history import (
26 PRODUCT_FIELD_HISTORIZE25 PRODUCT_FIELD_HISTORIZE
27)26)
28from openerp import SUPERUSER_ID
29import time27import time
30from datetime import datetime, timedelta28from datetime import datetime, timedelta
31import logging29import logging
@@ -60,7 +58,7 @@
60 if not field_flag:58 if not field_flag:
61 field_flag = True59 field_flag = True
62 if self._columns[field_name]._multi:60 if self._columns[field_name]._multi:
63 raise ValueError('multi is not supported on the cost_price field')61 raise ValueError('multi is not supported on the %s field' % field_name)
64 # use admin user for accessing objects having rules defined on62 # use admin user for accessing objects having rules defined on
65 # store fields63 # store fields
66 result = self._columns[field_name].get(cr, self, ids,64 result = self._columns[field_name].get(cr, self, ids,
@@ -71,16 +69,12 @@
71 if r in field_dict.keys():69 if r in field_dict.keys():
72 if field_name in field_dict[r]:70 if field_name in field_dict[r]:
73 result.pop(r)71 result.pop(r)
74 for id, value in result.items():72 prods = self.read(cr, uid, result.keys(), ['product_tmpl_id'],
75 tpl_id = self.read(cr, uid, id,73 context=context, load='_classic_write')
76 ['product_tmpl_id'],74 tmpls = dict((row['id'], row['product_tmpl_id']) for row in prods)
77 context=context)['product_tmpl_id']75 for prod_id, value in result.iteritems():
78 _logger.debug("set price history: %s, product_tpl_id: %s, "76 tmpl_id = tmpls[prod_id]
79 "context: %s",77 prod_tpl_obj._log_price_change(cr, uid, tmpl_id,
80 value,
81 tpl_id,
82 context)
83 prod_tpl_obj._log_price_change(cr, uid, id,
84 field_name,78 field_name,
85 value,79 value,
86 context=context)80 context=context)
@@ -101,9 +95,6 @@
101 fields = list(set(fields))95 fields = list(set(fields))
102 fields.remove('cost_price')96 fields.remove('cost_price')
103 self._set_field_name_values(cr, uid, ids, 'cost_price', context)97 self._set_field_name_values(cr, uid, ids, 'cost_price', context)
104 _logger.debug("call _store_set_values, ids %s, fields: %s",
105 ids,
106 fields)
107 res = super(product_product, self)._store_set_values(cr,98 res = super(product_product, self)._store_set_values(cr,
108 uid,99 uid,
109 ids,100 ids,
@@ -138,37 +129,57 @@
138 context=None, load='_classic_read'):129 context=None, load='_classic_read'):
139 if context is None:130 if context is None:
140 context = {}131 context = {}
141 if fields:132 if not fields:
133 fields = []
134 else:
135 fields = fields[:] # avoid to modify the callee's list
136 if fields and not 'id' in fields:
142 fields.append('id')137 fields.append('id')
143 pt_obj = self.pool.get('product.template')138 pt_obj = self.pool.get('product.template')
139
140 historized_fields = [f for f in fields if f in PRODUCT_FIELD_HISTORIZE]
141 remove_tmpl_field = False
142 if fields and not 'product_tmpl_id' in fields and historized_fields:
143 remove_tmpl_field = True
144 fields.append('product_tmpl_id')
145
144 results = super(product_product, self)._read_flat(cr, uid, ids,146 results = super(product_product, self)._read_flat(cr, uid, ids,
145 fields,147 fields,
146 context=context,148 context=context,
147 load=load)149 load=load)
148 # Note if fields is empty => read all, so look at history table150 # Note if fields is empty => read all, so look at history table
149 if not fields or any([f in PRODUCT_FIELD_HISTORIZE for f in fields]):151 if not fields or historized_fields:
150 date_crit = False152 date_crit = False
151 price_history = self.pool.get('product.price.history')153 price_history = self.pool.get('product.price.history')
152 company_id = pt_obj._get_transaction_company_id(cr, uid,154 company_id = pt_obj._get_transaction_company_id(cr, uid,
153 context=context)155 context=context)
154 if context.get('to_date'):156 if context.get('to_date'):
155 date_crit = context['to_date']157 date_crit = context['to_date']
156 # if fields is empty we read all price fields158 if load == '_classic_write':
157 if not fields:159 # list of ids
158 price_fields = PRODUCT_FIELD_HISTORIZE160 tmpl_ids = [row['product_tmpl_id'] for row in results]
159 # Otherwise we filter on price fields asked in read
160 else:161 else:
161 price_fields = [f for f in PRODUCT_FIELD_HISTORIZE162 # list of (id, name)
162 if f in fields]163 tmpl_ids = [row['product_tmpl_id'][0] for row in results]
163 prod_prices = price_history._get_historic_price(cr, uid,164 prod_prices = price_history._get_historic_price(
164 ids,165 cr, uid,
165 company_id,166 tmpl_ids,
166 datetime=date_crit,167 company_id,
167 field_names=price_fields,168 datetime=date_crit,
168 context=context)169 field_names=historized_fields or PRODUCT_FIELD_HISTORIZE,
170 context=context)
169 for result in results:171 for result in results:
170 dict_value = prod_prices[result['id']]172 if load == '_classic_write':
173 tmpl_id = result['product_tmpl_id']
174 else:
175 tmpl_id = result['product_tmpl_id'][0]
176 dict_value = prod_prices[tmpl_id]
171 result.update(dict_value)177 result.update(dict_value)
178
179 if remove_tmpl_field:
180 for row in results:
181 # this field was not asked by the callee
182 del row['product_tmpl_id']
172 return results183 return results
173184
174 def _product_value(self, cr, uid, ids, field_names=None,185 def _product_value(self, cr, uid, ids, field_names=None,
@@ -184,8 +195,6 @@
184 products = self.read(cr, uid, ids,195 products = self.read(cr, uid, ids,
185 ['id', 'qty_available', 'cost_price'],196 ['id', 'qty_available', 'cost_price'],
186 context=context)197 context=context)
187 _logger.debug("product value get, result :%s, context: %s",
188 products, context)
189 for product in products:198 for product in products:
190 res[product['id']] = product['qty_available'] * product['cost_price']199 res[product['id']] = product['qty_available'] * product['cost_price']
191 return res200 return res
192201
=== modified file 'product_historical_margin/account_invoice_view.xml'
--- product_historical_margin/account_invoice_view.xml 2013-11-28 15:20:12 +0000
+++ product_historical_margin/account_invoice_view.xml 2014-02-05 09:14:09 +0000
@@ -31,6 +31,34 @@
31 </field>31 </field>
32 </record>32 </record>
3333
34 <record id="view_invoice_line_form_from_product" model="ir.ui.view">
35 <field name="name">account.invoice.line.from.product.form</field>
36 <field name="model">account.invoice.line</field>
37 <field name="arch" type="xml">
38 <form string="Invoice Line" create="false">
39 <field name="invoice_type"/>
40 <field name="partner_id"/>
41 <field name="invoice_user_id"/>
42 <field name="invoice_id"/>
43 <field name="invoice_date"/>
44 <field name="name" invisible="1"/>
45 <field name="product_id"/>
46 <field name="account_id" invisible="1"/>
47 <field name="quantity"/>
48 <field name="uos_id"/>
49 <field name="price_unit" invisible="1"/>
50 <field name="discount" invisible="1"/>
51 <field name="price_subtotal" invisible="1"/>
52 <field name="subtotal_cost_price" invisible="1"/>
53 <field name="company_id" invisible="1"/>
54 <field name="subtotal_company" sum="Total Net Sales "/>
55 <field name="subtotal_cost_price_company" sum="Total Cost"/>
56 <field name="margin_absolute" sum="Total Absolute Margin"/>
57 <field name="margin_relative" />
58 </form>
59 </field>
60 </record>
61
34 <record id="view_account_invoice_line_filter" model="ir.ui.view">62 <record id="view_account_invoice_line_filter" model="ir.ui.view">
35 <field name="name">account.invoice.line.select</field>63 <field name="name">account.invoice.line.select</field>
36 <field name="model">account.invoice.line</field>64 <field name="model">account.invoice.line</field>
3765
=== modified file 'product_price_history/product_price_history.py'
--- product_price_history/product_price_history.py 2013-12-11 15:09:00 +0000
+++ product_price_history/product_price_history.py 2014-02-05 09:14:09 +0000
@@ -22,7 +22,7 @@
2222
23import logging23import logging
24import time24import time
25from openerp.osv import orm, fields25from openerp.osv import orm, fields, expression
26import openerp.addons.decimal_precision as dp26import openerp.addons.decimal_precision as dp
27from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT27from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT
2828
@@ -140,6 +140,19 @@
140 "goods stored at this Location, or any of its children."),140 "goods stored at this Location, or any of its children."),
141 }141 }
142142
143 def open_product_historic_prices(self, cr, uid, ids, context=None):
144 if context is None:
145 context = {}
146 prod_tpl_obj = self.pool.get('product.template')
147 prod_tpl_ids = []
148 for product in self.browse(cr, uid, ids, context=context):
149 if product.product_tmpl_id.id not in prod_tpl_ids:
150 prod_tpl_ids.append(product.product_tmpl_id.id)
151 res = self.pool.get('ir.actions.act_window').for_xml_id(cr, uid,
152 'product_price_history', 'action_price_history', context=context)
153 res['domain'] = expression.AND([res.get('domain', []),
154 [('product_id', 'in', prod_tpl_ids)]])
155 return res
143156
144class product_template(orm.Model):157class product_template(orm.Model):
145 _inherit = "product.template"158 _inherit = "product.template"
146159
=== modified file 'product_price_history/product_price_history_view.xml'
--- product_price_history/product_price_history_view.xml 2013-12-10 13:52:28 +0000
+++ product_price_history/product_price_history_view.xml 2014-02-05 09:14:09 +0000
@@ -56,10 +56,10 @@
56 <field name="product_id"/>56 <field name="product_id"/>
57 <field name="company_id" groups="base.group_multi_company"/>57 <field name="company_id" groups="base.group_multi_company"/>
58 <group expand="0" string="Group By...">58 <group expand="0" string="Group By...">
59 <filter string="Date" icon="terp-go-month" domain="[]" context="{'group_by':'datetime'}"/>59 <filter string="Date" name="group_date" icon="terp-go-month" domain="[]" context="{'group_by':'datetime'}"/>
60 <filter string="Product" domain="[]" context="{'group_by':'product_id'}"/>60 <filter string="Product" name="group_product_id" domain="[]" context="{'group_by':'product_id'}"/>
61 <filter string="Name" domain="[]" context="{'group_by':'name'}"/>61 <filter string="Name" domain="[]" name="group_name" context="{'group_by':'name'}"/>
62 <filter string="Company" domain="[]" context="{'group_by':'company_id'}" groups="base.group_multi_company"/>62 <filter string="Company" domain="[]" name="group_company_id" context="{'group_by':'company_id'}" groups="base.group_multi_company"/>
63 </group>63 </group>
64 </search>64 </search>
6565
@@ -73,18 +73,34 @@
73 <field name="view_type">form</field>73 <field name="view_type">form</field>
74 <field name="view_id" ref="view_product_price_history_from_product"/>74 <field name="view_id" ref="view_product_price_history_from_product"/>
75 <field name="search_view_id" ref="view_product_price_history_filter"/>75 <field name="search_view_id" ref="view_product_price_history_filter"/>
76 <field name="context">{'search_default_group_product_id':1,'search_default_group_name': 1,'group_by':[]}</field>
76 </record>77 </record>
7778
78 <act_window79
80 <menuitem action="action_price_history"
81 id="menu_product_price_history_action_form"
82 parent="stock.next_id_61" sequence="2"/>
83
84 <!-- <act_window
79 context="{'search_default_product_id': [active_id], 'default_product_id': active_id}"85 context="{'search_default_product_id': [active_id], 'default_product_id': active_id}"
80 id="act_product_prices_history_open"86 id="act_product_prices_history_open"
81 name="Prices History"87 name="Prices History"
82 res_model="product.price.history"88 res_model="product.price.history"
83 src_model="product.product"/>89 src_model="product.product"/> -->
8490
85 <menuitem action="action_price_history"91 <record id="product_search_form_view_stock" model="ir.ui.view">
86 id="menu_product_price_history_action_form"92 <field name="name">product.product.price_history.form</field>
87 parent="stock.next_id_61" sequence="2"/>93 <field name="model">product.product</field>
94 <field name="inherit_id" ref="product.product_normal_form_view"/>
95 <field name="arch" type="xml">
96 <div class="oe_right oe_button_box" name="buttons" position="inside">
97 <button name="open_product_historic_prices"
98 string="Prices History" groups="product.group_costing_method"
99 type="object" />
100 </div>
101 </field>
102 </record>
103
88 104
89 </data>105 </data>
90</openerp>106</openerp>
91107
=== modified file 'product_price_history/wizard/historic_prices.py'
--- product_price_history/wizard/historic_prices.py 2013-12-12 10:09:02 +0000
+++ product_price_history/wizard/historic_prices.py 2014-02-05 09:14:09 +0000
@@ -25,8 +25,11 @@
2525
2626
27class historic_prices(orm.TransientModel):27class historic_prices(orm.TransientModel):
28 """ Will display an inventory valuation of the stock with quantity > 0
29 at the given date.
30 """
28 _name = 'historic.prices'31 _name = 'historic.prices'
29 _description = 'Product historical prices'32 _description = 'Inventory Valuation'
3033
31 def _default_location(self, cr, uid, ids, context=None):34 def _default_location(self, cr, uid, ids, context=None):
32 try:35 try:
@@ -159,3 +162,4 @@
159 'domain': domain,162 'domain': domain,
160 'search_view_id': filter_id,163 'search_view_id': filter_id,
161 }164 }
165
162166
=== modified file 'product_price_history/wizard/historic_prices_view.xml'
--- product_price_history/wizard/historic_prices_view.xml 2013-12-10 10:36:54 +0000
+++ product_price_history/wizard/historic_prices_view.xml 2014-02-05 09:14:09 +0000
@@ -32,6 +32,5 @@
32 id="menu_action_product_historic_prices_tree"32 id="menu_action_product_historic_prices_tree"
33 parent="stock.next_id_61" />33 parent="stock.next_id_61" />
3434
35
36 </data>35 </data>
37</openerp>36</openerp>

Subscribers

People subscribed via source and target branches