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
=== added directory 'last_sale_price'
=== added file 'last_sale_price/__init__.py'
--- last_sale_price/__init__.py 1970-01-01 00:00:00 +0000
+++ last_sale_price/__init__.py 2014-06-19 11:15:10 +0000
@@ -0,0 +1,21 @@
1# -*- coding: utf-8 -*-
2##############################################################################
3#
4# Author: Yannick Vaucher
5# Copyright 2014 Camptocamp SA
6#
7# This program is free software: you can redistribute it and/or modify
8# it under the terms of the GNU Affero General Public License as
9# published by the Free Software Foundation, either version 3 of the
10# License, or (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU Affero General Public License for more details.
16#
17# You should have received a copy of the GNU Affero General Public License
18# along with this program. If not, see <http://www.gnu.org/licenses/>.
19#
20##############################################################################
21from . import sale
022
=== added file 'last_sale_price/__openerp__.py'
--- last_sale_price/__openerp__.py 1970-01-01 00:00:00 +0000
+++ last_sale_price/__openerp__.py 2014-06-19 11:15:10 +0000
@@ -0,0 +1,52 @@
1# -*- coding: utf-8 -*-
2##############################################################################
3#
4# Author: Yannick Vaucher
5# Copyright 2014 Camptocamp SA
6#
7# This program is free software: you can redistribute it and/or modify
8# it under the terms of the GNU Affero General Public License as
9# published by the Free Software Foundation, either version 3 of the
10# License, or (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU Affero General Public License for more details.
16#
17# You should have received a copy of the GNU Affero General Public License
18# along with this program. If not, see <http://www.gnu.org/licenses/>.
19#
20##############################################################################
21{'name': 'Last Sale Price',
22 'summary': 'Show last price defined for customer on sale order line',
23 'version': '1.0',
24 'category': 'Sales',
25 'description': """
26Last Sale Price
27===============
28
29Add price, quantity and date of a product of the last time it was sold to
30a partner.
31
32In order to let the salesman know if a customer already ordered a product.
33And to give him hint about what price he should propose.
34That information is shown next to the price in Sale Order's line Form.
35
36Only Sale Orders' lines in state Confirmed and Done are considered to
37compute those fields.
38
39If multiple Sale Order lines for the same partner where made on the same
40date for the same product, the sum of all quantity and the average price
41will be displayed.
42""",
43 'author': 'Camptocamp',
44 'maintainer': 'Camptocamp',
45 'website': 'http://www.camptocamp.com/',
46 'depends': ['base', 'sale'],
47 'data': ['sale_view.xml'],
48 'test': ['test/last_sale_price.yml'],
49 'installable': True,
50 'auto_install': False,
51 'application': True,
52 }
053
=== added directory 'last_sale_price/i18n'
=== added file 'last_sale_price/i18n/last_sale_price.pot'
--- last_sale_price/i18n/last_sale_price.pot 1970-01-01 00:00:00 +0000
+++ last_sale_price/i18n/last_sale_price.pot 2014-06-19 11:15:10 +0000
@@ -0,0 +1,43 @@
1# Translation of OpenERP Server.
2# This file contains the translation of the following modules:
3# * last_sale_price
4#
5msgid ""
6msgstr ""
7"Project-Id-Version: OpenERP Server 7.0\n"
8"Report-Msgid-Bugs-To: \n"
9"POT-Creation-Date: 2014-06-18 15:28+0000\n"
10"PO-Revision-Date: 2014-06-18 15:28+0000\n"
11"Last-Translator: <>\n"
12"Language-Team: \n"
13"MIME-Version: 1.0\n"
14"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Transfer-Encoding: \n"
16"Plural-Forms: \n"
17
18#. module: last_sale_price:
19#: field:sale.order.line,last_sale_date:0
20msgid "Last Sale Date"
21msgstr ""
22
23#. module: last_sale_price
24#: field:sale.order.line,last_sale_price:0
25msgid "Last Sale Price"
26msgstr ""
27
28#. module: last_sale_price
29#: field:sale.order.line,last_sale_qty:0
30msgid "Last Sale Quantity"
31msgstr ""
32
33#. module: last_sale_price
34#: model:ir.model,name:last_sale_price.model_sale_order_line
35msgid "Sale Order line"
36msgstr ""
37
38#. module: last_sale_price
39#: code:_description:0
40#, python-format
41msgid "Sales Order Line"
42msgstr ""
43
044
=== added file 'last_sale_price/sale.py'
--- last_sale_price/sale.py 1970-01-01 00:00:00 +0000
+++ last_sale_price/sale.py 2014-06-19 11:15:10 +0000
@@ -0,0 +1,94 @@
1# -*- coding: utf-8 -*-
2##############################################################################
3#
4# Author: Yannick Vaucher
5# Copyright 2014 Camptocamp SA
6#
7# This program is free software: you can redistribute it and/or modify
8# it under the terms of the GNU Affero General Public License as
9# published by the Free Software Foundation, either version 3 of the
10# License, or (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU Affero General Public License for more details.
16#
17# You should have received a copy of the GNU Affero General Public License
18# along with this program. If not, see <http://www.gnu.org/licenses/>.
19#
20##############################################################################
21from openerp.osv import orm, fields
22
23
24class SaleOrderLine(orm.Model):
25 _inherit = 'sale.order.line'
26
27 def _get_last_sale_sums(self, cr, uid, last_lines, context=None):
28 """ Get last price from sale order lines
29
30 If multiple lines exists at the same date we do an average
31 """
32 if len(last_lines) == 1:
33 return last_lines[0].price_unit, last_lines[0].product_uom_qty
34 else:
35 sum_price = 0.0
36 sum_qty = 0.0
37 for line in last_lines:
38 sum_qty += line.product_uom_qty
39 sum_price += line.price_unit * line.product_uom_qty
40 return sum_price / float(sum_qty), sum_qty
41
42 def _get_last_sale(self, cr, uid, ids, field_name, arg, context=None):
43 """ Get last sale price and last sale date
44 """
45 res = {}
46 for res_id in ids:
47 res[res_id] = {'last_sale_price': False,
48 'last_sale_qty': False,
49 'last_sale_date': False}
50 for line in self.browse(cr, uid, ids, context=context):
51 if not line.product_id:
52 continue
53
54 line_ids = self.search(
55 cr, uid,
56 [('order_partner_id', '=', line.order_partner_id.id),
57 ('product_id', '=', line.product_id.id),
58 ('state', 'in', ['confirmed', 'done'])],
59 context=context)
60
61 if not line_ids:
62 continue
63
64 old_lines = self.browse(cr, uid, line_ids, context=context)
65 old_lines.sort(key=lambda l: l.order_id.date_order, reverse=True)
66
67 last_date = old_lines[0].order_id.date_order
68 last_lines = [l for l in old_lines
69 if l.order_id.date_order == last_date]
70 res[line.id]['last_sale_date'] = last_date
71
72 (last_price, last_qty) = self._get_last_sale_sums(
73 cr, uid, last_lines, context=context)
74 res[line.id]['last_sale_price'] = last_price
75 res[line.id]['last_sale_qty'] = last_qty
76 return res
77
78 _columns = {
79 'last_sale_price': fields.function(
80 _get_last_sale,
81 type="float",
82 string='Last Sale Price',
83 multi='last_sale'),
84 'last_sale_qty': fields.function(
85 _get_last_sale,
86 type="float",
87 string='Last Sale Quantity',
88 multi='last_sale'),
89 'last_sale_date': fields.function(
90 _get_last_sale,
91 type="date",
92 string='Last Sale Date',
93 multi='last_sale'),
94 }
095
=== added file 'last_sale_price/sale_view.xml'
--- last_sale_price/sale_view.xml 1970-01-01 00:00:00 +0000
+++ last_sale_price/sale_view.xml 2014-06-19 11:15:10 +0000
@@ -0,0 +1,23 @@
1<?xml version="1.0" encoding="utf-8"?>
2<openerp>
3 <data>
4 <record id="view_order_form" model="ir.ui.view">
5 <field name="name">sale.order.form.last_sale</field>
6 <field name="model">sale.order</field>
7 <field name="inherit_id" ref="sale.view_order_form"/>
8 <field name="arch" type="xml">
9 <xpath expr="//field[@name='order_line']/form//field[@name='price_unit']" position="after">
10 <field name="last_sale_date"/>
11 <field name="last_sale_price"/>
12 <field name="last_sale_qty"/>
13 </xpath>
14 <xpath expr="//field[@name='order_line']/tree//field[@name='price_unit']" position="after">
15 <field name="last_sale_date"/>
16 <field name="last_sale_price"/>
17 <field name="last_sale_qty"/>
18 </xpath>
19 </field>
20 </record>
21
22 </data>
23</openerp>
024
=== added directory 'last_sale_price/test'
=== added file 'last_sale_price/test/last_sale_price.yml'
--- last_sale_price/test/last_sale_price.yml 1970-01-01 00:00:00 +0000
+++ last_sale_price/test/last_sale_price.yml 2014-06-19 11:15:10 +0000
@@ -0,0 +1,169 @@
1-
2 In order to test module last_sale_price I will create
3 multiple orders on different dates with different products
4 and for different partners
5
6 I test the following with user admin
7-
8 !context
9 uid: 'base.user_root'
10-
11 I create a screwdriver product
12-
13 !record {model: product.product, id: product_product_a}:
14 categ_id: product.product_category_1
15 name: Blue Screwdriver A
16 cost_method: standard
17 uom_id: product.product_uom_unit
18 uom_po_id: product.product_uom_unit
19 company_id: 0
20 standard_price: 5.0
21 list_price: 25.0
22-
23 I create a hammer product
24-
25 !record {model: product.product, id: product_product_b}:
26 categ_id: product.product_category_1
27 name: Red Hammer B
28 cost_method: standard
29 uom_id: product.product_uom_unit
30 uom_po_id: product.product_uom_unit
31 company_id: 0
32 standard_price: 10.0
33 list_price: 30.0
34
35-
36 I create a sale order buying screwdriver
37-
38 !record {model: sale.order, id: sale_order_p1_1}:
39 name: My first order
40 partner_id: base.res_partner_12
41 date_order: 2000-01-01
42 order_line:
43 - name: Screwdrivers
44 product_id: product_product_a
45 product_uom_qty: 5
46 price_unit: 21.0
47
48-
49 I verify no last price is set as there was no previous sale for this partner
50-
51 !assert {model: sale.order, id: sale_order_p1_1, string: last_sale_price is not empty}:
52 - order_line[0].last_sale_price == False
53 - order_line[0].last_sale_qty == False
54 - order_line[0].last_sale_date == False
55
56-
57 I confirm the first order
58-
59 !workflow {model: sale.order, action: order_confirm, ref: sale_order_p1_1}
60
61-
62 I verify confirming the order changed previous data for this product
63-
64 !assert {model: sale.order, id: sale_order_p1_1, string: last_sale_price is not correctly set}:
65 - order_line[0].last_sale_price == 21.0
66 - order_line[0].last_sale_qty == 5
67 - order_line[0].last_sale_date == '2000-01-01'
68
69-
70 In order to test different product doesn't impact each other
71 and test if with multiple order the last one is the one we use
72 Create a second sale order buying screwdriver and hammers
73-
74 !record {model: sale.order, id: sale_order_p1_2}:
75 name: My second order
76 partner_id: base.res_partner_12
77 date_order: 2001-01-01
78 order_line:
79 - name: Screwdrivers
80 product_id: product_product_a
81 product_uom_qty: 6
82 price_unit: 20.0
83 - name: Hammers
84 product_id: product_product_b
85 product_uom_qty: 25
86 price_unit: 25.0
87
88-
89 I verify nothing changed after creating the unconfirmed order
90-
91 !assert {model: sale.order, id: sale_order_p1_2, string: last_sale data are not correctly set}:
92 - order_line[0].last_sale_price == 21.0
93 - order_line[0].last_sale_qty == 5
94 - order_line[0].last_sale_date == '2000-01-01'
95
96-
97 I verify product B is not impacted by product A
98-
99 !assert {model: sale.order, id: sale_order_p1_2, string: last_sale_price of second line is not empty}:
100 - order_line[1].last_sale_price == False
101 - order_line[1].last_sale_qty == False
102 - order_line[1].last_sale_date == False
103
104-
105 I confirm the second first order
106-
107 !workflow {model: sale.order, action: order_confirm, ref: sale_order_p1_2}
108
109-
110 I verify the newest sale changed lase Sale data
111-
112 !assert {model: sale.order, id: sale_order_p1_2, string: last_sale data is not set with last data}:
113 - order_line[0].last_sale_price == 20.0
114 - order_line[0].last_sale_qty == 6
115 - order_line[0].last_sale_date == '2001-01-01'
116-
117 I verify second customer has no impact on product B
118-
119 !assert {model: sale.order, id: sale_order_p1_2, string: last_sale data is wrongly set with multiple products}:
120 - order_line[1].last_sale_price == 25.0
121 - order_line[1].last_sale_qty == 25
122 - order_line[1].last_sale_date == '2001-01-01'
123-
124 In order sales from a partner doesn't impact sales for other partners
125 and in order to impact of multiple order line from same partner on same product
126 Create another order buying hammers in 2 times for another customer
127-
128 !record {model: sale.order, id: sale_order_p2_1}:
129 name: Another order from another customer
130 partner_id: base.res_partner_11
131 date_order: 2001-01-01
132 order_line:
133 - name: Hammers
134 product_id: product_product_b
135 product_uom_qty: 100
136 price_unit: 5.0
137 - name: Hammers
138 product_id: product_product_b
139 product_uom_qty: 100
140 price_unit: 15.0
141
142-
143 I verify nothing is set for second customer
144-
145 !assert {model: sale.order, id: sale_order_p2_1, string: last_sale data is not empty}:
146 - order_line[0].last_sale_price == False
147 - order_line[0].last_sale_qty == False
148 - order_line[0].last_sale_date == False
149
150-
151 I confirm the third order
152-
153 !workflow {model: sale.order, action: order_confirm, ref: sale_order_p2_1}
154
155-
156 I verify that for first customer, the sale to second customer has no impact on product B
157-
158 !assert {model: sale.order, id: sale_order_p1_2, string: last_sale data is wrongly shared by partner}:
159 - order_line[1].last_sale_price == 25.0
160 - order_line[1].last_sale_qty == 25
161 - order_line[1].last_sale_date == '2001-01-01'
162
163-
164 I verify that for second customer product B last sale price is the mean of all sales of same date
165-
166 !assert {model: sale.order, id: sale_order_p2_1, string: last_sale data didn't change for hammers}:
167 - order_line[0].last_sale_price == 10.0
168 - order_line[0].last_sale_qty == 200
169 - order_line[0].last_sale_date == '2001-01-01'

Subscribers

People subscribed via source and target branches