Merge lp:~camptocamp/sale-wkfl/product_procurement_type into lp:~sale-core-editors/sale-wkfl/7.0

Proposed by Alexandre Fayolle - camptocamp
Status: Rejected
Rejected by: Leonardo Pistone
Proposed branch: lp:~camptocamp/sale-wkfl/product_procurement_type
Merge into: lp:~sale-core-editors/sale-wkfl/7.0
Diff against target: 617 lines (+563/-0)
10 files modified
product_procurement_type/__init__.py (+22/-0)
product_procurement_type/__openerp__.py (+52/-0)
product_procurement_type/product.py (+139/-0)
product_procurement_type/product_view.xml (+42/-0)
product_procurement_type/test/test_onchange_procurement_type.yml (+56/-0)
product_procurement_type_dropshipping/__init__.py (+22/-0)
product_procurement_type_dropshipping/__openerp__.py (+46/-0)
product_procurement_type_dropshipping/product.py (+115/-0)
product_procurement_type_dropshipping/product_view.xml (+17/-0)
product_procurement_type_dropshipping/test/test_onchange_procurement_type.yml (+52/-0)
To merge this branch: bzr merge lp:~camptocamp/sale-wkfl/product_procurement_type
Reviewer Review Type Date Requested Status
Pedro Manuel Baeza Needs Resubmitting
Lorenzo Battistini (community) code review Needs Fixing
Yannick Vaucher @ Camptocamp code review, no tests Pending
Leonardo Pistone code review Pending
Stefan Rijnhart (Opener) Pending
Alexandre Fayolle - camptocamp code review, test Pending
Joël Grand-Guillaume @ camptocamp code review + no tests Pending
Review via email: mp+222111@code.launchpad.net

This proposal supersedes a proposal from 2014-03-03.

Description of the change

Here are two new addons who brings a simple field to manage several combinations
for two procurements fields : procure_method & supply_method :
First addon adds:
- Normal: MTS + buy
- Bill of Materials: MTO + produce
Second addon depends of sale_dropshipping addon and adds:
- Dropshipping: MTO + buy

I'm not sure if it's the right community branch to propose it, if you think about a better
place, let me know.

To post a comment you must log in.
Revision history for this message
Yannick Vaucher @ Camptocamp (yvaucher-c2c) wrote : Posted in a previous version of this proposal

LGTM for the code

However, I don't think we have a proper branch to extend procurement.

Shall we create one?

review: Approve (code review, no tests)
Revision history for this message
Alexandre Fayolle - camptocamp (alexandre-fayolle-c2c) wrote : Posted in a previous version of this proposal

> LGTM for the code
>
> However, I don't think we have a proper branch to extend procurement.
>
> Shall we create one?

Since this is mainly affecting sales, I think this branch is correct.

Revision history for this message
Alexandre Fayolle - camptocamp (alexandre-fayolle-c2c) wrote : Posted in a previous version of this proposal

need to set the value of the attribute from current product configuration when the module is installed.

setting status to "Work in progress" until this is resolved

review: Needs Fixing
Revision history for this message
Alexandre Fayolle - camptocamp (alexandre-fayolle-c2c) wrote : Posted in a previous version of this proposal

> > LGTM for the code
> >
> > However, I don't think we have a proper branch to extend procurement.
> >
> > Shall we create one?
>
> Since this is mainly affecting sales, I think this branch is correct.

However I'm not sure this is not too customer specific to get in OCA. What do other think?

review: Needs Information
Revision history for this message
Alexandre Fayolle - camptocamp (alexandre-fayolle-c2c) wrote : Posted in a previous version of this proposal

> need to set the value of the attribute from current product configuration when
> the module is installed.
>
> setting status to "Work in progress" until this is resolved

dons

Revision history for this message
Joël Grand-Guillaume @ camptocamp (jgrandguillaume-c2c) wrote : Posted in a previous version of this proposal

LGTM, and I agree about adding this module here. Thanks

review: Approve (code review, no tests)
Revision history for this message
Leonardo Pistone (lepistone) wrote : Posted in a previous version of this proposal

I approve the code.

I share Alexandre's question if there is interest to have that in OCA. If not, being it approved technically, we can quickly merge it to a specific branch.

review: Approve (code review)
Revision history for this message
Stefan Rijnhart (Opener) (stefan-opener) wrote : Posted in a previous version of this proposal

I don't see a problem having these modules here. About the code: there is a migration script, and I think its purpose is to update existing products upon installation of the module. However, I don't think the script is run at module installation time. Are you sure that this is the case?

Otherwise, you will need to put it in the model's _auto_init() method. It will run every time the module is upgraded (or installed) but that should not hurt. What you can do is check if column 'procurement_type' exists, call super() and run the migration queries only if the column did not exist when you checked. This indicates the installation of the module.

review: Needs Information
Revision history for this message
Alexandre Fayolle - camptocamp (alexandre-fayolle-c2c) wrote : Posted in a previous version of this proposal

> I don't see a problem having these modules here. About the code: there is a
> migration script, and I think its purpose is to update existing products upon
> installation of the module. However, I don't think the script is run at module
> installation time. Are you sure that this is the case?

Yes it is run at installation time, I checked for this.

> Otherwise, you will need to put it in the model's _auto_init() method. It will
> run every time the module is upgraded (or installed) but that should not hurt.
> What you can do is check if column 'procurement_type' exists, call super() and
> run the migration queries only if the column did not exist when you checked.
> This indicates the installation of the module.

Not sure what the cleanest way is. Do you have an opinion about the cleanness of either options, and what we should aim for in OCA modules?

Revision history for this message
Stefan Rijnhart (Opener) (stefan-opener) wrote : Posted in a previous version of this proposal

Great, that means that we have the pre- and post-installation scripts that I always wanted after all! Much better solution than the _auto_init one.

review: Approve
Revision history for this message
Alexandre Fayolle - camptocamp (alexandre-fayolle-c2c) wrote : Posted in a previous version of this proposal

I found an issue (possibly a framework bug) which prevents the new attribute from being imported from a CSV file.

review: Needs Resubmitting (test)
Revision history for this message
Alexandre Fayolle - camptocamp (alexandre-fayolle-c2c) wrote : Posted in a previous version of this proposal
review: Approve (code review, test)
Revision history for this message
Lorenzo Battistini (elbati) wrote : Posted in a previous version of this proposal

Hello Alexandre,

line 223: if vals['type'] == 'service', should we run _compute_procurement_vals anyway?

lines 585 and 597: as 'product_procurement_type_dropshipping' depends on 'product_procurement_type', why do the write and create methods call the '_compute_procurement_vals' method, already called by 'product_procurement_type'?

Thanks!

review: Needs Information
Revision history for this message
Joël Grand-Guillaume @ camptocamp (jgrandguillaume-c2c) wrote : Posted in a previous version of this proposal

Hi,

Regarding Lorenzo's comments:

 * L223 : IMO think that's not necessary
 * L585 : I agree with Lorenzo's opinion here, you should remove the write and create override in the product_procurement_type_dropshipping module. Already made in the product_procurement_type one.

Thanks !

review: Needs Fixing (code review + no tests)
Revision history for this message
Alexandre Fayolle - camptocamp (alexandre-fayolle-c2c) wrote :

I've fixed Lorenzo's remarks, and moved the migration script to an init method as the migration script may not be executed on initial installation

46. By Romain Deheele - Camptocamp

[UPD] update manifest according to selection values

47. By Romain Deheele - Camptocamp

replace ValueError exception with False value that will be refused because a value is required : avoid ugly traceback

48. By Romain Deheele - Camptocamp

[UPD] update manifest description

Revision history for this message
Romain Deheele - Camptocamp (romaindeheele) wrote :

After several various changes, I think it's time to review it again.

Thanks,

Romain

Revision history for this message
Lorenzo Battistini (elbati) wrote :

Hello Romain and Alexandre,

diff comments + some PEP8 remarks

product_procurement_type/product.py:27:1: E302 expected 2 blank lines, found 1
product_procurement_type/product.py:34:1: E302 expected 2 blank lines, found 1
product_procurement_type/product.py:99:13: E123 closing bracket does not match indentation of opening bracket's line

product_procurement_type/product.py:42:80: E501 line too long (95 > 79 characters)

product_procurement_type_dropshipping/product.py:28:1: E302 expected 2 blank lines, found 0
product_procurement_type_dropshipping/product.py:33:1: E302 expected 2 blank lines, found 1
product_procurement_type_dropshipping/product.py:52:5: E303 too many blank lines (2)
product_procurement_type_dropshipping/product.py:111:17: E123 closing bracket does not match indentation of opening bracket's line
product_procurement_type_dropshipping/product.py:115:1: W391 blank line at end of file

product_procurement_type_dropshipping/product.py:25:80: E501 line too long (90 > 79 characters)
product_procurement_type_dropshipping/product.py:46:80: E501 line too long (116 > 79 characters)
product_procurement_type_dropshipping/product.py:64:80: E501 line too long (80 > 79 characters)

review: Needs Fixing (code review)
Revision history for this message
Pedro Manuel Baeza (pedro.baeza) wrote :

This project is now hosted on https://github.com/OCA/sale-workflow. Please move your proposal there. This guide may help you https://github.com/OCA/maintainers-tools/wiki/How-to-move-a-Merge-Proposal-to-GitHub

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

Unmerged revisions

48. By Romain Deheele - Camptocamp

[UPD] update manifest description

47. By Romain Deheele - Camptocamp

replace ValueError exception with False value that will be refused because a value is required : avoid ugly traceback

46. By Romain Deheele - Camptocamp

[UPD] update manifest according to selection values

45. By Alexandre Fayolle - camptocamp

the migration scripts are not longer called on installation -> move to init method

44. By Alexandre Fayolle - camptocamp

[IMP] remove unnecessary code pointed out by lpistone

43. By Alexandre Fayolle - camptocamp

[FIX] issue when importing products from CSV with procurement_type attribute

There is an issue in the framework (I think) which will break the previous
version of the code in CSV imports: the get_product_procurement_type method (in
product_template) is called with an instance of product_product for self, and
the call to super() crashed. This redesign works around the issue by extracting
get_product_procurement_type to a function and thus avoiding self altogether.

42. By Alexandre Fayolle - camptocamp

[FIX] tests

41. By Alexandre Fayolle - camptocamp

[ADD] migration script to ensure that the new attribute is populated

40. By Alexandre Fayolle - camptocamp

[FIX] values of procurement_type in dispatch method + help string + module version number

39. By Alexandre Fayolle - camptocamp

[IMP] follow changes in product_procurement_type_dropshipping

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added directory 'product_procurement_type'
2=== added file 'product_procurement_type/__init__.py'
3--- product_procurement_type/__init__.py 1970-01-01 00:00:00 +0000
4+++ product_procurement_type/__init__.py 2014-06-10 15:36:28 +0000
5@@ -0,0 +1,22 @@
6+# -*- coding: utf-8 -*-
7+##############################################################################
8+#
9+# Author: Romain Deheele
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+
27+from . import product
28
29=== added file 'product_procurement_type/__openerp__.py'
30--- product_procurement_type/__openerp__.py 1970-01-01 00:00:00 +0000
31+++ product_procurement_type/__openerp__.py 2014-06-10 15:36:28 +0000
32@@ -0,0 +1,52 @@
33+# -*- coding: utf-8 -*-
34+##############################################################################
35+#
36+# Author: Romain Deheele
37+# Copyright 2014 Camptocamp SA
38+#
39+# This program is free software: you can redistribute it and/or modify
40+# it under the terms of the GNU Affero General Public License as
41+# published by the Free Software Foundation, either version 3 of the
42+# License, or (at your option) any later version.
43+#
44+# This program is distributed in the hope that it will be useful,
45+# but WITHOUT ANY WARRANTY; without even the implied warranty of
46+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
47+# GNU Affero General Public License for more details.
48+#
49+# You should have received a copy of the GNU Affero General Public License
50+# along with this program. If not, see <http://www.gnu.org/licenses/>.
51+#
52+##############################################################################
53+
54+{
55+ "name": "Product Procurement Types",
56+ "version": "0.1",
57+ "author": "Camptocamp",
58+ "license": "AGPL-3",
59+ "category": "Sales",
60+ "description":
61+ """
62+ Add a procurement type selection on products.
63+ Let create products as :
64+ - On stock, buy
65+ - On stock, produce
66+ - On order, buy
67+ - On order, produce
68+
69+ Choose "On stock, buy" changes automatically
70+ procurement method as "make to stock" and supply method as "buy".
71+ Choose "On demand, produce" changes automatically
72+ procurement method as "make to order" and supply method as "produce".
73+
74+ """,
75+ "website": "http://camptocamp.com",
76+ "depends": ['sale',
77+ 'procurement',
78+ 'mrp'],
79+ "data": ['product_view.xml'],
80+ "demo": [],
81+ "test": ['test/test_onchange_procurement_type.yml'],
82+ "active": False,
83+ "installable": True,
84+}
85
86=== added file 'product_procurement_type/product.py'
87--- product_procurement_type/product.py 1970-01-01 00:00:00 +0000
88+++ product_procurement_type/product.py 2014-06-10 15:36:28 +0000
89@@ -0,0 +1,139 @@
90+# -*- coding: utf-8 -*-
91+##############################################################################
92+#
93+# Author: Romain Deheele
94+# Copyright 2014 Camptocamp SA
95+#
96+# This program is free software: you can redistribute it and/or modify
97+# it under the terms of the GNU Affero General Public License as
98+# published by the Free Software Foundation, either version 3 of the
99+# License, or (at your option) any later version.
100+#
101+# This program is distributed in the hope that it will be useful,
102+# but WITHOUT ANY WARRANTY; without even the implied warranty of
103+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
104+# GNU Affero General Public License for more details.
105+#
106+# You should have received a copy of the GNU Affero General Public License
107+# along with this program. If not, see <http://www.gnu.org/licenses/>.
108+#
109+##############################################################################
110+import logging
111+
112+from openerp.osv import orm, fields
113+
114+_logger = logging.getLogger('openerp.upgrade')
115+
116+def get_procurement_type_selection():
117+ return [('buy_stock', 'On stock, buy'),
118+ ('buy_demand', 'On demand, buy'),
119+ ('produce_demand', 'On demand, produce'),
120+ ('produce_stock', 'On stock, produce'),
121+ ]
122+
123+class product_template(orm.Model):
124+
125+ _inherit = 'product.template'
126+
127+ def init(self, cr):
128+ _logger.info('Migrating product_procurement_type')
129+ query = ("UPDATE product_template pt "
130+ "SET procurement_type=%(procurement_type)s "
131+ "WHERE procure_method=%(procure_method)s and supply_method=%(supply_method)s")
132+ fixes = [{'procurement_type': 'buy_stock',
133+ 'procure_method': 'make_to_stock',
134+ 'supply_method': 'buy'},
135+ {'procurement_type': 'buy_demand',
136+ 'procure_method': 'make_to_order',
137+ 'supply_method': 'buy'},
138+ {'procurement_type': 'produce_stock',
139+ 'procure_method': 'make_to_stock',
140+ 'supply_method': 'produce'},
141+ {'procurement_type': 'produce_demand',
142+ 'procure_method': 'make_to_order',
143+ 'supply_method': 'produce'},
144+ ]
145+ for fix in fixes:
146+ cr.execute(query, fix)
147+
148+ def get_procurement_type_selection(self, cr, uid, context=None):
149+ """
150+ Has to be inherited to add procurement type
151+ """
152+ return get_procurement_type_selection()
153+
154+ def _compute_procurement_vals(self, vals):
155+ if vals['procurement_type'] == 'buy_stock':
156+ vals.update({'procure_method': 'make_to_stock',
157+ 'supply_method': 'buy',
158+ })
159+ elif vals['procurement_type'] == 'produce_demand':
160+ vals.update({'procure_method': 'make_to_order',
161+ 'supply_method': 'produce',
162+ })
163+ elif vals['procurement_type'] == 'buy_demand':
164+ vals.update({'procure_method': 'make_to_order',
165+ 'supply_method': 'buy',
166+ })
167+ elif vals['procurement_type'] == 'produce_stock':
168+ vals.update({'procure_method': 'make_to_stock',
169+ 'supply_method': 'produce',
170+ })
171+ else:
172+ vals['procurement_type'] = False
173+ return vals
174+
175+ _columns = {
176+ 'procurement_type': fields.selection(
177+ get_procurement_type_selection,
178+ 'Procurement Type',
179+ required=True,
180+ help='On stock, buy: Procurement Method: Make to Stock, '
181+ 'Supply Method: Buy.\n'
182+ 'On stock, produce: Procurement Method: Make to Stock, '
183+ 'Supply Method: Produce.\n'
184+ 'On order, buy: Procurement Method: Make to Order, '
185+ 'Supply Method: Buy.\n'
186+ 'On order, produce: Procurement Method: Make to Order, '
187+ 'Supply Method: Produce.\n'
188+ ),
189+ }
190+
191+ _defaults = {
192+ 'procurement_type': 'buy_stock',
193+ }
194+
195+ def onchange_procurement_type(self, cr, uid, ids, type, procurement_type,
196+ context=None):
197+ vals = {'procurement_type': procurement_type}
198+ if type != 'service':
199+ vals = self._compute_procurement_vals(vals)
200+ return {'value': vals}
201+
202+ def write(self, cr, uid, ids, vals, context=None):
203+ for product in self.read(cr, uid, ids, ['type'], context=context):
204+ if product['type'] != 'service' and \
205+ vals.get('procurement_type'):
206+ vals = self._compute_procurement_vals(vals)
207+ res = super(product_template, self).write(cr, uid, ids, vals,
208+ context=context)
209+ return res
210+
211+ def create(self, cr, uid, vals, context=None):
212+ if vals['type'] != 'service' and vals.get('procurement_type'):
213+ vals = self._compute_procurement_vals(vals)
214+ return super(product_template, self).create(cr, uid, vals,
215+ context=context)
216+
217+
218+class product_product(orm.Model):
219+
220+ _inherit = 'product.product'
221+
222+ def onchange_procurement_type(self, cr, uid, ids, type, procurement_type,
223+ context=None):
224+ tmpl_obj = self.pool['product.template']
225+ res = tmpl_obj.onchange_procurement_type(cr, uid, ids, type,
226+ procurement_type,
227+ context=context)
228+ return {'value': res['value']}
229
230=== added file 'product_procurement_type/product_view.xml'
231--- product_procurement_type/product_view.xml 1970-01-01 00:00:00 +0000
232+++ product_procurement_type/product_view.xml 2014-06-10 15:36:28 +0000
233@@ -0,0 +1,42 @@
234+<?xml version="1.0" encoding="utf-8"?>
235+<openerp>
236+ <data>
237+ <record id="product_normal_form_view_procurement_type" model="ir.ui.view">
238+ <field name="name">product.product.procurement_type</field>
239+ <field name="model">product.product</field>
240+ <field name="inherit_id" ref="procurement.product_form_view_procurement_button"/>
241+ <field name="arch" type="xml">
242+ <data>
243+ <field name="procure_method" position="before">
244+ <field name="procurement_type" on_change="onchange_procurement_type(type, procurement_type)" attrs="{'invisible':[('type','=','service')]}"/>
245+ </field>
246+ <field name="supply_method" position="attributes">
247+ <attribute name="attrs">{'invisible':[('type','!=','service')]}</attribute>
248+ </field>
249+ <field name="procure_method" position="attributes">
250+ <attribute name="attrs">{'invisible':[('type','!=','service')]}</attribute>
251+ </field>
252+ </data>
253+ </field>
254+ </record>
255+
256+ <record model="ir.ui.view" id="product_template_form_view_procurement_type">
257+ <field name="name">product.template.procurement_type</field>
258+ <field name="model">product.template</field>
259+ <field name="inherit_id" ref="procurement.product_template_form_view_procurement"/>
260+ <field name="arch" type="xml">
261+ <data>
262+ <field name="procure_method" position="before">
263+ <field name="procurement_type" on_change="onchange_procurement_type(type, procurement_type)" attrs="{'invisible':[('type','=','service')]}"/>
264+ </field>
265+ <field name="procure_method" position="attributes">
266+ <attribute name="invisible">{'invisible':[('type','!=','service')]}</attribute>
267+ </field>
268+ <field name="supply_method" position="attributes">
269+ <attribute name="invisible">{'invisible':[('type','!=','service')]}</attribute>
270+ </field>
271+ </data>
272+ </field>
273+ </record>
274+ </data>
275+</openerp>
276
277=== added directory 'product_procurement_type/test'
278=== added file 'product_procurement_type/test/test_onchange_procurement_type.yml'
279--- product_procurement_type/test/test_onchange_procurement_type.yml 1970-01-01 00:00:00 +0000
280+++ product_procurement_type/test/test_onchange_procurement_type.yml 2014-06-10 15:36:28 +0000
281@@ -0,0 +1,56 @@
282+-
283+ Testing change of procurement type on product
284+-
285+ I create a product "Store" with type buy_stock
286+-
287+ !record {model: product.product, id: product1}:
288+ name: Store
289+ type: product
290+ procurement_type: buy_stock
291+-
292+ I check if the product is MTS + buy
293+-
294+ !assert {model: product.product, id: product1}:
295+ - procure_method == 'make_to_stock'
296+ - supply_method == 'buy'
297+-
298+ I create a product "Curtain" with type produce_demand
299+-
300+ !record {model: product.product, id: product2}:
301+ name: Curtain
302+ type: product
303+ procurement_type: produce_demand
304+-
305+ I check if the product is MTO + produce
306+-
307+ !assert {model: product.product, id: product2}:
308+ - procure_method == 'make_to_order'
309+ - supply_method == 'produce'
310+
311+-
312+ I create a product "Curtain2" with type produce_stock
313+-
314+ !record {model: product.product, id: product3}:
315+ name: Curtain2
316+ type: product
317+ procurement_type: produce_stock
318+-
319+ I check if the product is MTS + produce
320+-
321+ !assert {model: product.product, id: product3}:
322+ - procure_method == 'make_to_stock'
323+ - supply_method == 'produce'
324+
325+-
326+ I create a product "Store2" with type buy_demand
327+-
328+ !record {model: product.product, id: product4}:
329+ name: Store2
330+ type: product
331+ procurement_type: buy_demand
332+-
333+ I check if the product is MTO + buy
334+-
335+ !assert {model: product.product, id: product4}:
336+ - procure_method == 'make_to_order'
337+ - supply_method == 'buy'
338
339=== added directory 'product_procurement_type_dropshipping'
340=== added file 'product_procurement_type_dropshipping/__init__.py'
341--- product_procurement_type_dropshipping/__init__.py 1970-01-01 00:00:00 +0000
342+++ product_procurement_type_dropshipping/__init__.py 2014-06-10 15:36:28 +0000
343@@ -0,0 +1,22 @@
344+# -*- coding: utf-8 -*-
345+##############################################################################
346+#
347+# Author: Romain Deheele
348+# Copyright 2014 Camptocamp SA
349+#
350+# This program is free software: you can redistribute it and/or modify
351+# it under the terms of the GNU Affero General Public License as
352+# published by the Free Software Foundation, either version 3 of the
353+# License, or (at your option) any later version.
354+#
355+# This program is distributed in the hope that it will be useful,
356+# but WITHOUT ANY WARRANTY; without even the implied warranty of
357+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
358+# GNU Affero General Public License for more details.
359+#
360+# You should have received a copy of the GNU Affero General Public License
361+# along with this program. If not, see <http://www.gnu.org/licenses/>.
362+#
363+##############################################################################
364+
365+from . import product
366
367=== added file 'product_procurement_type_dropshipping/__openerp__.py'
368--- product_procurement_type_dropshipping/__openerp__.py 1970-01-01 00:00:00 +0000
369+++ product_procurement_type_dropshipping/__openerp__.py 2014-06-10 15:36:28 +0000
370@@ -0,0 +1,46 @@
371+# -*- coding: utf-8 -*-
372+##############################################################################
373+#
374+# Author: Romain Deheele
375+# Copyright 2014 Camptocamp SA
376+#
377+# This program is free software: you can redistribute it and/or modify
378+# it under the terms of the GNU Affero General Public License as
379+# published by the Free Software Foundation, either version 3 of the
380+# License, or (at your option) any later version.
381+#
382+# This program is distributed in the hope that it will be useful,
383+# but WITHOUT ANY WARRANTY; without even the implied warranty of
384+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
385+# GNU Affero General Public License for more details.
386+#
387+# You should have received a copy of the GNU Affero General Public License
388+# along with this program. If not, see <http://www.gnu.org/licenses/>.
389+#
390+##############################################################################
391+
392+{
393+ "name": "Product Procurement Type Dropshipping",
394+ "version": "0.1",
395+ "author": "Camptocamp",
396+ "license": "AGPL-3",
397+ "category": "Sales",
398+ "description":
399+ """
400+ Add a choice named 'dropshipping' in procurement_type selection
401+ introduced by product_procurement_type addon.
402+ Choose "Dropshipping" changes automatically
403+ procurement method as "make to order" and supply method as "buy".
404+ It checks if at least one supplier is associated on supplier list
405+ in product form.
406+
407+ """,
408+ "website": "http://camptocamp.com",
409+ "depends": ['product_procurement_type',
410+ 'sale_dropshipping'],
411+ "data": ['product_view.xml'],
412+ "demo": [],
413+ "test": ['test/test_onchange_procurement_type.yml'],
414+ "active": False,
415+ "installable": True,
416+}
417
418=== added file 'product_procurement_type_dropshipping/product.py'
419--- product_procurement_type_dropshipping/product.py 1970-01-01 00:00:00 +0000
420+++ product_procurement_type_dropshipping/product.py 2014-06-10 15:36:28 +0000
421@@ -0,0 +1,115 @@
422+# -*- coding: utf-8 -*-
423+##############################################################################
424+#
425+# Author: Romain Deheele
426+# Copyright 2014 Camptocamp SA
427+#
428+# This program is free software: you can redistribute it and/or modify
429+# it under the terms of the GNU Affero General Public License as
430+# published by the Free Software Foundation, either version 3 of the
431+# License, or (at your option) any later version.
432+#
433+# This program is distributed in the hope that it will be useful,
434+# but WITHOUT ANY WARRANTY; without even the implied warranty of
435+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
436+# GNU Affero General Public License for more details.
437+#
438+# You should have received a copy of the GNU Affero General Public License
439+# along with this program. If not, see <http://www.gnu.org/licenses/>.
440+#
441+##############################################################################
442+import logging
443+
444+from openerp.osv import orm, fields
445+from openerp.tools.translate import _
446+from openerp.addons.product_procurement_type.product import get_procurement_type_selection
447+
448+_logger = logging.getLogger(__name__)
449+def get_procurement_type_selection_with_dropshipping():
450+ selections = get_procurement_type_selection()
451+ selections.append(('direct_delivery', 'Drop Shipping'))
452+ return selections
453+
454+class product_template(orm.Model):
455+
456+ _inherit = 'product.template'
457+
458+ def init(self, cr):
459+ _logger.info('Migrating product_procurement_type_dropshipping')
460+ query = ("UPDATE product_template AS pt "
461+ "SET procurement_type=%(procurement_type)s "
462+ "FROM product_supplierinfo AS psi "
463+ "WHERE procure_method=%(procure_method)s "
464+ " AND supply_method=%(supply_method)s "
465+ " AND psi.product_id = pt.id "
466+ " AND psi.direct_delivery_flag = true")
467+ fixes = [{'procurement_type': 'direct_delivery', 'procure_method': 'make_to_order', 'supply_method': 'buy'},
468+ ]
469+ for fix in fixes:
470+ cr.execute(query, fix)
471+
472+
473+ def get_procurement_type_selection(self, cr, uid, context=None):
474+ """
475+ Adds type dropshipping in procurement_type selection
476+ """
477+ return get_procurement_type_selection_with_dropshipping()
478+
479+ def _compute_procurement_vals(self, vals):
480+ if vals['procurement_type'] == 'direct_delivery':
481+ vals.update({'procure_method': 'make_to_order',
482+ 'supply_method': 'buy',
483+ })
484+ else:
485+ vals = super(product_template, self)._compute_procurement_vals(vals)
486+ return vals
487+
488+ def _check_sellers(self, cr, uid, ids, procurement_type, context=None):
489+ dd_flag = procurement_type == 'direct_delivery'
490+ seller_pool = self.pool['product.supplierinfo']
491+ seller_ids = seller_pool.search(cr, uid, [('product_id', 'in', ids)],
492+ context=context)
493+ if seller_ids:
494+ seller_pool.write(cr, uid, seller_ids,
495+ {'direct_delivery_flag': dd_flag},
496+ context=context)
497+ else:
498+ if dd_flag:
499+ raise orm.except_orm(
500+ _('Warning'),
501+ _('No suppliers defined'))
502+
503+ _columns = {
504+ 'procurement_type': fields.selection(
505+ get_procurement_type_selection,
506+ 'Procurement Type',
507+ required=True,
508+ help='On stock, buy: Procurement Method: Make to Stock, '
509+ 'Supply Method: Buy.\n'
510+ 'On stock, produce: Procurement Method: Make to Stock, '
511+ 'Supply Method: Produce.\n'
512+ 'On order, buy: Procurement Method: Make to Order, '
513+ 'Supply Method: Buy.\n'
514+ 'On order, produce: Procurement Method: Make to Order, '
515+ 'Supply Method: Produce.\n'
516+ 'DropShipping: Procurement Method: Make to Order, '
517+ 'Supply Method: Buy + supplier does drop shipping'),
518+ }
519+
520+ def onchange_procurement_type(self, cr, uid, ids, type,
521+ procurement_type, context=None):
522+ res = super(product_template, self).\
523+ onchange_procurement_type(cr,
524+ uid,
525+ ids,
526+ type,
527+ procurement_type)
528+ if type != 'service':
529+ res['value'].update(
530+ self._compute_procurement_vals(
531+ {'procurement_type': procurement_type})
532+ )
533+ self._check_sellers(cr, uid, ids, procurement_type,
534+ context=context)
535+ return res
536+
537
538=== added file 'product_procurement_type_dropshipping/product_view.xml'
539--- product_procurement_type_dropshipping/product_view.xml 1970-01-01 00:00:00 +0000
540+++ product_procurement_type_dropshipping/product_view.xml 2014-06-10 15:36:28 +0000
541@@ -0,0 +1,17 @@
542+<?xml version="1.0" encoding="utf-8"?>
543+<openerp>
544+ <data>
545+ <record id="view_product_supplier_context_dropshipping" model="ir.ui.view">
546+ <field name="name">product.supplier.context.dropshipping</field>
547+ <field name="model">product.product</field>
548+ <field name="inherit_id" ref="purchase.view_product_supplier_inherit"/>
549+ <field name="arch" type="xml">
550+ <data>
551+ <field name="seller_ids" position="attributes">
552+ <attribute name="context">{'uom_id': uom_id, 'default_direct_delivery_flag': procurement_type == 'direct_delivery'}</attribute>
553+ </field>
554+ </data>
555+ </field>
556+ </record>
557+ </data>
558+</openerp>
559
560=== added directory 'product_procurement_type_dropshipping/test'
561=== added file 'product_procurement_type_dropshipping/test/test_onchange_procurement_type.yml'
562--- product_procurement_type_dropshipping/test/test_onchange_procurement_type.yml 1970-01-01 00:00:00 +0000
563+++ product_procurement_type_dropshipping/test/test_onchange_procurement_type.yml 2014-06-10 15:36:28 +0000
564@@ -0,0 +1,52 @@
565+-
566+ Testing change of procurement type on product
567+-
568+ I create a product "Jalousie"
569+-
570+ !record {model: product.product, id: product3}:
571+ name: Jalousie
572+ type: product
573+-
574+ I define the product with dropshipping
575+ but it fails because the product has no suppliers defined.
576+-
577+ !python {model: product.product}: |
578+ from openerp.osv import orm
579+ product3_id = ref("product3")
580+ try:
581+ self.write(cr, uid, [product3_id], {'procurement_type': 'direct_delivery'})
582+ except orm.except_orm as err:
583+ assert 'Error Expected'
584+-
585+ I create a supplier "Dupont"
586+-
587+ !record {model: res.partner, id: partner1}:
588+ name: Dupont
589+ supplier: True
590+-
591+ I set this supplier on the product "Jalousie"
592+-
593+ !record {model: product.supplierinfo, id: psupinfo1}:
594+ name: partner1
595+ product_id: product3
596+ min_qty: 1.0
597+-
598+ I define dropshipping on the product.
599+-
600+ !python {model: product.product}: |
601+ product3_id = ref("product3")
602+ try:
603+ values = self.onchange_procurement_type(cr, uid, [product3_id], 'product', 'direct_delivery')
604+ self.write(cr, uid, [product3_id], values['value'])
605+ except:
606+ raise AssertionError('Expected no error')
607+-
608+ I check if the product is now made to order
609+-
610+ !assert {model: product.product, id: product3}:
611+ - procure_method == 'make_to_order'
612+-
613+ I check if supplier is checked as doing dropshipping
614+-
615+ !assert {model: product.supplierinfo, id: psupinfo1}:
616+ - direct_delivery_flag == 1
617\ No newline at end of file

Subscribers

People subscribed via source and target branches