Merge lp:~camptocamp/sale-wkfl/7.0-add-last_sale_price-yvr into lp:~sale-core-editors/sale-wkfl/7.0

Proposed by Yannick Vaucher @ Camptocamp
Status: Rejected
Rejected by: Yannick Vaucher @ Camptocamp
Proposed branch: lp:~camptocamp/sale-wkfl/7.0-add-last_sale_price-yvr
Merge into: lp:~sale-core-editors/sale-wkfl/7.0
Diff against target: 434 lines (+402/-0)
6 files modified
last_sale_price/__init__.py (+21/-0)
last_sale_price/__openerp__.py (+52/-0)
last_sale_price/i18n/last_sale_price.pot (+43/-0)
last_sale_price/sale.py (+94/-0)
last_sale_price/sale_view.xml (+23/-0)
last_sale_price/test/last_sale_price.yml (+169/-0)
To merge this branch: bzr merge lp:~camptocamp/sale-wkfl/7.0-add-last_sale_price-yvr
Reviewer Review Type Date Requested Status
Leonardo Pistone Approve
Review via email: mp+223704@code.launchpad.net

Commit message

[ADD] module last_sale_price - This module provides new columns in sale order line in order to let the sellerman know if a customer already ordrered a product
to give him hint of what price he should propose, those information will be
shown next to the price in sale order line Form.

Description of the change

Add a module to show last price defined for customer on sale order line

To post a comment you must log in.
49. By Yannick Vaucher @ Camptocamp

improve module description

Revision history for this message
Leonardo Pistone (lepistone) wrote :

l63 sellerman -> salesman
l63 ordrer -> ordered
hint of -> a hint about
those information -> that information
in sale -> in the sale

l67 -> Only lines in Sale Orders in state Confirmed and Done are considered

l70 mean of price -> average price or mean of the prices

l261 are you sure that __init__.py should be there?

Thanks!

review: Needs Fixing
50. By Yannick Vaucher @ Camptocamp

remove __init__.py in test

51. By Yannick Vaucher @ Camptocamp

English correction typo and improvement of description

52. By Yannick Vaucher @ Camptocamp

quantity instead of qty

Revision history for this message
Yannick Vaucher @ Camptocamp (yvaucher-c2c) wrote :

Thanks for the review.

I just fixed the __openerp__.py

Revision history for this message
Guewen Baconnier @ Camptocamp (gbaconnier-c2c) wrote :

Yannick, you need to save the sales order to see the prices. That seems a usability issue.
I'm not sure that we can deal with that properly with onchanges though.

Revision history for this message
Leonardo Pistone (lepistone) wrote :

Thanks Yannick.

I agree with Guewen an onchange would be a better UI, but I'm not blocking on this.

review: Approve
Revision history for this message
Yannick Vaucher @ Camptocamp (yvaucher-c2c) wrote :

Ported on github

Unmerged revisions

52. By Yannick Vaucher @ Camptocamp

quantity instead of qty

51. By Yannick Vaucher @ Camptocamp

English correction typo and improvement of description

50. By Yannick Vaucher @ Camptocamp

remove __init__.py in test

49. By Yannick Vaucher @ Camptocamp

improve module description

48. By Yannick Vaucher @ Camptocamp

Add module last_sale_price

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added directory 'last_sale_price'
2=== added file 'last_sale_price/__init__.py'
3--- last_sale_price/__init__.py 1970-01-01 00:00:00 +0000
4+++ last_sale_price/__init__.py 2014-06-19 11:15:10 +0000
5@@ -0,0 +1,21 @@
6+# -*- coding: utf-8 -*-
7+##############################################################################
8+#
9+# Author: Yannick Vaucher
10+# Copyright 2014 Camptocamp SA
11+#
12+# This program is free software: you can redistribute it and/or modify
13+# it under the terms of the GNU Affero General Public License as
14+# published by the Free Software Foundation, either version 3 of the
15+# License, or (at your option) any later version.
16+#
17+# This program is distributed in the hope that it will be useful,
18+# but WITHOUT ANY WARRANTY; without even the implied warranty of
19+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20+# GNU Affero General Public License for more details.
21+#
22+# You should have received a copy of the GNU Affero General Public License
23+# along with this program. If not, see <http://www.gnu.org/licenses/>.
24+#
25+##############################################################################
26+from . import sale
27
28=== added file 'last_sale_price/__openerp__.py'
29--- last_sale_price/__openerp__.py 1970-01-01 00:00:00 +0000
30+++ last_sale_price/__openerp__.py 2014-06-19 11:15:10 +0000
31@@ -0,0 +1,52 @@
32+# -*- coding: utf-8 -*-
33+##############################################################################
34+#
35+# Author: Yannick Vaucher
36+# Copyright 2014 Camptocamp SA
37+#
38+# This program is free software: you can redistribute it and/or modify
39+# it under the terms of the GNU Affero General Public License as
40+# published by the Free Software Foundation, either version 3 of the
41+# License, or (at your option) any later version.
42+#
43+# This program is distributed in the hope that it will be useful,
44+# but WITHOUT ANY WARRANTY; without even the implied warranty of
45+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
46+# GNU Affero General Public License for more details.
47+#
48+# You should have received a copy of the GNU Affero General Public License
49+# along with this program. If not, see <http://www.gnu.org/licenses/>.
50+#
51+##############################################################################
52+{'name': 'Last Sale Price',
53+ 'summary': 'Show last price defined for customer on sale order line',
54+ 'version': '1.0',
55+ 'category': 'Sales',
56+ 'description': """
57+Last Sale Price
58+===============
59+
60+Add price, quantity and date of a product of the last time it was sold to
61+a partner.
62+
63+In order to let the salesman know if a customer already ordered a product.
64+And to give him hint about what price he should propose.
65+That information is shown next to the price in Sale Order's line Form.
66+
67+Only Sale Orders' lines in state Confirmed and Done are considered to
68+compute those fields.
69+
70+If multiple Sale Order lines for the same partner where made on the same
71+date for the same product, the sum of all quantity and the average price
72+will be displayed.
73+""",
74+ 'author': 'Camptocamp',
75+ 'maintainer': 'Camptocamp',
76+ 'website': 'http://www.camptocamp.com/',
77+ 'depends': ['base', 'sale'],
78+ 'data': ['sale_view.xml'],
79+ 'test': ['test/last_sale_price.yml'],
80+ 'installable': True,
81+ 'auto_install': False,
82+ 'application': True,
83+ }
84
85=== added directory 'last_sale_price/i18n'
86=== added file 'last_sale_price/i18n/last_sale_price.pot'
87--- last_sale_price/i18n/last_sale_price.pot 1970-01-01 00:00:00 +0000
88+++ last_sale_price/i18n/last_sale_price.pot 2014-06-19 11:15:10 +0000
89@@ -0,0 +1,43 @@
90+# Translation of OpenERP Server.
91+# This file contains the translation of the following modules:
92+# * last_sale_price
93+#
94+msgid ""
95+msgstr ""
96+"Project-Id-Version: OpenERP Server 7.0\n"
97+"Report-Msgid-Bugs-To: \n"
98+"POT-Creation-Date: 2014-06-18 15:28+0000\n"
99+"PO-Revision-Date: 2014-06-18 15:28+0000\n"
100+"Last-Translator: <>\n"
101+"Language-Team: \n"
102+"MIME-Version: 1.0\n"
103+"Content-Type: text/plain; charset=UTF-8\n"
104+"Content-Transfer-Encoding: \n"
105+"Plural-Forms: \n"
106+
107+#. module: last_sale_price:
108+#: field:sale.order.line,last_sale_date:0
109+msgid "Last Sale Date"
110+msgstr ""
111+
112+#. module: last_sale_price
113+#: field:sale.order.line,last_sale_price:0
114+msgid "Last Sale Price"
115+msgstr ""
116+
117+#. module: last_sale_price
118+#: field:sale.order.line,last_sale_qty:0
119+msgid "Last Sale Quantity"
120+msgstr ""
121+
122+#. module: last_sale_price
123+#: model:ir.model,name:last_sale_price.model_sale_order_line
124+msgid "Sale Order line"
125+msgstr ""
126+
127+#. module: last_sale_price
128+#: code:_description:0
129+#, python-format
130+msgid "Sales Order Line"
131+msgstr ""
132+
133
134=== added file 'last_sale_price/sale.py'
135--- last_sale_price/sale.py 1970-01-01 00:00:00 +0000
136+++ last_sale_price/sale.py 2014-06-19 11:15:10 +0000
137@@ -0,0 +1,94 @@
138+# -*- coding: utf-8 -*-
139+##############################################################################
140+#
141+# Author: Yannick Vaucher
142+# Copyright 2014 Camptocamp SA
143+#
144+# This program is free software: you can redistribute it and/or modify
145+# it under the terms of the GNU Affero General Public License as
146+# published by the Free Software Foundation, either version 3 of the
147+# License, or (at your option) any later version.
148+#
149+# This program is distributed in the hope that it will be useful,
150+# but WITHOUT ANY WARRANTY; without even the implied warranty of
151+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
152+# GNU Affero General Public License for more details.
153+#
154+# You should have received a copy of the GNU Affero General Public License
155+# along with this program. If not, see <http://www.gnu.org/licenses/>.
156+#
157+##############################################################################
158+from openerp.osv import orm, fields
159+
160+
161+class SaleOrderLine(orm.Model):
162+ _inherit = 'sale.order.line'
163+
164+ def _get_last_sale_sums(self, cr, uid, last_lines, context=None):
165+ """ Get last price from sale order lines
166+
167+ If multiple lines exists at the same date we do an average
168+ """
169+ if len(last_lines) == 1:
170+ return last_lines[0].price_unit, last_lines[0].product_uom_qty
171+ else:
172+ sum_price = 0.0
173+ sum_qty = 0.0
174+ for line in last_lines:
175+ sum_qty += line.product_uom_qty
176+ sum_price += line.price_unit * line.product_uom_qty
177+ return sum_price / float(sum_qty), sum_qty
178+
179+ def _get_last_sale(self, cr, uid, ids, field_name, arg, context=None):
180+ """ Get last sale price and last sale date
181+ """
182+ res = {}
183+ for res_id in ids:
184+ res[res_id] = {'last_sale_price': False,
185+ 'last_sale_qty': False,
186+ 'last_sale_date': False}
187+ for line in self.browse(cr, uid, ids, context=context):
188+ if not line.product_id:
189+ continue
190+
191+ line_ids = self.search(
192+ cr, uid,
193+ [('order_partner_id', '=', line.order_partner_id.id),
194+ ('product_id', '=', line.product_id.id),
195+ ('state', 'in', ['confirmed', 'done'])],
196+ context=context)
197+
198+ if not line_ids:
199+ continue
200+
201+ old_lines = self.browse(cr, uid, line_ids, context=context)
202+ old_lines.sort(key=lambda l: l.order_id.date_order, reverse=True)
203+
204+ last_date = old_lines[0].order_id.date_order
205+ last_lines = [l for l in old_lines
206+ if l.order_id.date_order == last_date]
207+ res[line.id]['last_sale_date'] = last_date
208+
209+ (last_price, last_qty) = self._get_last_sale_sums(
210+ cr, uid, last_lines, context=context)
211+ res[line.id]['last_sale_price'] = last_price
212+ res[line.id]['last_sale_qty'] = last_qty
213+ return res
214+
215+ _columns = {
216+ 'last_sale_price': fields.function(
217+ _get_last_sale,
218+ type="float",
219+ string='Last Sale Price',
220+ multi='last_sale'),
221+ 'last_sale_qty': fields.function(
222+ _get_last_sale,
223+ type="float",
224+ string='Last Sale Quantity',
225+ multi='last_sale'),
226+ 'last_sale_date': fields.function(
227+ _get_last_sale,
228+ type="date",
229+ string='Last Sale Date',
230+ multi='last_sale'),
231+ }
232
233=== added file 'last_sale_price/sale_view.xml'
234--- last_sale_price/sale_view.xml 1970-01-01 00:00:00 +0000
235+++ last_sale_price/sale_view.xml 2014-06-19 11:15:10 +0000
236@@ -0,0 +1,23 @@
237+<?xml version="1.0" encoding="utf-8"?>
238+<openerp>
239+ <data>
240+ <record id="view_order_form" model="ir.ui.view">
241+ <field name="name">sale.order.form.last_sale</field>
242+ <field name="model">sale.order</field>
243+ <field name="inherit_id" ref="sale.view_order_form"/>
244+ <field name="arch" type="xml">
245+ <xpath expr="//field[@name='order_line']/form//field[@name='price_unit']" position="after">
246+ <field name="last_sale_date"/>
247+ <field name="last_sale_price"/>
248+ <field name="last_sale_qty"/>
249+ </xpath>
250+ <xpath expr="//field[@name='order_line']/tree//field[@name='price_unit']" position="after">
251+ <field name="last_sale_date"/>
252+ <field name="last_sale_price"/>
253+ <field name="last_sale_qty"/>
254+ </xpath>
255+ </field>
256+ </record>
257+
258+ </data>
259+</openerp>
260
261=== added directory 'last_sale_price/test'
262=== added file 'last_sale_price/test/last_sale_price.yml'
263--- last_sale_price/test/last_sale_price.yml 1970-01-01 00:00:00 +0000
264+++ last_sale_price/test/last_sale_price.yml 2014-06-19 11:15:10 +0000
265@@ -0,0 +1,169 @@
266+-
267+ In order to test module last_sale_price I will create
268+ multiple orders on different dates with different products
269+ and for different partners
270+
271+ I test the following with user admin
272+-
273+ !context
274+ uid: 'base.user_root'
275+-
276+ I create a screwdriver product
277+-
278+ !record {model: product.product, id: product_product_a}:
279+ categ_id: product.product_category_1
280+ name: Blue Screwdriver A
281+ cost_method: standard
282+ uom_id: product.product_uom_unit
283+ uom_po_id: product.product_uom_unit
284+ company_id: 0
285+ standard_price: 5.0
286+ list_price: 25.0
287+-
288+ I create a hammer product
289+-
290+ !record {model: product.product, id: product_product_b}:
291+ categ_id: product.product_category_1
292+ name: Red Hammer B
293+ cost_method: standard
294+ uom_id: product.product_uom_unit
295+ uom_po_id: product.product_uom_unit
296+ company_id: 0
297+ standard_price: 10.0
298+ list_price: 30.0
299+
300+-
301+ I create a sale order buying screwdriver
302+-
303+ !record {model: sale.order, id: sale_order_p1_1}:
304+ name: My first order
305+ partner_id: base.res_partner_12
306+ date_order: 2000-01-01
307+ order_line:
308+ - name: Screwdrivers
309+ product_id: product_product_a
310+ product_uom_qty: 5
311+ price_unit: 21.0
312+
313+-
314+ I verify no last price is set as there was no previous sale for this partner
315+-
316+ !assert {model: sale.order, id: sale_order_p1_1, string: last_sale_price is not empty}:
317+ - order_line[0].last_sale_price == False
318+ - order_line[0].last_sale_qty == False
319+ - order_line[0].last_sale_date == False
320+
321+-
322+ I confirm the first order
323+-
324+ !workflow {model: sale.order, action: order_confirm, ref: sale_order_p1_1}
325+
326+-
327+ I verify confirming the order changed previous data for this product
328+-
329+ !assert {model: sale.order, id: sale_order_p1_1, string: last_sale_price is not correctly set}:
330+ - order_line[0].last_sale_price == 21.0
331+ - order_line[0].last_sale_qty == 5
332+ - order_line[0].last_sale_date == '2000-01-01'
333+
334+-
335+ In order to test different product doesn't impact each other
336+ and test if with multiple order the last one is the one we use
337+ Create a second sale order buying screwdriver and hammers
338+-
339+ !record {model: sale.order, id: sale_order_p1_2}:
340+ name: My second order
341+ partner_id: base.res_partner_12
342+ date_order: 2001-01-01
343+ order_line:
344+ - name: Screwdrivers
345+ product_id: product_product_a
346+ product_uom_qty: 6
347+ price_unit: 20.0
348+ - name: Hammers
349+ product_id: product_product_b
350+ product_uom_qty: 25
351+ price_unit: 25.0
352+
353+-
354+ I verify nothing changed after creating the unconfirmed order
355+-
356+ !assert {model: sale.order, id: sale_order_p1_2, string: last_sale data are not correctly set}:
357+ - order_line[0].last_sale_price == 21.0
358+ - order_line[0].last_sale_qty == 5
359+ - order_line[0].last_sale_date == '2000-01-01'
360+
361+-
362+ I verify product B is not impacted by product A
363+-
364+ !assert {model: sale.order, id: sale_order_p1_2, string: last_sale_price of second line is not empty}:
365+ - order_line[1].last_sale_price == False
366+ - order_line[1].last_sale_qty == False
367+ - order_line[1].last_sale_date == False
368+
369+-
370+ I confirm the second first order
371+-
372+ !workflow {model: sale.order, action: order_confirm, ref: sale_order_p1_2}
373+
374+-
375+ I verify the newest sale changed lase Sale data
376+-
377+ !assert {model: sale.order, id: sale_order_p1_2, string: last_sale data is not set with last data}:
378+ - order_line[0].last_sale_price == 20.0
379+ - order_line[0].last_sale_qty == 6
380+ - order_line[0].last_sale_date == '2001-01-01'
381+-
382+ I verify second customer has no impact on product B
383+-
384+ !assert {model: sale.order, id: sale_order_p1_2, string: last_sale data is wrongly set with multiple products}:
385+ - order_line[1].last_sale_price == 25.0
386+ - order_line[1].last_sale_qty == 25
387+ - order_line[1].last_sale_date == '2001-01-01'
388+-
389+ In order sales from a partner doesn't impact sales for other partners
390+ and in order to impact of multiple order line from same partner on same product
391+ Create another order buying hammers in 2 times for another customer
392+-
393+ !record {model: sale.order, id: sale_order_p2_1}:
394+ name: Another order from another customer
395+ partner_id: base.res_partner_11
396+ date_order: 2001-01-01
397+ order_line:
398+ - name: Hammers
399+ product_id: product_product_b
400+ product_uom_qty: 100
401+ price_unit: 5.0
402+ - name: Hammers
403+ product_id: product_product_b
404+ product_uom_qty: 100
405+ price_unit: 15.0
406+
407+-
408+ I verify nothing is set for second customer
409+-
410+ !assert {model: sale.order, id: sale_order_p2_1, string: last_sale data is not empty}:
411+ - order_line[0].last_sale_price == False
412+ - order_line[0].last_sale_qty == False
413+ - order_line[0].last_sale_date == False
414+
415+-
416+ I confirm the third order
417+-
418+ !workflow {model: sale.order, action: order_confirm, ref: sale_order_p2_1}
419+
420+-
421+ I verify that for first customer, the sale to second customer has no impact on product B
422+-
423+ !assert {model: sale.order, id: sale_order_p1_2, string: last_sale data is wrongly shared by partner}:
424+ - order_line[1].last_sale_price == 25.0
425+ - order_line[1].last_sale_qty == 25
426+ - order_line[1].last_sale_date == '2001-01-01'
427+
428+-
429+ I verify that for second customer product B last sale price is the mean of all sales of same date
430+-
431+ !assert {model: sale.order, id: sale_order_p2_1, string: last_sale data didn't change for hammers}:
432+ - order_line[0].last_sale_price == 10.0
433+ - order_line[0].last_sale_qty == 200
434+ - order_line[0].last_sale_date == '2001-01-01'

Subscribers

People subscribed via source and target branches