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

Proposed by Romain Deheele - Camptocamp
Status: Superseded
Proposed branch: lp:~camptocamp/sale-wkfl/product_procurement_type
Merge into: lp:~sale-core-editors/sale-wkfl/7.0
Diff against target: 682 lines (+614/-0)
12 files modified
product_procurement_type/__init__.py (+22/-0)
product_procurement_type/__openerp__.py (+50/-0)
product_procurement_type/migrations/7.0.0.1/post-migration.py (+38/-0)
product_procurement_type/product.py (+115/-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/migrations/7.0.0.1/post-migration.py (+39/-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
Alexandre Fayolle - camptocamp test Needs Resubmitting
Stefan Rijnhart (Opener) Approve
Leonardo Pistone code review Approve
Joël Grand-Guillaume @ camptocamp code review, no tests Approve
Yannick Vaucher @ Camptocamp code review, no tests Approve
Review via email: mp+207638@code.launchpad.net

This proposal has been superseded by a proposal from 2014-03-03.

Description of the change

Hello,

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.

Regards,

Romain

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

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 :

> 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 :

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 :

> > 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 :

> 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

42. By Alexandre Fayolle - camptocamp

[FIX] tests

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

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 :

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 :

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 :

> 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 :

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 :

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

review: Needs Resubmitting (test)
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.

44. By Alexandre Fayolle - camptocamp

[IMP] remove unnecessary code pointed out by lpistone

45. By Alexandre Fayolle - camptocamp

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

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

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

Subscribers

People subscribed via source and target branches