Merge lp:~unifield-team/unifield-addons/uf-108-default-supplier-suggestion into lp:unifield-addons

Proposed by Quentin THEURET @Amaris
Status: Rejected
Rejected by: jftempo
Proposed branch: lp:~unifield-team/unifield-addons/uf-108-default-supplier-suggestion
Merge into: lp:unifield-addons
Diff against target: 2254 lines (+872/-1096)
27 files modified
msf_partner/__init__.py (+0/-27)
msf_partner/__openerp__.py (+0/-49)
msf_partner/partner.py (+0/-45)
msf_partner/partner_demo.xml (+0/-46)
msf_partner/partner_view.xml (+0/-56)
msf_partner/product.py (+0/-38)
msf_partner/product_view.xml (+0/-31)
msf_partner/test/msf_partner.yml (+0/-18)
procurement_list/__init__.py (+1/-0)
procurement_list/__openerp__.py (+3/-0)
procurement_list/partner.py (+92/-0)
procurement_list/partner_view.xml (+27/-0)
procurement_list/procurement_list.py (+123/-36)
procurement_list/procurement_list_view.xml (+12/-4)
procurement_list/security/ir.model.access.csv (+1/-1)
procurement_list/test/procurement_list.yml (+312/-65)
procurement_list/wizard/__init__.py (+1/-0)
procurement_list/wizard/choose_supplier.py (+241/-0)
procurement_list/wizard/choose_supplier_view.xml (+59/-0)
stock_inventory_type/__init__.py (+0/-28)
stock_inventory_type/__openerp__.py (+0/-49)
stock_inventory_type/security/ir.model.access.csv (+0/-2)
stock_inventory_type/stock.py (+0/-135)
stock_inventory_type/stock_data.xml (+0/-23)
stock_inventory_type/stock_move_report.py (+0/-130)
stock_inventory_type/stock_view.xml (+0/-196)
stock_inventory_type/test/adjustment_type.yml (+0/-117)
To merge this branch: bzr merge lp:~unifield-team/unifield-addons/uf-108-default-supplier-suggestion
Reviewer Review Type Date Requested Status
jftempo Needs Fixing
Review via email: mp+53861@code.launchpad.net
To post a comment you must log in.
Revision history for this message
jftempo (jfb-tempo-consulting) wrote :

Please set supplier selection on procurement.list.line and move buttons "create_rfq", "create_po" from procurement.choose.supplier to procurement.list.

review: Needs Fixing
4473. By Quentin THEURET <quentin@tempo-quentin>

UF-108: [IMP] Set supplier selection on procurement.list.line and move buttons create_rfq, create_po from procurement.choose.supplier to procurement.list

Unmerged revisions

4473. By Quentin THEURET <quentin@tempo-quentin>

UF-108: [IMP] Set supplier selection on procurement.list.line and move buttons create_rfq, create_po from procurement.choose.supplier to procurement.list

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== removed directory 'msf_partner'
2=== removed file 'msf_partner/__init__.py'
3--- msf_partner/__init__.py 2011-03-15 15:01:14 +0000
4+++ msf_partner/__init__.py 1970-01-01 00:00:00 +0000
5@@ -1,27 +0,0 @@
6-#!/usr/bin/env python
7-# -*- encoding: utf-8 -*-
8-##############################################################################
9-#
10-# OpenERP, Open Source Management Solution
11-# Copyright (C) 2011 TeMPO Consulting, MSF
12-#
13-# This program is free software: you can redistribute it and/or modify
14-# it under the terms of the GNU Affero General Public License as
15-# published by the Free Software Foundation, either version 3 of the
16-# License, or (at your option) any later version.
17-#
18-# This program is distributed in the hope that it will be useful,
19-# but WITHOUT ANY WARRANTY; without even the implied warranty of
20-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21-# GNU Affero General Public License for more details.
22-#
23-# You should have received a copy of the GNU Affero General Public License
24-# along with this program. If not, see <http://www.gnu.org/licenses/>.
25-#
26-##############################################################################
27-
28-import partner
29-import product
30-
31-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
32-
33
34=== removed file 'msf_partner/__openerp__.py'
35--- msf_partner/__openerp__.py 2011-03-15 15:01:14 +0000
36+++ msf_partner/__openerp__.py 1970-01-01 00:00:00 +0000
37@@ -1,49 +0,0 @@
38-# -*- coding: utf-8 -*-
39-##############################################################################
40-#
41-# OpenERP, Open Source Management Solution
42-# Copyright (C) 2011 TeMPO Consulting, MSF
43-#
44-# This program is free software: you can redistribute it and/or modify
45-# it under the terms of the GNU Affero General Public License as
46-# published by the Free Software Foundation, either version 3 of the
47-# License, or (at your option) any later version.
48-#
49-# This program is distributed in the hope that it will be useful,
50-# but WITHOUT ANY WARRANTY; without even the implied warranty of
51-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
52-# GNU Affero General Public License for more details.
53-#
54-# You should have received a copy of the GNU Affero General Public License
55-# along with this program. If not, see <http://www.gnu.org/licenses/>.
56-#
57-##############################################################################
58-{
59- "name" : "MSF Partners",
60- "version" : "1.0",
61- "author" : "TeMPO Consulting, MSF",
62- "category": "Others",
63- "description": """
64- This modules aims to differentiate Internal/External partners
65- It also aims to create a new type of partner: Manufacturer
66- """,
67- "website": "http://unifield.msf.org",
68- "init_xml": [
69- ],
70- "depends" : [
71- "base",
72- "product",
73- ],
74- "update_xml": [
75- "partner_view.xml",
76- "product_view.xml",
77- ],
78- "demo_xml": [
79- "partner_demo.xml",
80- ],
81- "test": [
82- "test/msf_partner.yml",
83- ],
84- "installable": True,
85- "active": False,
86-}
87
88=== removed file 'msf_partner/partner.py'
89--- msf_partner/partner.py 2011-03-15 15:01:14 +0000
90+++ msf_partner/partner.py 1970-01-01 00:00:00 +0000
91@@ -1,45 +0,0 @@
92-#!/usr/bin/env python
93-# -*- encoding: utf-8 -*-
94-##############################################################################
95-#
96-# OpenERP, Open Source Management Solution
97-# Copyright (C) 2011 TeMPO Consulting, MSF
98-#
99-# This program is free software: you can redistribute it and/or modify
100-# it under the terms of the GNU Affero General Public License as
101-# published by the Free Software Foundation, either version 3 of the
102-# License, or (at your option) any later version.
103-#
104-# This program is distributed in the hope that it will be useful,
105-# but WITHOUT ANY WARRANTY; without even the implied warranty of
106-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
107-# GNU Affero General Public License for more details.
108-#
109-# You should have received a copy of the GNU Affero General Public License
110-# along with this program. If not, see <http://www.gnu.org/licenses/>.
111-#
112-##############################################################################
113-
114-from osv import osv
115-from osv import fields
116-
117-
118-class res_partner(osv.osv):
119- _name = 'res.partner'
120- _inherit = 'res.partner'
121-
122- _columns = {
123- 'manufacturer': fields.boolean(string='Manufacturer', help='Check this box if the partner is a manufacturer'),
124- 'partner_type': fields.selection([('internal', 'Internal'), ('section', 'Inter-section'),
125- ('external', 'External')], string='Partner type', required=True),
126- }
127-
128- _defaults = {
129- 'manufacturer': lambda *a: False,
130- 'partner_type': lambda *a: 'internal',
131- }
132-
133-res_partner()
134-
135-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
136-
137
138=== removed file 'msf_partner/partner_demo.xml'
139--- msf_partner/partner_demo.xml 2011-03-15 14:05:12 +0000
140+++ msf_partner/partner_demo.xml 1970-01-01 00:00:00 +0000
141@@ -1,46 +0,0 @@
142-<?xml version="1.0" encoding="utf-8" ?>
143-<openerp>
144- <data noupdate="0">
145-
146- <record id="base.res_partner_desertic_hispafuentes" model="res.partner">
147- <field name="manufacturer">1</field>
148- <field name="partner_type">section</field>
149- </record>
150-
151- <record id="base.res_partner_tinyatwork" model="res.partner">
152- <field name="manufacturer">1</field>
153- </record>
154-
155- <record id="base.res_partner_asus" model="res.partner">
156- <field name="partner_type">external</field>
157- </record>
158- <record id="base.res_partner_agrolait" model="res.partner">
159- <field name="partner_type">external</field>
160- </record>
161- <record id="base.res_partner_c2c" model="res.partner">
162- <field name="partner_type">section</field>
163- </record>
164- <record id="base.res_partner_sednacom" model="res.partner">
165- <field name="partner_type">internal</field>
166- </record>
167- <record id="base.res_partner_thymbra" model="res.partner">
168- <field name="partner_type">internal</field>
169- </record>
170-
171- <record id="product.supplierinfo10" model="product.supplierinfo">
172- <field name="manufacturer_id" ref="base.res_partner_tinyatwork" />
173- </record>
174-
175- <record id="product.supplierinfo11" model="product.supplierinfo">
176- <field name="manufacturer_id" ref="base.res_partner_tinyatwork" />
177- </record>
178-
179- <record id="product.supplierinfo6" model="product.supplierinfo">
180- <field name="manufacturer_id" ref="base.res_partner_desertic_hispafuentes" />
181- </record>
182-
183- <record id="product.supplierinfo7" model="product.supplierinfo">
184- <field name="manufacturer_id" ref="base.res_partner_tinyatwork" />
185- </record>
186- </data>
187-</openerp>
188
189=== removed file 'msf_partner/partner_view.xml'
190--- msf_partner/partner_view.xml 2011-03-15 15:01:14 +0000
191+++ msf_partner/partner_view.xml 1970-01-01 00:00:00 +0000
192@@ -1,56 +0,0 @@
193-<?xml version="1.0" encoding="utf-8" ?>
194-<openerp>
195- <data>
196-
197- <record id="msf_view_partner_tree" model="ir.ui.view">
198- <field name="name">msf.view.partner.tree</field>
199- <field name="model">res.partner</field>
200- <field name="type">tree</field>
201- <field name="inherit_id" ref="base.view_partner_tree" />
202- <field name="arch" type="xml">
203- <xpath expr="/tree/field[@name='ref']" position="after">
204- <field name="partner_type" />
205- </xpath>
206- </field>
207- </record>
208-
209- <record id="msf_view_partner_form" model="ir.ui.view">
210- <field name="name">msf.view.partner.form</field>
211- <field name="model">res.partner</field>
212- <field name="type">form</field>
213- <field name="inherit_id" ref="base.view_partner_form" />
214- <field name="arch" type="xml">
215- <data>
216- <xpath expr="/form/group/group/field[@name='title']" position="replace">
217- <field name="partner_type" />
218- </xpath>
219- <xpath expr="/form/group/group[2]/field[@name='supplier']" position="after">
220- <field name="manufacturer" />
221- </xpath>
222- </data>
223- </field>
224- </record>
225-
226- <record id="msf_view_res_partner_filter" model="ir.ui.view">
227- <field name="name">msf.view.res.partner.filter</field>
228- <field name="model">res.partner</field>
229- <field name="type">search</field>
230- <field name="inherit_id" ref="base.view_res_partner_filter" />
231- <field name="arch" type="xml">
232- <data>
233- <xpath expr="/search/group/filter[@name='supplier']" position="after">
234- <filter string="Manufacturers" name="manufacturer" icon="terp-personal" domain="[('manufacturer','=',1)]" help="Manufacturer Partners"/>
235- </xpath>
236- <xpath expr="/search/group/field[@name='name']" position="before">
237- <filter string="Internal" name="internal" icon="gtk-leave-fullscreen" domain="[('partner_type','=','internal')]" help="Internal Partners"/>
238- <filter string="Inter-section" name="inter-section" icon="gtk-refresh" domain="[('partner_type','=','section')]" help="Inter-section Partners"/>
239- <filter string="External" name="external" icon="gtk-quit" domain="[('partner_type','=','external')]" help="External Partners"/>
240- <separator orientation="vertical" />
241- </xpath>
242- </data>
243- </field>
244- </record>
245-
246- </data>
247-</openerp>
248-
249
250=== removed file 'msf_partner/product.py'
251--- msf_partner/product.py 2011-03-15 15:01:14 +0000
252+++ msf_partner/product.py 1970-01-01 00:00:00 +0000
253@@ -1,38 +0,0 @@
254-#!/usr/bin/env python
255-# -*- encoding: utf-8 -*-
256-##############################################################################
257-#
258-# OpenERP, Open Source Management Solution
259-# Copyright (C) 2011 TeMPO Consulting, MSF
260-#
261-# This program is free software: you can redistribute it and/or modify
262-# it under the terms of the GNU Affero General Public License as
263-# published by the Free Software Foundation, either version 3 of the
264-# License, or (at your option) any later version.
265-#
266-# This program is distributed in the hope that it will be useful,
267-# but WITHOUT ANY WARRANTY; without even the implied warranty of
268-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
269-# GNU Affero General Public License for more details.
270-#
271-# You should have received a copy of the GNU Affero General Public License
272-# along with this program. If not, see <http://www.gnu.org/licenses/>.
273-#
274-##############################################################################
275-
276-from osv import osv
277-from osv import fields
278-
279-
280-class product_supplierinfo(osv.osv):
281- _name = 'product.supplierinfo'
282- _inherit = 'product.supplierinfo'
283-
284- _columns = {
285- 'manufacturer_id': fields.many2one('res.partner', string='Manufacturer', domain=[('manufacturer', '=', 1)]),
286- }
287-
288-product_supplierinfo()
289-
290-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
291-
292
293=== removed file 'msf_partner/product_view.xml'
294--- msf_partner/product_view.xml 2011-03-10 09:07:17 +0000
295+++ msf_partner/product_view.xml 1970-01-01 00:00:00 +0000
296@@ -1,31 +0,0 @@
297-<?xml version="1.0" encoding="utf-8" ?>
298-<openerp>
299- <data>
300-
301- <record id="manufacturer_supplierinfo_form_view" model="ir.ui.view">
302- <field name="name">manufacture.supplierinfo.form.view</field>
303- <field name="model">product.supplierinfo</field>
304- <field name="type">form</field>
305- <field name="inherit_id" ref="product.product_supplierinfo_form_view" />
306- <field name="arch" type="xml">
307- <xpath expr="/form/field[@name='product_code']" position="after">
308- <field name="manufacturer_id" />
309- </xpath>
310- </field>
311- </record>
312-
313- <record id="manufacturer_supplierinfo_tree_view" model="ir.ui.view">
314- <field name="name">manufacturer.supplierinfo.tree.view</field>
315- <field name="model">product.supplierinfo</field>
316- <field name="type">tree</field>
317- <field name="inherit_id" ref="product.product_supplierinfo_tree_view" />
318- <field name="arch" type="xml">
319- <xpath expr="/tree/field[@name='min_qty']" position="after">
320- <field name="manufacturer_id" />
321- </xpath>
322- </field>
323- </record>
324-
325- </data>
326-</openerp>
327-
328
329=== removed directory 'msf_partner/test'
330=== removed file 'msf_partner/test/msf_partner.yml'
331--- msf_partner/test/msf_partner.yml 2011-03-15 15:01:14 +0000
332+++ msf_partner/test/msf_partner.yml 1970-01-01 00:00:00 +0000
333@@ -1,18 +0,0 @@
334--
335- In order to test the module msf_partne, I will create a partner
336- and check that the default values are well applied.
337--
338- I create the first partner
339--
340- !record {model: res.partner, id: partner1}:
341- name: A
342- supplier: 1
343- customer: 1
344- address:
345- - name: A
346--
347- I check if the default values are good
348--
349- !assert {model: res.partner, id: partner1}:
350- - partner_type == 'internal', "Default value 'internal' for partner_type is not applied"
351- - manufacturer == 0, "Default value 'False' for manufacturer is not applied"
352
353=== modified file 'procurement_list/__init__.py'
354--- procurement_list/__init__.py 2011-03-16 13:17:54 +0000
355+++ procurement_list/__init__.py 2011-03-24 15:56:19 +0000
356@@ -20,6 +20,7 @@
357 ##############################################################################
358
359 import procurement_list
360+import partner
361 import wizard
362
363 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
364
365=== modified file 'procurement_list/__openerp__.py'
366--- procurement_list/__openerp__.py 2011-03-16 18:18:33 +0000
367+++ procurement_list/__openerp__.py 2011-03-24 15:56:19 +0000
368@@ -32,13 +32,16 @@
369 'init_xml': [
370 ],
371 'depends' : [
372+ 'base',
373 'purchase',
374 ],
375 'update_xml': [
376 'procurement_list_sequence.xml',
377 'procurement_list_view.xml',
378+ 'partner_view.xml',
379 'procurement_list_wizard.xml',
380 'wizard/wizard_import_list_view.xml',
381+ 'wizard/choose_supplier_view.xml',
382 'security/ir.model.access.csv',
383 ],
384 'demo_xml': [
385
386=== added file 'procurement_list/partner.py'
387--- procurement_list/partner.py 1970-01-01 00:00:00 +0000
388+++ procurement_list/partner.py 2011-03-24 15:56:19 +0000
389@@ -0,0 +1,92 @@
390+#!/usr/bin/env python
391+# -*- encoding: utf-8 -*-
392+##############################################################################
393+#
394+# OpenERP, Open Source Management Solution
395+# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
396+#
397+# This program is free software: you can redistribute it and/or modify
398+# it under the terms of the GNU Affero General Public License as
399+# published by the Free Software Foundation, either version 3 of the
400+# License, or (at your option) any later version.
401+#
402+# This program is distributed in the hope that it will be useful,
403+# but WITHOUT ANY WARRANTY; without even the implied warranty of
404+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
405+# GNU Affero General Public License for more details.
406+#
407+# You should have received a copy of the GNU Affero General Public License
408+# along with this program. If not, see <http://www.gnu.org/licenses/>.
409+#
410+##############################################################################
411+
412+from osv import osv
413+from osv import fields
414+
415+class res_partner(osv.osv):
416+ _name= 'res.partner'
417+ _inherit = 'res.partner'
418+
419+ _order = 'name'
420+
421+ def _set_in_product(self, cr, uid, ids, field_name, arg, context={}):
422+ '''
423+ Returns according to the context if the partner is in product form
424+ '''
425+ res = {}
426+
427+ product_obj = self.pool.get('product.product')
428+
429+ # If we aren't in the context of choose supplier on procurement list
430+ if not context.get('product_id', False) or 'choose_supplier' not in context:
431+ for i in ids:
432+ res[i] = False
433+ else:
434+ product = product_obj.browse(cr, uid, context.get('product_id'))
435+ seller_ids = []
436+ # Get all suppliers defined on product form
437+ for s in product.seller_ids:
438+ seller_ids.append(s.name.id)
439+ # Check if the partner is in product form
440+ for i in ids:
441+ if i in seller_ids:
442+ res[i] = True
443+ else:
444+ res[i] = False
445+
446+ return res
447+
448+ _columns = {
449+ 'in_product': fields.function(_set_in_product, string='In product', type="boolean", readonly=True, method=True),
450+ }
451+
452+ def read(self, cr, uid, ids, fields=None, context={}, load='_classic_read'):
453+ '''
454+ Sort the supplier according to the context
455+ '''
456+ res = super(res_partner, self).read(cr, uid, ids, fields, context=context, load=load)
457+ # If we are in the context of choose supplier on procurement list
458+ if context.get('product_id', False) and 'choose_supplier' in context:
459+ # Add in_product field in read
460+ if not 'in_product' in fields:
461+ fields.append('in_product')
462+
463+ seller_ids =[]
464+ not_seller_ids = []
465+
466+ for r in res:
467+ if r.get('in_product', False):
468+ seller_ids.append(r)
469+ else:
470+ not_seller_ids.append(r)
471+
472+ result = seller_ids + not_seller_ids
473+ else:
474+ result = res
475+
476+ return result
477+
478+res_partner()
479+
480+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
481+
482
483=== added file 'procurement_list/partner_view.xml'
484--- procurement_list/partner_view.xml 1970-01-01 00:00:00 +0000
485+++ procurement_list/partner_view.xml 2011-03-24 15:56:19 +0000
486@@ -0,0 +1,27 @@
487+<?xml version="1.0" encoding="utf-8" ?>
488+<openerp>
489+ <data>
490+
491+ <record id="in_product_view_partner_tree" model="ir.ui.view">
492+ <field name="name">in.product.view.partner.tree</field>
493+ <field name="model">res.partner</field>
494+ <field name="type">tree</field>
495+ <field name="inherit_id" ref="base.view_partner_tree" />
496+ <field name="arch" type="xml">
497+ <xpath expr="/tree" position="replace">
498+ <tree string="Partners" colors="red:in_product==True">
499+ <field name="name" />
500+ <field name="ref" groups="base.group_extended" />
501+ <field name="phone" />
502+ <field name="email" />
503+ <field name="city" />
504+ <field name="country" />
505+ <field name="user_id" />
506+ <field name="in_product" invisible="1" />
507+ </tree>
508+ </xpath>
509+ </field>
510+ </record>
511+
512+ </data>
513+</openerp>
514\ No newline at end of file
515
516=== modified file 'procurement_list/procurement_list.py'
517--- procurement_list/procurement_list.py 2011-03-16 18:05:16 +0000
518+++ procurement_list/procurement_list.py 2011-03-24 15:56:19 +0000
519@@ -43,10 +43,6 @@
520 'line_ids': fields.one2many('procurement.list.line', 'list_id', string='Lines', readonly=True,
521 states={'draft': [('readonly', False)]}),
522 'notes': fields.text(string='Notes'),
523- 'supplier_ids': fields.many2many('res.partner', 'procurement_list_supplier_rel',
524- 'list_id', 'supplier_id', string='Suppliers',
525- domain="[('supplier', '=', True)]",
526- states={'done': [('readonly', True)]}),
527 'order_ids': fields.many2many('purchase.order', 'procurement_list_order_rel',
528 'list_id', 'order_id', string='Orders', readonly=True),
529 }
530@@ -75,6 +71,82 @@
531 self.write(cr, uid, ids, {'state': 'cancel'})
532
533 return True
534+
535+ def create_po(self, cr, uid, ids, context={}):
536+ '''
537+ Creates all purchase orders according to choices on lines
538+ '''
539+ if ids and isinstance(ids, (int, long)):
540+ ids = [ids]
541+
542+ order_obj = self.pool.get('purchase.order')
543+ order_line_obj = self.pool.get('purchase.order.line')
544+ proc_obj = self.pool.get('procurement.list')
545+ line_obj = self.pool.get('procurement.list.line')
546+ prod_sup_obj = self.pool.get('product.supplierinfo')
547+
548+ # We search if at least one line hasn't defined supplier
549+ for list in self.browse(cr, uid, ids):
550+ for line in list.line_ids:
551+ if not line.supplier_id:
552+ raise osv.except_osv(_('Error'), _('You cannot create purchase orders while all lines haven\'t a defined supplier'))
553+
554+ # We search lines group by supplier_id
555+ po_exists = {}
556+ po_id = False
557+ po_ids = []
558+ line_ids = line_obj.search(cr, uid, [('list_id', 'in', ids)], order='supplier_id')
559+ for l in line_obj.browse(cr, uid, line_ids):
560+ # Search if a PO already exists in the system
561+ if not po_exists.get(l.supplier_id.id, False):
562+ # If no PO in local memory, search in DB
563+ po_exist = order_obj.search(cr, uid, [('origin', '=', l.list_id.name), ('partner_id', '=', l.supplier_id.id)])
564+ if po_exist:
565+ # A PO exists in DB, set the id in local memory
566+ po_exists[l.supplier_id.id] = po_exist[0]
567+ else:
568+ # try to create a new PO, and set its id in local memory
569+ address = l.supplier_id.address_get().get('default')
570+ # Returns an error when the supplier has not defined address
571+ if not address:
572+ raise osv.except_osv(_('Error'), _('The supplier %s has no address defined on its form' %l.supplier_id.name))
573+ # When starting or when the supplier changed, we create a Purchase Order
574+ po_id = order_obj.create(cr, uid, {'partner_id': l.supplier_id.id,
575+ 'partner_address_id': address,
576+ 'pricelist_id': l.supplier_id.property_product_pricelist.id,
577+ 'origin': l.list_id.name,
578+ 'location_id': proc_obj._get_location(cr, uid, l.list_id.warehouse_id)})
579+ po_exists[l.supplier_id.id] = po_id
580+
581+ # Get the PO id in local memory
582+ po_id = po_exists.get(l.supplier_id.id)
583+
584+ # We create all lines for this supplier
585+ price_unit = prod_sup_obj.price_get(cr, uid, [l.supplier_id.id], l.product_id.id, l.product_qty)
586+ order_line_obj.create(cr, uid, {'product_uom': l.product_uom_id.id,
587+ 'product_id': l.product_id.id,
588+ 'order_id': po_id,
589+ 'price_unit': price_unit[l.supplier_id.id],
590+ 'date_planned': l.list_id.order_date,
591+ 'product_qty': l.product_qty,
592+ 'name': l.product_id.name,})
593+
594+ for supplier in po_exists:
595+ po_ids.append(po_exists.get(supplier))
596+
597+ # We confirm all created orders
598+ wf_service = netsvc.LocalService("workflow")
599+ for po in po_ids:
600+ wf_service.trg_validate(uid, 'purchase.order', po, 'purchase_confirm', cr)
601+
602+ proc_obj.write(cr, uid, ids[0], {'state': 'done', 'order_ids': [(6, 0, po_ids)]})
603+
604+ return {'type': 'ir.actions.act_window',
605+ 'res_model': 'purchase.order',
606+ 'view_type': 'form',
607+ 'view_mode': 'tree,form',
608+ 'domain': [('id', 'in', po_ids)],
609+ }
610
611 def create_rfq(self, cr, uid, ids, context={}):
612 '''
613@@ -86,43 +158,21 @@
614 order_ids = []
615
616 for list in self.browse(cr, uid, ids, context=context):
617- # Returns an error message if no suppliers or no products
618- if not list.supplier_ids or len(list.supplier_ids) == 0:
619- raise osv.except_osv(_('Error'), _('No supplier defined for this list !'))
620+ # Returns an error message if no products defined
621 if not list.line_ids or len(list.line_ids) == 0:
622 raise osv.except_osv(_('Error'), _('No line defined for this list !'))
623
624 location_id = self._get_location(cr, uid, list.warehouse_id)
625- # Creates a RfQ for each supplier...
626- for supplier in list.supplier_ids:
627- po_id = purchase_obj.create(cr, uid, {'partner_id': supplier.id,
628- 'partner_address_id': supplier.address_get().get('default'),
629- 'pricelist_id': supplier.property_product_pricelist.id,
630- 'origin': list.name,
631- 'location_id': location_id})
632- order_ids.append(po_id)
633-
634- # ... with all lines...
635- for line in list.line_ids:
636- # ... which aren't from stock
637- if not line.from_stock:
638- line_obj.create(cr, uid, {'product_uom': line.product_uom_id.id,
639- 'product_id': line.product_id.id,
640- 'order_id': po_id,
641- 'price_unit': 0.00,
642- 'date_planned': list.order_date,
643- 'product_qty': line.product_qty,
644- 'procurement_line_id': line.id,
645- 'name': line.product_id.name,})
646- self.pool.get('procurement.list.line').write(cr, uid, line.id, {'latest': 'RfQ In Progress'})
647-
648- self.write(cr, uid, ids, {'state': 'done', 'order_ids': [(6, 0, order_ids)]})
649+
650+ context['active_ids'] = ids
651+ context['active_id'] = ids[0]
652
653 return {'type': 'ir.actions.act_window',
654- 'res_model': 'purchase.order',
655+ 'res_model': 'procurement.choose.supplier.rfq',
656+ 'target': 'new',
657 'view_type': 'form',
658- 'view_mode': 'tree,form',
659- 'domain': [('id', 'in', order_ids)]}
660+ 'view_mode': 'form',
661+ 'context': context}
662
663 def reset(self, cr, uid, ids, context={}):
664 '''
665@@ -158,6 +208,7 @@
666 'from_stock': fields.boolean(string='From stock ?'),
667 'latest': fields.char(size=64, string='Latest document', readonly=True),
668 'list_id': fields.many2one('procurement.list', string='List', required=True, ondelete='cascade'),
669+ 'supplier_id': fields.many2one('res.partner', string='Supplier'),
670 }
671
672 _defaults = {
673@@ -183,12 +234,48 @@
674
675 v = {}
676 if not product_id:
677- v.update({'product_uom_id': False})
678+ v.update({'product_uom_id': False, 'supplier_id': False})
679 else:
680 product = product_obj.browse(cr, uid, product_id, context=context)
681- v.update({'product_uom_id': product.uom_id.id})
682+ v.update({'product_uom_id': product.uom_id.id, 'supplier_id': product.seller_id.id})
683
684 return {'value': v}
685+
686+
687+ def split_line(self, cr, uid, ids, context={}):
688+ '''
689+ Split a line into two lines
690+ '''
691+ if ids and isinstance(ids, (int, long)):
692+ ids = [ids]
693+ for line in self.browse(cr, uid, ids):
694+ state = line.list_id.state
695+ context.update({'line_id': ids[0], 'state': state})
696+ return {'type': 'ir.actions.act_window',
697+ 'res_model': 'procurement.list.line.split',
698+ 'target': 'new',
699+ 'view_type': 'form',
700+ 'view_mode': 'form',
701+ 'context': context,
702+ }
703+
704+ def merge_line(self, cr, uid, ids, context={}):
705+ '''
706+ Merges two lines
707+ '''
708+ if ids and isinstance(ids, (int, long)):
709+ ids = [ids]
710+ for line in self.browse(cr, uid, ids):
711+ state = line.list_id.state
712+ context.update({'line_id': ids[0], 'state': state})
713+
714+ return {'type': 'ir.actions.act_window',
715+ 'res_model': 'procurement.list.line.merge',
716+ 'target': 'new',
717+ 'view_type': 'form',
718+ 'view_mode': 'form',
719+ 'context': context,
720+ }
721
722 procurement_list_line()
723
724
725=== modified file 'procurement_list/procurement_list_view.xml'
726--- procurement_list/procurement_list_view.xml 2011-03-15 16:28:59 +0000
727+++ procurement_list/procurement_list_view.xml 2011-03-24 15:56:19 +0000
728@@ -1,6 +1,13 @@
729 <?xml version="1.0" encoding="utf-8" ?>
730 <openerp>
731 <data>
732+
733+ <record id="action_choose_supplier" model="ir.actions.server">
734+ <field name="name">Choose Supplier</field>
735+ <field name="model_id" ref="model_procurement_choose_supplier"/>
736+ <field name="state">code</field>
737+ <field name="code">action = obj.start_choose_supplier(context=context)</field>
738+ </record>
739
740 <record id="procurement_list_form_view" model="ir.ui.view">
741 <field name="name">procurement.list.form.view</field>
742@@ -25,18 +32,19 @@
743 <field name="comment" />
744 <field name="from_stock" />
745 <field name="latest" />
746+ <field name="supplier_id" context="{'product_id': product_id, 'choose_supplier': True}" />
747+ <button name="split_line" type="object" string="Split Line" icon="terp-stock_effects-object-colorize" />
748+ <button name="merge_line" type="object" string="Merge Line" icon="terp-gtk-jump-to-ltr" context="{'wizard_id': active_id}" />
749 </tree>
750 </field>
751 <group colspan="4" col="6">
752 <field name="state" />
753 <button name="cancel" string="Cancel" icon="gtk-cancel" type="object" states="draft"/>
754- <button name="create_rfq" string="Create RfQ" icon="gtk-execute" type="object" states="draft" />
755+ <button name="create_rfq" type="object" string="Create RfQ" icon="gtk-execute" states="draft" />
756+ <button name="create_po" type="object" string="Create PO" icon="gtk-execute" states="draft" />
757 <button name="reset" string="Reset to Draft" icon="gtk-ok" type="object" states="cancel" />
758 </group>
759 </page>
760- <page string="Suppliers">
761- <field name="supplier_ids" nolabel="1" />
762- </page>
763 <page string="Sourcing Documents">
764 <field name="order_ids" nolabel="1" colspan="4">
765 <tree string="Sourcing Documents" colors="blue:state=='draft'">
766
767=== modified file 'procurement_list/security/ir.model.access.csv'
768--- procurement_list/security/ir.model.access.csv 2011-03-09 13:24:58 +0000
769+++ procurement_list/security/ir.model.access.csv 2011-03-24 15:56:19 +0000
770@@ -1,3 +1,3 @@
771 "id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
772 "access_procurement_list_all","procurement.list all","model_procurement_list",,1,1,1,1
773-"access_procurement_list_line_all","procurement.list.line all","model_procurement_list_line",,1,1,1,1
774+"access_procurement_list_line_all","procurement.list.line all","model_procurement_list_line",,1,1,1,1
775\ No newline at end of file
776
777=== modified file 'procurement_list/test/procurement_list.yml'
778--- procurement_list/test/procurement_list.yml 2011-03-16 16:38:58 +0000
779+++ procurement_list/test/procurement_list.yml 2011-03-24 15:56:19 +0000
780@@ -1,4 +1,59 @@
781 -
782+ In order to test the procurement list module, I will create 6 suppliers,
783+ 5 products and 3 procurement request.
784+ After, I try all possibility to test the supplier default selection
785+-
786+ I create the 6 partners
787+-
788+ I create supplier S1
789+-
790+ !record {model: res.partner, id: supplier1}:
791+ name: S1
792+ supplier: True
793+ address:
794+ - name: S1
795+-
796+ I create the supplier S2
797+-
798+ !record {model: res.partner, id: supplier2}:
799+ name: S2
800+ supplier: True
801+ address:
802+ - name: S2
803+-
804+ I create the supplier S3
805+-
806+ !record {model: res.partner, id: supplier3}:
807+ name: S3
808+ supplier: True
809+ address:
810+ - name: S3
811+-
812+ I create the supplier S4
813+-
814+ !record {model: res.partner, id: supplier4}:
815+ name: S4
816+ supplier: True
817+ address:
818+ - name: S4
819+-
820+ I create the supplier S5
821+-
822+ !record {model: res.partner, id: supplier5}:
823+ name: S5
824+ supplier: True
825+ address:
826+ - name: S5
827+-
828+ I create the supplier S6
829+-
830+ !record {model: res.partner, id: supplier6}:
831+ name: S6
832+ supplier: True
833+ address:
834+ - name: S6
835+-
836+ I create the product P1
837 In order to test the procurement list module, I start by creating a new product category
838 -
839 !record {model: product.category, id: product_cat1}:
840@@ -22,10 +77,20 @@
841 type: product
842 uom_id: product.product_uom_unit
843 uom_po_id: product.product_uom_unit
844- volume: 0.0
845+ volume : 0.0
846 warranty: 0.0
847 weight: 0.0
848 weight_net: 0.0
849+ seller_ids:
850+ - sequence: 10
851+ min_qty: 0.00
852+ name: supplier1
853+ - sequence: 20
854+ min_qty: 0.00
855+ name: supplier2
856+ - sequence: 30
857+ min_qty: 0.00
858+ name: supplier3
859 -
860 I create a second product, P2
861 -
862@@ -43,34 +108,106 @@
863 standard_price: 100.0
864 supply_method: buy
865 type: product
866- uom_id: product.product_uom_unit
867- uom_po_id: product.product_uom_unit
868- volume: 0.0
869- warranty: 0.0
870- weight: 0.0
871- weight_net: 0.0
872--
873- I create a partner
874--
875- !record {model: res.partner, id: partner1}:
876- name: Supplier 1
877--
878- I create an address for this partner
879--
880- !record {model: res.partner.address, id: addr1}:
881- partner_id: partner1
882- name: Supplier1
883--
884- I create a second partner
885--
886- !record {model: res.partner, id: partner2}:
887- name: Supplier 2
888--
889- I create an address for this second partner
890--
891- !record {model: res.partner.address, id: addr2}:
892- partner_id: partner2
893- name: Supplier2
894+ uom_id: product.product_uom_unit
895+ uom_po_id: product.product_uom_unit
896+ volume : 0.0
897+ warranty: 0.0
898+ weight: 0.0
899+ weight_net: 0.0
900+ seller_ids:
901+ - sequence: 10
902+ min_qty: 0.00
903+ name: supplier2
904+ - sequence: 20
905+ min_qty: 0.00
906+ name: supplier1
907+-
908+ I create the product P3
909+-
910+ !record {model: product.product, id: product3}:
911+ categ_id: product.cat0
912+ cost_method: standard
913+ mes_type: fixed
914+ name: P3
915+ price_margin: 2.0
916+ procure_method: make_to_stock
917+ property_stock_inventory: stock.location_inventory
918+ property_stock_procurement: stock.location_procurement
919+ property_stock_production: stock.location_production
920+ seller_delay: '1'
921+ standard_price: 100.0
922+ supply_method: buy
923+ type: product
924+ uom_id: product.product_uom_unit
925+ uom_po_id: product.product_uom_unit
926+ volume : 0.0
927+ warranty: 0.0
928+ weight: 0.0
929+ weight_net: 0.0
930+ seller_ids:
931+ - sequence: 10
932+ min_qty: 0.00
933+ name: supplier3
934+-
935+ I create the product P4
936+-
937+ !record {model: product.product, id: product4}:
938+ categ_id: product.cat0
939+ cost_method: standard
940+ mes_type: fixed
941+ name: P4
942+ price_margin: 2.0
943+ procure_method: make_to_stock
944+ property_stock_inventory: stock.location_inventory
945+ property_stock_procurement: stock.location_procurement
946+ property_stock_production: stock.location_production
947+ seller_delay: '1'
948+ standard_price: 100.0
949+ supply_method: buy
950+ type: product
951+ uom_id: product.product_uom_unit
952+ uom_po_id: product.product_uom_unit
953+ volume : 0.0
954+ warranty: 0.0
955+ weight: 0.0
956+ weight_net: 0.0
957+ seller_ids:
958+ - sequence: 10
959+ min_qty: 0.00
960+ name: supplier3
961+ - sequence: 20
962+ min_qty: 0.00
963+ name: supplier4
964+-
965+ I create the product P5
966+-
967+ !record {model: product.product, id: product5}:
968+ categ_id: product.cat0
969+ cost_method: standard
970+ mes_type: fixed
971+ name: P5
972+ price_margin: 2.0
973+ procure_method: make_to_stock
974+ property_stock_inventory: stock.location_inventory
975+ property_stock_procurement: stock.location_procurement
976+ property_stock_production: stock.location_production
977+ seller_delay: '1'
978+ standard_price: 100.0
979+ supply_method: buy
980+ type: product
981+ uom_id: product.product_uom_unit
982+ uom_po_id: product.product_uom_unit
983+ volume : 0.0
984+ warranty: 0.0
985+ weight: 0.0
986+ weight_net: 0.0
987+ seller_ids:
988+ - sequence: 10
989+ min_qty: 0.00
990+ name: supplier4
991+ - sequence: 20
992+ min_qty: 0.00
993+ name: supplier5
994 -
995 I create a procurement list for these two products
996 -
997@@ -78,28 +215,67 @@
998 requestor: Administration
999 warehouse_id: stock.warehouse0
1000 origin: R 20043
1001- supplier_ids:
1002- - partner1
1003- - partner2
1004 -
1005- I add two lines in this procurement list
1006+ I create a Procurement Request Line 1 for list1
1007 -
1008 !record {model: procurement.list.line, id: list1_line1}:
1009 product_id: product1
1010 product_uom_id: product.product_uom_unit
1011- product_qty: 100.00
1012+ product_qty: 12.0
1013 comment: special comment
1014 from_stock: False
1015 list_id: list1
1016+ supplier_id: supplier1
1017 -
1018- The second line
1019+ I create a Procurement Request Line 2 for list1
1020 -
1021 !record {model: procurement.list.line, id: list1_line2}:
1022 product_id: product2
1023 product_uom_id: product.product_uom_unit
1024- product_qty: 50.0
1025+ product_qty: 10.0
1026 from_stock: True
1027 list_id: list1
1028+ supplier_id: supplier2
1029+-
1030+ I create a second Procurement Request
1031+-
1032+ !record {model: procurement.list, id: list2}:
1033+ requestor: Administration
1034+ warehouse_id: stock.warehouse0
1035+-
1036+ I create Procurement Request line 1 for list2
1037+-
1038+ !record {model: procurement.list.line, id: list2_line1}:
1039+ product_id: product3
1040+ product_uom_id: product.product_uom_unit
1041+ product_qty: 20.0
1042+ list_id: list2
1043+ supplier_id: supplier3
1044+-
1045+ I create Procurement Request line 2 for list2
1046+-
1047+ !record {model: procurement.list.line, id: list2_line2}:
1048+ product_id: product4
1049+ product_uom_id: product.product_uom_unit
1050+ product_qty: 30.0
1051+ list_id: list2
1052+ supplier_id: supplier3
1053+-
1054+ I create a third Procurement Request
1055+-
1056+ !record {model: procurement.list, id: list3}:
1057+ requestor: Administration
1058+ warehouse_id: stock.warehouse0
1059+ origin: R 20045
1060+-
1061+ I create a Procurement Request Line 1 for list3
1062+-
1063+ !record {model: procurement.list.line, id: list3_line1}:
1064+ product_id: product5
1065+ product_uom_id: product.product_uom_unit
1066+ product_qty: 30.0
1067+ list_id: list3
1068+ supplier_id: supplier3
1069 -
1070 I check that the list which was initially in the draft state
1071 -
1072@@ -108,36 +284,107 @@
1073 - requestor == 'Administration'
1074 - origin == 'R 20043'
1075 -
1076- I create RfQ from this list
1077--
1078- !python {model: procurement.list}: |
1079- pl_obj = self.pool.get('procurement.list')
1080- pl_id1 = pl_obj.browse(cr, uid, ref('list1'))
1081- pl_id1.create_rfq()
1082--
1083- I check if the latest message in procurement line is 'RfQ In Progress'
1084--
1085- !assert {model: procurement.list.line, id: list1_line1}:
1086- - latest == 'RfQ In Progress'
1087--
1088- I check if only one RfQ will be created for the
1089--
1090- !python {model: procurement.list}: |
1091- pl_obj = self.pool.get('procurement.list')
1092+ I check if the creation of PO is ok
1093+-
1094+ !python {model: procurement.list}: |
1095+ self.create_po(cr, uid, [ref('list1')])
1096+-
1097+ I check if documents in 'Sourcing' tab are filled
1098+-
1099+ !assert {model: procurement.list, id: list1}:
1100+ - len(order_ids) == 2, "Number of sourcing documents is wrong"
1101+-
1102+ I check if the creation of RfQ is ok
1103+-
1104+ !record {model: procurement.choose.supplier.rfq, id: supplier_choose2}:
1105+ choose_id: list2
1106+ supplier_ids:
1107+ - supplier3
1108+ - supplier4
1109+-
1110+ I confirm the creation of RfQ
1111+-
1112+ !python {model: procurement.choose.supplier.rfq}: |
1113+ self.create_rfq(cr, uid, [ref('supplier_choose2')])
1114+-
1115+ I check if the latest message in procurement line is 'RfQ In Progress'
1116+-
1117+ !assert {model: procurement.list.line, id: list2_line1}:
1118+ - latest == 'RfQ In Progress', "Rfq In Progress not applied in latest field of line"
1119+-
1120+ I check if the latest message in procurement line is 'RfQ In Progress'
1121+-
1122+ !assert {model: procurement.list.line, id: list2_line2}:
1123+ - latest == 'RfQ In Progress', "Rfq In Progress not applied in latest field of line"
1124+-
1125+ I check if documents in 'Sourcing' tab are filled
1126+-
1127+ !assert {model: procurement.list, id: list2}:
1128+ - len(order_ids) == 2, "Number of sourcing documents is wrong"
1129+-
1130+ I check if only one RfQ will be created for the line
1131+-
1132+ !python {model: procurement.list}: |
1133+ list2 = self.browse(cr, uid, ref('list2'))
1134 pol_obj = self.pool.get('purchase.order.line')
1135 order_obj = self.pool.get('purchase.order')
1136- pol_ids = pol_obj.search(cr, uid, [('product_id', '=', ref('product1'))])
1137- pl = pl_obj.browse(cr, uid, ref('list1'))
1138+
1139+ list_line_ids = []
1140+ for line in list2.line_ids:
1141+ list_line_ids.append(line.id)
1142+
1143+ pol_ids = pol_obj.search(cr, uid, [('product_id', '=', ref('product3')), ('procurement_line_id', 'in', list_line_ids)])
1144
1145 for pol in pol_obj.browse(cr, uid, pol_ids):
1146- assert pol.order_id.origin == pl.name, "Bad name for the name of the generated Purchase Order"
1147- order_obj.wkf_confirm_order(cr, uid, [pol.order_id.id])
1148- assert pol.procurement_line_id.latest == pol.order_id.name, "Procurement line not updated"
1149--
1150- I check that no purchase order line with P2
1151--
1152- !python {model: procurement.list}: |
1153- pl_obj = self.pool.get('procurement.list')
1154- pol_obj = self.pool.get('purchase.order.line')
1155- pol_ids = pol_obj.search(cr, uid, [('product_id', '=', ref('product2'))])
1156- assert len(pol_ids) == 0, "No purchase order line found !"
1157+ assert pol.order_id.origin == pl.name, "Bad origin for the generated Purchase Order"
1158+ order_obj.wkf_confirm_order(cr, uid, [pol.order_id.id])
1159+ print pol.procurement_line_id.latest, pol.order_id.name
1160+ assert pol.procurement_line_id.latest == pol.order_id.name, "Procurement line not updated"
1161+-
1162+ Split the line
1163+-
1164+ !record {model: procurement.list.line.split, id: split1}:
1165+ line_id: list3_line1
1166+ qty: 20.00
1167+-
1168+ I check if we have two lines for the product P5 now
1169+-
1170+ !python {model: procurement.list.line}: |
1171+ self.pool.get('procurement.list.line.split').split(cr, uid, ref('split1'))
1172+ assert len(self.search(cr, uid, [('product_id', '=', ref('product5')), ('list_id', '=', ref('list3'))])) == 2, "Line isn't split"
1173+-
1174+ I check if the quantity in old line is decrease of 20 PCE
1175+-
1176+ !python {model: procurement.list.line}: |
1177+ assert self.browse(cr, uid, ref('list3_line1')).product_qty == 10.0, "Quantity of old line isn't updated"
1178+-
1179+ I check if the quantity of the new line is good
1180+-
1181+ !python {model: procurement.list.line}: |
1182+ line_id = self.search(cr, uid, [('product_id', '=', ref('product5')), ('list_id', '=', ref('list3'))])
1183+ for line in line_id:
1184+ if line != ref('list3_line1'):
1185+ assert self.browse(cr, uid, line).product_qty == 20.00, "Quantity of new line is wrong"
1186+-
1187+ I change the supplier of the second line
1188+-
1189+ !python {model: procurement.list.line}: |
1190+ line_id = self.search(cr, uid, [('product_id', '=', ref('product5')), ('list_id', '=', ref('list3')), ('id', '!=', ref('list3_line1'))])
1191+ self.write(cr, uid, line_id, {'supplier_id': ref('supplier6')})
1192+-
1193+ I simulate a click on Create Purchase Order button
1194+-
1195+ !python {model: procurement.list}: |
1196+ self.create_po(cr, uid, [ref('list3')])
1197+-
1198+ I check if two purchase orders have well created
1199+-
1200+ !assert {model: procurement.list, id: list3}:
1201+ - len(order_ids) == 2, "Number of sourcing documents is wrong"
1202+-
1203+ I check if the purchase orders have well confirmed
1204+-
1205+ !python {model: procurement.list}: |
1206+ for order in self.browse(cr, uid, ref('list3')).order_ids:
1207+ assert order.state == 'approved', "PO state isn't confirmed"
1208+
1209\ No newline at end of file
1210
1211=== modified file 'procurement_list/wizard/__init__.py'
1212--- procurement_list/wizard/__init__.py 2011-03-16 13:17:54 +0000
1213+++ procurement_list/wizard/__init__.py 2011-03-24 15:56:19 +0000
1214@@ -23,6 +23,7 @@
1215 import wizard_list_to_order
1216 import wizard_list_to_rfq
1217 import wizard_import_list
1218+import choose_supplier
1219
1220 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
1221
1222
1223=== added file 'procurement_list/wizard/choose_supplier.py'
1224--- procurement_list/wizard/choose_supplier.py 1970-01-01 00:00:00 +0000
1225+++ procurement_list/wizard/choose_supplier.py 2011-03-24 15:56:19 +0000
1226@@ -0,0 +1,241 @@
1227+#!/usr/bin/env python
1228+# -*- encoding: utf-8 -*-
1229+##############################################################################
1230+#
1231+# OpenERP, Open Source Management Solution
1232+# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
1233+#
1234+# This program is free software: you can redistribute it and/or modify
1235+# it under the terms of the GNU Affero General Public License as
1236+# published by the Free Software Foundation, either version 3 of the
1237+# License, or (at your option) any later version.
1238+#
1239+# This program is distributed in the hope that it will be useful,
1240+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1241+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1242+# GNU Affero General Public License for more details.
1243+#
1244+# You should have received a copy of the GNU Affero General Public License
1245+# along with this program. If not, see <http://www.gnu.org/licenses/>.
1246+#
1247+##############################################################################
1248+
1249+from osv import osv
1250+from osv import fields
1251+
1252+import netsvc
1253+import time
1254+
1255+from tools.translate import _
1256+
1257+
1258+class procurement_list_line_split(osv.osv_memory):
1259+ _name = 'procurement.list.line.split'
1260+ _description = 'Wizard to split a line into two lines'
1261+
1262+ _columns = {
1263+ 'line_id': fields.many2one('procurement.list.line', string='Line to split'),
1264+ 'qty': fields.float(digits=(16,2), string='Quantity for the new line', required=True),
1265+ }
1266+
1267+ def default_get(self, cr, uid, fields, context={}):
1268+ '''
1269+ Fills information for the wizard
1270+ '''
1271+ line_obj = self.pool.get('procurement.list.line')
1272+
1273+ res = super(procurement_list_line_split, self).default_get(cr, uid, fields, context)
1274+ line_id = context.get('line_id', False)
1275+ state = context.get('state', False)
1276+
1277+ if not line_id:
1278+ return res
1279+
1280+ line = line_obj.browse(cr, uid, line_id, context=context)
1281+ if state == 'done':
1282+ raise osv.except_osv(_('Error'), _('You cannot split a line in a Done Procurement Request'))
1283+
1284+ res['line_id'] = line_id
1285+
1286+ # Default quantity = Old quantity divided by 2
1287+ res['qty'] = line_obj.browse(cr, uid, line_id, context=context).product_qty/2
1288+
1289+ return res
1290+
1291+ def split(self, cr, uid, ids, context={}):
1292+ '''
1293+ Changes the quantity of the old line and creates a new line with the
1294+ new quantity
1295+ '''
1296+ if ids and isinstance(ids, (int, long)):
1297+ ids = [ids]
1298+ line_obj = self.pool.get('procurement.list.line')
1299+
1300+ for obj in self.browse(cr, uid, ids, context=context):
1301+ # Returns an error if the quantity is negative
1302+ if obj.qty < 0.00:
1303+ raise osv.except_osv(_('Error'), _('The new quantity should be positive'))
1304+ if obj.qty > obj.line_id.product_qty:
1305+ raise osv.except_osv(_('Error'), _('The new quantity can\'t be superior to the quantity of initial line'))
1306+ # Changes the quantity on the old line
1307+ line_obj.write(cr, uid, [obj.line_id.id], {'product_qty': obj.line_id.product_qty-obj.qty})
1308+ # Creates the new line with new quantity
1309+ line_obj.create(cr, uid, {'list_id': obj.line_id.list_id.id,
1310+ 'product_id': obj.line_id.product_id.id,
1311+ 'product_uom_id': obj.line_id.product_uom_id.id,
1312+ 'product_qty': obj.qty,
1313+ 'supplier_id': False,})
1314+
1315+ return {'type': 'ir.actions.act_window_close'}
1316+
1317+procurement_list_line_split()
1318+
1319+
1320+class procurement_list_line_merge(osv.osv_memory):
1321+ _name = 'procurement.list.line.merge'
1322+ _description = 'Merge Lines'
1323+
1324+ _columns = {
1325+ 'line_id': fields.many2one('procurement.list.line', string='Line to merged', readonly=True),
1326+ 'line_ids': fields.many2many('procurement.list.line', 'merge_line_rel', 'merge_id', 'line_id',
1327+ string='Lines to merged'),
1328+ }
1329+
1330+ def default_get(self, cr, uid, fields, context={}):
1331+ '''
1332+ Initializes data with only lines with the same product and the same
1333+ procurement list
1334+
1335+ '''
1336+ line_obj = self.pool.get('procurement.list.line')
1337+ res = {}
1338+
1339+ line_id = context.get('line_id', False)
1340+ state = context.get('state', False)
1341+ if not line_id:
1342+ raise osv.except_osv(_('Error'), _('No lines to merged'))
1343+
1344+ line = line_obj.browse(cr, uid, line_id, context=context)
1345+ if state == 'done':
1346+ raise osv.except_osv(_('Error'), _('You cannot merge a line in a Done Procurement Request'))
1347+ product_id = line.product_id.id
1348+ product_uom = line.product_uom_id.id
1349+ wizard_id = line.list_id.id
1350+
1351+ res['line_id'] = line_id
1352+ res['line_ids']= line_obj.search(cr, uid, [('list_id', '=', wizard_id),
1353+ ('product_id', '=', product_id),
1354+ ('product_uom_id', '=', product_uom)])
1355+
1356+ if line_id in res['line_ids']:
1357+ res['line_ids'].remove(line_id)
1358+
1359+ return res
1360+
1361+ def merge_confirm(self, cr, uid, ids, context={}):
1362+ '''
1363+ Merged lines
1364+ '''
1365+ if ids and isinstance(ids, (int, long)):
1366+ ids = [ids]
1367+ line_obj = self.pool.get('procurement.list.line')
1368+
1369+ for obj in self.browse(cr, uid, ids, context=context):
1370+ # Get the supplier of the main line because if merge no lines,
1371+ # the supplier shouldn't removed
1372+ supplier_id = obj.line_id.supplier_id.id
1373+ qty = obj.line_id.product_qty
1374+ for line in obj.line_ids:
1375+ qty += line.product_qty
1376+ supplier_id = False
1377+ line_obj.unlink(cr, uid, [line.id])
1378+
1379+ line_obj.write(cr, uid, [obj.line_id.id], {'product_qty': qty, 'supplier_id': supplier_id})
1380+
1381+ return {'type': 'ir.actions.act_window_close'}
1382+
1383+procurement_list_line_merge()
1384+
1385+
1386+class procurement_choose_supplier_rfq(osv.osv_memory):
1387+ _name = 'procurement.choose.supplier.rfq'
1388+ _description = 'Choose Supplier tp generate RfQ'
1389+
1390+ _columns = {
1391+ 'choose_id': fields.many2one('procurement.list', string='Wizard'),
1392+ 'supplier_ids': fields.many2many('res.partner', 'supplier_rfq_rel', 'rfq_id', 'supplier_id',
1393+ string='Suppliers', domain=[('supplier', '=', 1)]),
1394+ }
1395+
1396+ def default_get(self, cr, uid, fields, context={}):
1397+ '''
1398+ Fills information in the wizard
1399+ '''
1400+ res = super(procurement_choose_supplier_rfq, self).default_get(cr, uid, fields, context=context)
1401+ wizard_id = context.get('active_id', False)
1402+
1403+ if not wizard_id:
1404+ return res
1405+
1406+ res['choose_id'] = wizard_id
1407+
1408+ return res
1409+
1410+ def create_rfq(self, cr, uid, ids, context={}):
1411+ '''
1412+ Creates Requests for Quotation for each supplier with all lines
1413+ '''
1414+ if ids and isinstance(ids, (int, long)):
1415+ ids = [ids]
1416+ order_obj = self.pool.get('purchase.order')
1417+ order_line_obj = self.pool.get('purchase.order.line')
1418+ proc_list_obj = self.pool.get('procurement.list')
1419+ proc_line_obj = self.pool.get('procurement.list.line')
1420+
1421+ po_ids = [] # List of all created RfQ
1422+
1423+ for obj in self.browse(cr, uid, ids):
1424+ origin = obj.choose_id.name
1425+ location_id = proc_list_obj._get_location(cr, uid, obj.choose_id.warehouse_id)
1426+
1427+ lines = []
1428+ for l in obj.choose_id.line_ids:
1429+ lines.append({'line_id': l.id,
1430+ 'product_id': l.product_id.id,
1431+ 'product_uom': l.product_uom_id.id,
1432+ 'product_name': l.product_id.name,
1433+ 'product_qty': l.product_qty,})
1434+
1435+ # Creates one RfQ for each supplier
1436+ for s in obj.supplier_ids:
1437+ po_id = order_obj.create(cr, uid, {'partner_id': s.id,
1438+ 'partner_address_id': s.address_get().get('default'),
1439+ 'pricelist_id': s.property_product_pricelist.id,
1440+ 'origin': origin,
1441+ 'location_id': location_id})
1442+ po_ids.append(po_id)
1443+ # Creates lines
1444+ for l in lines:
1445+ order_line_obj.create(cr, uid, {'product_uom': l.get('product_uom'),
1446+ 'product_id': l.get('product_id'),
1447+ 'order_id': po_id,
1448+ 'price_unit': 0.00,
1449+ 'date_planned': obj.choose_id.order_date,
1450+ 'product_qty': l.get('product_qty'),
1451+ 'name': l.get('product_name'),
1452+ })
1453+
1454+ proc_id = self.browse(cr, uid, ids[0]).choose_id.id
1455+ proc_list_obj.write(cr, uid, proc_id, {'state': 'done', 'order_ids': [(6, 0, po_ids)]})
1456+
1457+ return {'type': 'ir.actions.act_window',
1458+ 'res_model': 'purchase.order',
1459+ 'view_type': 'form',
1460+ 'view_mode': 'tree,form',
1461+ 'domain': [('id', 'in', po_ids)]}
1462+
1463+procurement_choose_supplier_rfq()
1464+
1465+
1466+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
1467+
1468
1469=== added file 'procurement_list/wizard/choose_supplier_view.xml'
1470--- procurement_list/wizard/choose_supplier_view.xml 1970-01-01 00:00:00 +0000
1471+++ procurement_list/wizard/choose_supplier_view.xml 2011-03-24 15:56:19 +0000
1472@@ -0,0 +1,59 @@
1473+<?xml version="1.0" encoding="utf-8" ?>
1474+<openerp>
1475+ <data>
1476+
1477+ <record id="choose_supplier_line_split_qty" model="ir.ui.view">
1478+ <field name="name">choose.supplier.line.split.qty</field>
1479+ <field name="model">procurement.list.line.split</field>
1480+ <field name="type">form</field>
1481+ <field name="arch" type="xml">
1482+ <form string="Split line">
1483+ <separator colspan="4" string="New quantity" />
1484+ <field name="qty" colspan="4" />
1485+ <separator colspan="4" string="Actions" />
1486+ <button special="cancel" string="Cancel" icon="gtk-cancel" colspan="2" type="object" />
1487+ <button name="split" string="New line" icon="gtk-ok" colspan="2" type="object" />
1488+ </form>
1489+ </field>
1490+ </record>
1491+
1492+ <record id="choose_supplier_line_merge" model="ir.ui.view">
1493+ <field name="name">choose.supplier.line.merge</field>
1494+ <field name="model">procurement.list.line.merge</field>
1495+ <field name="type">form</field>
1496+ <field name="arch" type="xml">
1497+ <form string="Merge lines">
1498+ <separator colspan="4" string="Possible lines to merge" />
1499+ <field name="line_ids" colspan="4" nolabel="1" >
1500+ <tree string="Lines">
1501+ <field name="product_id" />
1502+ <field name="product_qty" />
1503+ <field name="product_uom_id" />
1504+ <field name="supplier_id" />
1505+ </tree>
1506+ </field>
1507+ <separator colspan="4" />
1508+ <button special="cancel" string="Cancel" icon="gtk-cancel" colspan="2" type="object" />
1509+ <button name="merge_confirm" string="Merge" icon="gtk-ok" colspan="2" type="object" />
1510+ </form>
1511+ </field>
1512+ </record>
1513+
1514+ <record id="choose_supplier_rfq_form_view" model="ir.ui.view">
1515+ <field name="name">choose.supplier.rfq.form.view</field>
1516+ <field name="model">procurement.choose.supplier.rfq</field>
1517+ <field name="type">form</field>
1518+ <field name="arch" type="xml">
1519+ <form string="Choose Suppliers">
1520+ <separator colspan="4" string="Suppliers" />
1521+ <field name="supplier_ids" colspan="4" nolabel="1" />
1522+ <separator colspan="4" />
1523+ <button special="cancel" string="Cancel" icon="gtk-cancel" colspan="2" type="object" />
1524+ <button name="create_rfq" type="object" string="Create RfQ" icon="gtk-execute" />
1525+ </form>
1526+ </field>
1527+ </record>
1528+
1529+ </data>
1530+</openerp>
1531+
1532
1533=== removed directory 'stock_inventory_type'
1534=== removed file 'stock_inventory_type/__init__.py'
1535--- stock_inventory_type/__init__.py 2011-03-15 17:05:15 +0000
1536+++ stock_inventory_type/__init__.py 1970-01-01 00:00:00 +0000
1537@@ -1,28 +0,0 @@
1538-#!/usr/bin/env python
1539-# -*- encoding: utf-8 -*-
1540-##############################################################################
1541-#
1542-# OpenERP, Open Source Management Solution
1543-# Copyright (C) 2011 TeMPO Consulting, MSF
1544-#
1545-# This program is free software: you can redistribute it and/or modify
1546-# it under the terms of the GNU Affero General Public License as
1547-# published by the Free Software Foundation, either version 3 of the
1548-# License, or (at your option) any later version.
1549-#
1550-# This program is distributed in the hope that it will be useful,
1551-# but WITHOUT ANY WARRANTY; without even the implied warranty of
1552-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1553-# GNU Affero General Public License for more details.
1554-#
1555-# You should have received a copy of the GNU Affero General Public License
1556-# along with this program. If not, see <http://www.gnu.org/licenses/>.
1557-#
1558-##############################################################################
1559-
1560-
1561-import stock
1562-import stock_move_report
1563-
1564-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
1565-
1566
1567=== removed file 'stock_inventory_type/__openerp__.py'
1568--- stock_inventory_type/__openerp__.py 2011-03-15 17:05:15 +0000
1569+++ stock_inventory_type/__openerp__.py 1970-01-01 00:00:00 +0000
1570@@ -1,49 +0,0 @@
1571-# -*- coding: utf-8 -*-
1572-##############################################################################
1573-#
1574-# OpenERP, Open Source Management Solution
1575-# Copyright (C) 2011 TeMPO Consulting, MSF
1576-#
1577-# This program is free software: you can redistribute it and/or modify
1578-# it under the terms of the GNU Affero General Public License as
1579-# published by the Free Software Foundation, either version 3 of the
1580-# License, or (at your option) any later version.
1581-#
1582-# This program is distributed in the hope that it will be useful,
1583-# but WITHOUT ANY WARRANTY; without even the implied warranty of
1584-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1585-# GNU Affero General Public License for more details.
1586-#
1587-# You should have received a copy of the GNU Affero General Public License
1588-# along with this program. If not, see <http://www.gnu.org/licenses/>.
1589-#
1590-##############################################################################
1591-{
1592- "name" : "Stock Adjustment/Move Report",
1593- "version" : "1.0",
1594- "author" : "TeMPO Consulting, MSF",
1595- "category": "Inventory Control",
1596- "description": """
1597- This module aims to help you to determine the type \
1598- of your inventory adjustment and to search stock move \
1599- by type of adjustment.
1600- """,
1601- "website": "http://unifield.msf.org",
1602- "init_xml": [
1603- ],
1604- "depends" : [
1605- "stock",
1606- ],
1607- "update_xml": [
1608- "stock_view.xml",
1609- "stock_data.xml",
1610- "security/ir.model.access.csv",
1611- ],
1612- "demo_xml": [
1613- ],
1614- "test": [
1615- "test/adjustment_type.yml",
1616- ],
1617- "installable": True,
1618- "active": False,
1619-}
1620
1621=== removed directory 'stock_inventory_type/security'
1622=== removed file 'stock_inventory_type/security/ir.model.access.csv'
1623--- stock_inventory_type/security/ir.model.access.csv 2011-03-09 14:54:31 +0000
1624+++ stock_inventory_type/security/ir.model.access.csv 1970-01-01 00:00:00 +0000
1625@@ -1,2 +0,0 @@
1626-"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
1627-"access_stock_adjustment_type_all","stock.adjustment.type all","model_stock_adjustment_type",,1,1,1,1
1628
1629=== removed file 'stock_inventory_type/stock.py'
1630--- stock_inventory_type/stock.py 2011-03-15 17:05:15 +0000
1631+++ stock_inventory_type/stock.py 1970-01-01 00:00:00 +0000
1632@@ -1,135 +0,0 @@
1633-#!/usr/bin/env python
1634-# -*- encoding: utf-8 -*-
1635-##############################################################################
1636-#
1637-# OpenERP, Open Source Management Solution
1638-# Copyright (C) 2011 TeMPO Consulting, MSF
1639-#
1640-# This program is free software: you can redistribute it and/or modify
1641-# it under the terms of the GNU Affero General Public License as
1642-# published by the Free Software Foundation, either version 3 of the
1643-# License, or (at your option) any later version.
1644-#
1645-# This program is distributed in the hope that it will be useful,
1646-# but WITHOUT ANY WARRANTY; without even the implied warranty of
1647-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1648-# GNU Affero General Public License for more details.
1649-#
1650-# You should have received a copy of the GNU Affero General Public License
1651-# along with this program. If not, see <http://www.gnu.org/licenses/>.
1652-#
1653-##############################################################################
1654-
1655-
1656-from osv import osv
1657-from osv import fields
1658-
1659-from tools.translate import _
1660-
1661-
1662-class stock_adjustment_type(osv.osv):
1663- _name = 'stock.adjustment.type'
1664- _description = 'Inventory/Move Adjustment Types'
1665-
1666- _columns = {
1667- 'name': fields.char(size=64, string='Name', required=True),
1668- }
1669-
1670-stock_adjustment_type()
1671-
1672-
1673-class stock_inventory_line(osv.osv):
1674- _name = 'stock.inventory.line'
1675- _inherit = 'stock.inventory.line'
1676-
1677- _columns = {
1678- 'type_id': fields.many2one('stock.adjustment.type', string='Adjustment type'),
1679- 'comment': fields.char(size=128, string='Comment'),
1680- }
1681-
1682-stock_inventory_line()
1683-
1684-
1685-class stock_move(osv.osv):
1686- _name = 'stock.move'
1687- _inherit = 'stock.move'
1688-
1689- _columns = {
1690- 'type_id': fields.many2one('stock.adjustment.type', string='Adjustment type', readonly=True),
1691- 'comment': fields.char(size=128, string='Comment'),
1692- }
1693-
1694-stock_move()
1695-
1696-
1697-class stock_inventory(osv.osv):
1698- _name = 'stock.inventory'
1699- _inherit = 'stock.inventory'
1700-
1701- def action_confirm(self, cr, uid, ids, context={}):
1702- """ Confirm the inventory and writes its finished date
1703- @return True
1704- """
1705- # @@@override@ stock.stock_inventory.action_confirm()
1706- # to perform the correct inventory corrections we need analyze stock location by
1707- # location, never recursively, so we use a special context
1708- product_context = dict(context, compute_child=False)
1709-
1710- location_obj = self.pool.get('stock.location')
1711- for inv in self.browse(cr, uid, ids, context=context):
1712- move_ids = []
1713- for line in inv.inventory_line_id:
1714- pid = line.product_id.id
1715- product_context.update(uom=line.product_uom.id,date=inv.date)
1716- amount = location_obj._product_get(cr, uid, line.location_id.id, [pid], product_context)[pid]
1717-
1718- change = line.product_qty - amount
1719- lot_id = line.prod_lot_id.id
1720- type_id = line.type_id.id
1721- if change:
1722- location_id = line.product_id.product_tmpl_id.property_stock_inventory.id
1723- value = {
1724- 'name': 'INV:' + str(line.inventory_id.id) + ':' + line.inventory_id.name,
1725- 'product_id': line.product_id.id,
1726- 'product_uom': line.product_uom.id,
1727- 'prodlot_id': lot_id,
1728- 'date': inv.date,
1729- # msf
1730- 'comment': line.comment,
1731- #
1732- }
1733- if change > 0:
1734- value.update( {
1735- 'product_qty': change,
1736- 'location_id': location_id,
1737- 'location_dest_id': line.location_id.id,
1738- })
1739- else:
1740- value.update( {
1741- 'product_qty': -change,
1742- 'location_id': line.location_id.id,
1743- 'location_dest_id': location_id,
1744- })
1745- if lot_id:
1746- value.update({
1747- 'prodlot_id': lot_id,
1748- 'product_qty': line.product_qty
1749- })
1750- # msf
1751- if type_id:
1752- value.update({
1753- 'type_id': type_id,
1754- })
1755- #
1756- move_ids.append(self._inventory_line_hook(cr, uid, line, value))
1757- message = _('Inventory') + " '" + inv.name + "' "+ _("is done.")
1758- self.log(cr, uid, inv.id, message)
1759- self.write(cr, uid, [inv.id], {'state': 'confirm', 'move_ids': [(6, 0, move_ids)]})
1760-
1761- return True
1762- # @@@end
1763-
1764-stock_inventory()
1765-
1766-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
1767-
1768
1769=== removed file 'stock_inventory_type/stock_data.xml'
1770--- stock_inventory_type/stock_data.xml 2011-03-09 14:54:31 +0000
1771+++ stock_inventory_type/stock_data.xml 1970-01-01 00:00:00 +0000
1772@@ -1,23 +0,0 @@
1773-<?xml version="1.0" encoding="utf-8" ?>
1774-<openerp>
1775- <data>
1776-
1777- <record id="adjustment_type_loss" model="stock.adjustment.type">
1778- <field name="name">Loss</field>
1779- </record>
1780-
1781- <record id="adjustment_type_scrap" model="stock.adjustment.type">
1782- <field name="name">Scrap</field>
1783- </record>
1784-
1785- <record id="adjustment_type_expired" model="stock.adjustment.type">
1786- <field name="name">Expired</field>
1787- </record>
1788-
1789- <record id="adjustment_type_broken" model="stock.adjustment.type">
1790- <field name="name">Broken</field>
1791- </record>
1792-
1793- </data>
1794-</openerp>
1795-
1796
1797=== removed file 'stock_inventory_type/stock_move_report.py'
1798--- stock_inventory_type/stock_move_report.py 2011-03-15 17:05:15 +0000
1799+++ stock_inventory_type/stock_move_report.py 1970-01-01 00:00:00 +0000
1800@@ -1,130 +0,0 @@
1801-# -*- coding: utf-8 -*-
1802-##############################################################################
1803-#
1804-# OpenERP, Open Source Management Solution
1805-# Copyright (C) 2011 TeMPO Consulting, MSF
1806-#
1807-# This program is free software: you can redistribute it and/or modify
1808-# it under the terms of the GNU Affero General Public License as
1809-# published by the Free Software Foundation, either version 3 of the
1810-# License, or (at your option) any later version.
1811-#
1812-# This program is distributed in the hope that it will be useful,
1813-# but WITHOUT ANY WARRANTY; without even the implied warranty of
1814-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1815-# GNU Affero General Public License for more details.
1816-#
1817-# You should have received a copy of the GNU Affero General Public License
1818-# along with this program. If not, see <http://www.gnu.org/licenses/>.
1819-#
1820-##############################################################################
1821-
1822-from osv import osv
1823-from osv import fields
1824-
1825-from decimal_precision import decimal_precision as dp
1826-
1827-import tools
1828-
1829-
1830-class report_stock_move(osv.osv):
1831- _name = 'report.stock.move'
1832- _inherit = 'report.stock.move'
1833-
1834- _columns = {
1835- 'type_id': fields.many2one('stock.adjustment.type', string='Adjustment type'),
1836- }
1837-
1838- def init(self, cr):
1839- # @@@override@ stock.report_stock_move.init
1840- tools.drop_view_if_exists(cr, 'report_stock_move')
1841- cr.execute("""
1842- CREATE OR REPLACE view report_stock_move AS (
1843- SELECT
1844- min(sm_id) as id,
1845- sm_type_id as type_id,
1846- date_trunc('day',al.dp) as date,
1847- al.curr_year as year,
1848- al.curr_month as month,
1849- al.curr_day as day,
1850- al.curr_day_diff as day_diff,
1851- al.curr_day_diff1 as day_diff1,
1852- al.curr_day_diff2 as day_diff2,
1853- al.location_id as location_id,
1854- al.picking_id as picking_id,
1855- al.company_id as company_id,
1856- al.location_dest_id as location_dest_id,
1857- al.product_qty,
1858- al.out_qty as product_qty_out,
1859- al.in_qty as product_qty_in,
1860- al.address_id as partner_id,
1861- al.product_id as product_id,
1862- al.state as state ,
1863- al.product_uom as product_uom,
1864- al.categ_id as categ_id,
1865- coalesce(al.type, 'other') as type,
1866- al.stock_journal as stock_journal,
1867- sum(al.in_value - al.out_value) as value
1868- FROM (SELECT
1869- CASE WHEN sp.type in ('out') THEN
1870- sum(sm.product_qty * pu.factor)
1871- ELSE 0.0
1872- END AS out_qty,
1873- CASE WHEN sp.type in ('in') THEN
1874- sum(sm.product_qty * pu.factor)
1875- ELSE 0.0
1876- END AS in_qty,
1877- CASE WHEN sp.type in ('out') THEN
1878- sum(sm.product_qty * pu.factor) * pt.standard_price
1879- ELSE 0.0
1880- END AS out_value,
1881- CASE WHEN sp.type in ('in') THEN
1882- sum(sm.product_qty * pu.factor) * pt.standard_price
1883- ELSE 0.0
1884- END AS in_value,
1885- min(sm.id) as sm_id,
1886- sm.date as dp,
1887- sm.type_id as sm_type_id,
1888- to_char(date_trunc('day',sm.date), 'YYYY') as curr_year,
1889- to_char(date_trunc('day',sm.date), 'MM') as curr_month,
1890- to_char(date_trunc('day',sm.date), 'YYYY-MM-DD') as curr_day,
1891- avg(date(sm.date)-date(sm.create_date)) as curr_day_diff,
1892- avg(date(sm.date_expected)-date(sm.create_date)) as curr_day_diff1,
1893- avg(date(sm.date)-date(sm.date_expected)) as curr_day_diff2,
1894- sm.location_id as location_id,
1895- sm.location_dest_id as location_dest_id,
1896- sum(sm.product_qty) as product_qty,
1897- pt.categ_id as categ_id ,
1898- sm.address_id as address_id,
1899- sm.product_id as product_id,
1900- sm.picking_id as picking_id,
1901- sm.company_id as company_id,
1902- sm.state as state,
1903- sm.product_uom as product_uom,
1904- sp.type as type,
1905- sp.stock_journal_id AS stock_journal
1906- FROM
1907- stock_move sm
1908- LEFT JOIN stock_picking sp ON (sm.picking_id=sp.id)
1909- LEFT JOIN product_product pp ON (sm.product_id=pp.id)
1910- LEFT JOIN product_uom pu ON (sm.product_uom=pu.id)
1911- LEFT JOIN product_template pt ON (pp.product_tmpl_id=pt.id)
1912- LEFT JOIN stock_location sl ON (sm.location_id = sl.id)
1913-
1914- GROUP BY
1915- sm.id,sp.type, sm.date,sm.address_id, sm.type_id,
1916- sm.product_id,sm.state,sm.product_uom,sm.date_expected,
1917- sm.product_id,pt.standard_price, sm.picking_id, sm.product_qty,
1918- sm.company_id,sm.product_qty, sm.location_id,sm.location_dest_id,pu.factor,pt.categ_id, sp.stock_journal_id)
1919- AS al
1920-
1921- GROUP BY
1922- al.out_qty,al.in_qty,al.curr_year,al.curr_month, al.sm_type_id,
1923- al.curr_day,al.curr_day_diff,al.curr_day_diff1,al.curr_day_diff2,al.dp,al.location_id,al.location_dest_id,
1924- al.address_id,al.product_id,al.state,al.product_uom,
1925- al.picking_id,al.company_id,al.type,al.product_qty, al.categ_id, al.stock_journal
1926- )
1927- """)
1928- # @@@end
1929-
1930-report_stock_move()
1931
1932=== removed file 'stock_inventory_type/stock_view.xml'
1933--- stock_inventory_type/stock_view.xml 2011-03-15 17:05:15 +0000
1934+++ stock_inventory_type/stock_view.xml 1970-01-01 00:00:00 +0000
1935@@ -1,196 +0,0 @@
1936-<?xml version="1.0" encoding="utf-8" ?>
1937-<openerp>
1938- <data>
1939-
1940- <!-- Stock Adjustment Types -->
1941-
1942- <record id="stock_adjustment_type_form_view" model="ir.ui.view">
1943- <field name="name">stock.adjustment.type.form.view</field>
1944- <field name="model">stock.adjustment.type</field>
1945- <field name="type">form</field>
1946- <field name="arch" type="xml">
1947- <form string="Adjustment Type">
1948- <field name="name" colspan="4" select="1" />
1949- </form>
1950- </field>
1951- </record>
1952-
1953- <record id="stock_adjustment_type_tree_view" model="ir.ui.view">
1954- <field name="name">stock.adjustment.type.tree.view</field>
1955- <field name="model">stock.adjustment.type</field>
1956- <field name="type">tree</field>
1957- <field name="arch" type="xml">
1958- <tree string="Adjustment Types">
1959- <field name="name" />
1960- </tree>
1961- </field>
1962- </record>
1963-
1964- <record id="action_stock_adjustment_type" model="ir.actions.act_window">
1965- <field name="name">Stock Adjustment Types</field>
1966- <field name="res_model">stock.adjustment.type</field>
1967- <field name="view_type">form</field>
1968- <field name="view_mode">tree,form</field>
1969- </record>
1970-
1971- <menuitem
1972- name="Inventory"
1973- id="menu_configuration_inventory"
1974- parent="stock.menu_stock_configuration" />
1975-
1976- <menuitem
1977- action="action_stock_adjustment_type"
1978- id="menu_stock_adjustment_type"
1979- parent="menu_configuration_inventory" />
1980-
1981-
1982- <!-- Overrirde Stock Inventory Lines -->
1983- <record id="stock_inventory_line_tree_type_id" model="ir.ui.view">
1984- <field name="name">stock.inventory.line.tree.type.id</field>
1985- <field name="model">stock.inventory.line</field>
1986- <field name="type">tree</field>
1987- <field name="inherit_id" ref="stock.stock_inventory_line_tree" />
1988- <field name="arch" type="xml">
1989- <xpath expr="/tree/field[@name='prodlot_id']" position="after">
1990- <field name="type_id" widget="selection" />
1991- <field name="comment" />
1992- </xpath>
1993- </field>
1994- </record>
1995-
1996- <record id="stock_inventory_line_form_type_id" model="ir.ui.view">
1997- <field name="name">stock.inventory.line.form.type.id</field>
1998- <field name="model">stock.inventory.line</field>
1999- <field name="type">form</field>
2000- <field name="inherit_id" ref="stock.stock_inventory_line_tree" />
2001- <field name="arch" type="xml">
2002- <xpath expr="/form/field[@name='prodlot_id']" position="after">
2003- <field name="type_id" widget="selection" />
2004- <field name="comment" />
2005- </xpath>
2006- </field>
2007- </record>
2008-
2009- <record id="stock_inventory_form_type_id" model="ir.ui.view">
2010- <field name="name">stock.inventory.form.type.id</field>
2011- <field name="model">stock.inventory</field>
2012- <field name="type">form</field>
2013- <field name="inherit_id" ref="stock.view_inventory_form" />
2014- <field name="arch" type="xml">
2015- <data>
2016- <xpath expr="/form/notebook/page/field[@name='inventory_line_id']/tree/field[@name='product_id']" position="after">
2017- <field name="type_id" widget="selection" />
2018- <field name="comment" />
2019- </xpath>
2020- <xpath expr="/form/notebook/page/field[@name='inventory_line_id']/form/field[@name='product_id']" position="after">
2021- <field name="type_id" widget="selection" />
2022- <field name="comment" />
2023- </xpath>
2024- <xpath expr="/form/notebook/page[@string='Posted Inventory']/field[@name='move_ids']/tree/field[@name='prodlot_id']" position="after">
2025- <field name="type_id" widget="selection" />
2026- </xpath>
2027- </data>
2028- </field>
2029- </record>
2030-
2031- <!-- Override Stock Moves -->
2032- <record id="stock_move_tree_type_id" model="ir.ui.view">
2033- <field name="name">stock.move.tree.type.id</field>
2034- <field name="model">stock.move</field>
2035- <field name="type">tree</field>
2036- <field name="inherit_id" ref="stock.stock_move_tree" />
2037- <field name="arch" type="xml">
2038- <xpath expr="/tree/field[@name='prodlot_id']" position="after">
2039- <field name="type_id" widget="selection" />
2040- <field name="comment" />
2041- </xpath>
2042- </field>
2043- </record>
2044-
2045- <record id="stock_move_tree2_type_id" model="ir.ui.view">
2046- <field name="name">stock.move.tree2.type.id</field>
2047- <field name="model">stock.move</field>
2048- <field name="type">tree</field>
2049- <field name="inherit_id" ref="stock.stock_move_tree2" />
2050- <field name="arch" type="xml">
2051- <xpath expr="/tree/field[@name='prodlot_id']" position="after">
2052- <field name="type_id" widget="selection" />
2053- <field name="comment" />
2054- </xpath>
2055- </field>
2056- </record>
2057-
2058- <record id="view_move_tree_type_id" model="ir.ui.view">
2059- <field name="name">view.move.tree.type.id</field>
2060- <field name="model">stock.move</field>
2061- <field name="type">tree</field>
2062- <field name="inherit_id" ref="stock.view_move_tree" />
2063- <field name="arch" type="xml">
2064- <xpath expr="/tree/field[@name='create_date']" position="after">
2065- <field name="type_id" widget="selection" />
2066- <field name="comment" />
2067- </xpath>
2068- </field>
2069- </record>
2070-
2071- <record id="view_move_form_type_id" model="ir.ui.view">
2072- <field name="name">view.move.form.type.id</field>
2073- <field name="model">stock.move</field>
2074- <field name="type">form</field>
2075- <field name="inherit_id" ref="stock.view_move_form" />
2076- <field name="arch" type="xml">
2077- <xpath expr="/form/group/button[@string='Scrap']" position="after">
2078- <field name="type_id" widget="selection" />
2079- <field name="comment" />
2080- </xpath>
2081- </field>
2082- </record>
2083-
2084- <record id="view_move_search_type_id" model="ir.ui.view">
2085- <field name="name">view.move.search.type.id</field>
2086- <field name="model">stock.move</field>
2087- <field name="type">search</field>
2088- <field name="inherit_id" ref="stock.view_move_search" />
2089- <field name="arch" type="xml">
2090- <xpath expr="/search/group/field[@name='product_id']" position="before">
2091- <field name="type_id" widget="selection" />
2092- <field name="comment" />
2093- </xpath>
2094- </field>
2095- </record>
2096-
2097- <record id="view_stock_tree_type_id" model="ir.ui.view">
2098- <field name="name">view.stock.tree.type.id</field>
2099- <field name="model">report.stock.move</field>
2100- <field name="type">tree</field>
2101- <field name="inherit_id" ref="stock.view_stock_tree" />
2102- <field name="arch" type="xml">
2103- <xpath expr="/tree/field[@name='type']" position="after">
2104- <field name="type_id" />
2105- </xpath>
2106- </field>
2107- </record>
2108-
2109- <record id="view_stock_search_type_id" model="ir.ui.view">
2110- <field name="name">view.stock.search.type.id</field>
2111- <field name="model">report.stock.move</field>
2112- <field name="type">search</field>
2113- <field name="inherit_id" ref="stock.view_stock_search" />
2114- <field name="arch" type="xml">
2115- <data>
2116- <xpath expr="/search/group/separator[3]" position="after">
2117- <field name="type_id" widget="selection" />
2118- </xpath>
2119- <xpath expr="/search/group[@string='Group By...']/filter[@name='group_type']" position="after">
2120- <filter string="Adjustment Type" name="group_type_id" icon="terp-stock_symbol-selection" context="{'group_by':'type_id'}" />
2121- </xpath>
2122- <xpath expr="/search/group[@string='Group By...']/separator[5]" position="replace">
2123- <newline />
2124- </xpath>
2125- </data>
2126- </field>
2127- </record>
2128-
2129- </data>
2130-</openerp>
2131-
2132
2133=== removed directory 'stock_inventory_type/test'
2134=== removed file 'stock_inventory_type/test/adjustment_type.yml'
2135--- stock_inventory_type/test/adjustment_type.yml 2011-03-09 16:36:19 +0000
2136+++ stock_inventory_type/test/adjustment_type.yml 1970-01-01 00:00:00 +0000
2137@@ -1,117 +0,0 @@
2138--
2139- In order to test the stock_inventory_type module, I will create product,
2140- create a physical inventory, fill inventory lines from location
2141--
2142- I create a product category
2143--
2144- !record {model: product.category, id: product_category1}:
2145- name: Categ1
2146--
2147- I create the first product (P1)
2148--
2149- !record {model: product.product, id: product_p1}:
2150- valuation: manual_periodic
2151- supply_method: produce
2152- mes_type: fixed
2153- uom_id: product.product_uom_unit
2154- uom_po_id: product.product_uom_unit
2155- type: product
2156- procure_method: make_to_stock
2157- cost_method: standard
2158- categ_id: stock_inventory_type.product_category1
2159- name: P1
2160- standard_price: 10.0
2161--
2162- I create the second product (P2)
2163--
2164- !record {model: product.product, id: product_p2}:
2165- valuation: manual_periodic
2166- supply_method: produce
2167- mes_type: fixed
2168- uom_id: product.product_uom_unit
2169- uom_po_id: product.product_uom_unit
2170- type: product
2171- procure_method: make_to_stock
2172- cost_method: standard
2173- categ_id: stock_inventory_type.product_category1
2174- name: P2
2175- standard_price: 20.0
2176--
2177- I create the third product (P3)
2178--
2179- !record {model: product.product, id: product_p3}:
2180- valuation: manual_periodic
2181- supply_method: produce
2182- mes_type: fixed
2183- uom_id: product.product_uom_unit
2184- uom_po_id: product.product_uom_unit
2185- type: product
2186- procure_method: make_to_stock
2187- cost_method: standard
2188- categ_id: stock_inventory_type.product_category1
2189- name: P3
2190- standard_price: 30.0
2191--
2192- I create a physical inventory
2193--
2194- !record {model: stock.inventory, id: stock_inventory1}:
2195- company_id: base.main_company
2196- date: !eval time.strftime('%Y-%m-%d %H:%M:%S')
2197- inventory_line_id:
2198- - company_id: base.main_company
2199- location_id: stock.stock_location_stock
2200- product_id: stock_inventory_type.product_p1
2201- product_qty: 70.0
2202- product_uom: product.product_uom_unit
2203- type_id: stock_inventory_type.adjustment_type_loss
2204- comment: Loss items
2205- - company_id: base.main_company
2206- location_id: stock.stock_location_stock
2207- product_id: stock_inventory_type.product_p2
2208- product_qty: 50.0
2209- product_uom: product.product_uom_unit
2210- type_id: stock_inventory_type.adjustment_type_expired
2211- comment: Expired product at 12/12/2012
2212- - company_id: base.main_company
2213- location_id: stock.stock_location_stock
2214- product_id: stock_inventory_type.product_p3
2215- product_qty: 10.0
2216- product_uom: product.product_uom_unit
2217- type_id: stock_inventory_type.adjustment_type_scrap
2218- name: Test of UNI-SUP-1.15
2219- state: draft
2220--
2221- I confirm the Inventory
2222--
2223- !python {model: stock.inventory}: |
2224- self.action_confirm(cr, uid, [ref('stock_inventory1')])
2225- self.action_done(cr, uid, [ref('stock_inventory1')])
2226--
2227- I check the 'Loss' stock moves
2228--
2229- !python {model: stock.move}: |
2230- move_ids = self.search(cr, uid, [('type_id', '=', ref('stock_inventory_type.adjustment_type_loss'))])
2231- assert move_ids, "No lines with 'Loss' type"
2232- move = self.browse(cr, uid, move_ids[0])
2233- assert move.product_id.id == ref('stock_inventory_type.product_p1'), "Move product (P1) is not correct"
2234- assert move.product_qty == 70.0, "Move quatity (70.0) is not correct"
2235- assert move.comment == 'Loss items', "Move comment (Loss items) is not correct"
2236--
2237- I check the 'Expired' stock moves
2238--
2239- !python {model: stock.move}: |
2240- move_ids = self.search(cr, uid, [('type_id', '=', ref('stock_inventory_type.adjustment_type_expired'))])
2241- assert move_ids, "No lines with 'Expired' type"
2242- move = self.browse(cr, uid, move_ids[0])
2243- assert move.product_id.id == ref('stock_inventory_type.product_p2'), "Move product (P2) is not correct"
2244- assert move.product_qty == 50.0, "Move quatity (50.0) is not correct"
2245- assert move.comment == 'Expired product at 12/12/2012', "Move comment (Expired product at 12/12/2012) is not correct"
2246--
2247- I check the 'Scrapped' stock moves
2248--
2249- !python {model: stock.move}: |
2250- move_ids = self.search(cr, uid, [('type_id', '=', ref('stock_inventory_type.adjustment_type_scrap'))])
2251- assert move_ids, "No lines with 'Scrap' type"
2252- move = self.browse(cr, uid, move_ids[0])
2253- assert move.product_id.id == ref('stock_inventory_type.product_p3'), "Move product (P3) is not correct"
2254- assert move.product_qty == 10.0, "Move quatity (10.0) is not correct"

Subscribers

People subscribed via source and target branches

to all changes: