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

Proposed by Alexandre Fayolle - 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: 615 lines (+561/-0)
10 files modified
product_procurement_type/__init__.py (+22/-0)
product_procurement_type/__openerp__.py (+50/-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
Joël Grand-Guillaume @ camptocamp code review + no tests Needs Fixing
Lorenzo Battistini (community) Needs Information
Alexandre Fayolle - camptocamp code review, test Approve
Leonardo Pistone code review Pending
Stefan Rijnhart (Opener) Pending
Yannick Vaucher @ Camptocamp code review, no tests Pending
Review via email: mp+209018@code.launchpad.net

This proposal supersedes a proposal from 2014-02-21.

This proposal has been superseded by a proposal from 2014-06-04.

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 : 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 :
review: Approve (code review, test)
Revision history for this message
Lorenzo Battistini (elbati) wrote :

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 :

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

Subscribers

People subscribed via source and target branches