Merge lp:~unifield-team/unifield-addons/new-purchase-order-state into lp:unifield-addons
- new-purchase-order-state
- Merge into trunk
Proposed by
Quentin THEURET @Amaris
Status: | Merged |
---|---|
Merged at revision: | 4457 |
Proposed branch: | lp:~unifield-team/unifield-addons/new-purchase-order-state |
Merge into: | lp:unifield-addons |
Diff against target: |
1069 lines (+996/-0) 14 files modified
procurement_list/__init__.py (+25/-0) procurement_list/__openerp__.py (+53/-0) procurement_list/procurement_list.py (+217/-0) procurement_list/procurement_list_sequence.xml (+20/-0) procurement_list/procurement_list_view.xml (+111/-0) procurement_list/procurement_list_wizard.xml (+21/-0) procurement_list/security/ir.model.access.csv (+3/-0) procurement_list/test/list_import.csv (+5/-0) procurement_list/test/procurement_list.yml (+143/-0) procurement_list/wizard/__init__.py (+28/-0) procurement_list/wizard/wizard_import_list.py (+196/-0) procurement_list/wizard/wizard_import_list_view.xml (+48/-0) procurement_list/wizard/wizard_list_to_order.py (+63/-0) procurement_list/wizard/wizard_list_to_rfq.py (+63/-0) |
To merge this branch: | bzr merge lp:~unifield-team/unifield-addons/new-purchase-order-state |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
UniField Dev Team | Pending | ||
Review via email: mp+53577@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
- 4469. By Quentin THEURET @Amaris
-
UF-98: [FIX] Fixed bug on confirmation of a purchase order with a line which hasn't linked procurement list line
- 4470. By Quentin THEURET @Amaris
-
UF-98: [ADD] Added csv file for import test
- 4471. By Quentin THEURET <quentin@tempo-quentin>
-
UF-98: [IMP] Added copy method to procurement.list to increase sequence and set empty the latest field of lines
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === added directory 'procurement_list' | |||
2 | === added file 'procurement_list/__init__.py' | |||
3 | --- procurement_list/__init__.py 1970-01-01 00:00:00 +0000 | |||
4 | +++ procurement_list/__init__.py 2011-03-16 16:41:25 +0000 | |||
5 | @@ -0,0 +1,25 @@ | |||
6 | 1 | # -*- coding: utf-8 -*- | ||
7 | 2 | ############################################################################## | ||
8 | 3 | # | ||
9 | 4 | # OpenERP, Open Source Management Solution | ||
10 | 5 | # Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>). | ||
11 | 6 | # | ||
12 | 7 | # This program is free software: you can redistribute it and/or modify | ||
13 | 8 | # it under the terms of the GNU Affero General Public License as | ||
14 | 9 | # published by the Free Software Foundation, either version 3 of the | ||
15 | 10 | # License, or (at your option) any later version. | ||
16 | 11 | # | ||
17 | 12 | # This program is distributed in the hope that it will be useful, | ||
18 | 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | 15 | # GNU Affero General Public License for more details. | ||
21 | 16 | # | ||
22 | 17 | # You should have received a copy of the GNU Affero General Public License | ||
23 | 18 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
24 | 19 | # | ||
25 | 20 | ############################################################################## | ||
26 | 21 | |||
27 | 22 | import procurement_list | ||
28 | 23 | import wizard | ||
29 | 24 | |||
30 | 25 | # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: | ||
31 | 0 | 26 | ||
32 | === added file 'procurement_list/__openerp__.py' | |||
33 | --- procurement_list/__openerp__.py 1970-01-01 00:00:00 +0000 | |||
34 | +++ procurement_list/__openerp__.py 2011-03-16 16:41:25 +0000 | |||
35 | @@ -0,0 +1,53 @@ | |||
36 | 1 | # -*- coding: utf-8 -*- | ||
37 | 2 | ############################################################################## | ||
38 | 3 | # | ||
39 | 4 | # OpenERP, Open Source Management Solution | ||
40 | 5 | # Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>). | ||
41 | 6 | # | ||
42 | 7 | # This program is free software: you can redistribute it and/or modify | ||
43 | 8 | # it under the terms of the GNU Affero General Public License as | ||
44 | 9 | # published by the Free Software Foundation, either version 3 of the | ||
45 | 10 | # License, or (at your option) any later version. | ||
46 | 11 | # | ||
47 | 12 | # This program is distributed in the hope that it will be useful, | ||
48 | 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
49 | 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
50 | 15 | # GNU Affero General Public License for more details. | ||
51 | 16 | # | ||
52 | 17 | # You should have received a copy of the GNU Affero General Public License | ||
53 | 18 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
54 | 19 | # | ||
55 | 20 | ############################################################################## | ||
56 | 21 | { | ||
57 | 22 | 'name' : 'Purchase list', | ||
58 | 23 | 'version' : '1.0', | ||
59 | 24 | 'author' : 'TeMPO Consulting, MSF', | ||
60 | 25 | 'category': 'Generic Modules/Sales & Purchases', | ||
61 | 26 | 'description': ''' | ||
62 | 27 | This module allows you to create a list of items to procure. You can create automatically RfQ for these lists after choosing a list \ | ||
63 | 28 | of suppliers. You can also compare these RfQ, choose the best supplier for each product and create automatically the associated \ | ||
64 | 29 | purchase orders. | ||
65 | 30 | ''', | ||
66 | 31 | 'website': 'http://unifield.msf.org', | ||
67 | 32 | 'init_xml': [ | ||
68 | 33 | ], | ||
69 | 34 | 'depends' : [ | ||
70 | 35 | 'purchase', | ||
71 | 36 | ], | ||
72 | 37 | 'update_xml': [ | ||
73 | 38 | 'procurement_list_sequence.xml', | ||
74 | 39 | 'procurement_list_view.xml', | ||
75 | 40 | 'procurement_list_wizard.xml', | ||
76 | 41 | 'wizard/wizard_import_list_view.xml', | ||
77 | 42 | 'security/ir.model.access.csv', | ||
78 | 43 | ], | ||
79 | 44 | 'demo_xml': [ | ||
80 | 45 | ], | ||
81 | 46 | 'test': [ | ||
82 | 47 | 'test/procurement_list.yml', | ||
83 | 48 | 'test/procurement_copy.yml', | ||
84 | 49 | ], | ||
85 | 50 | 'installable': True, | ||
86 | 51 | 'active': False, | ||
87 | 52 | } | ||
88 | 53 | # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: | ||
89 | 0 | 54 | ||
90 | === added file 'procurement_list/procurement_list.py' | |||
91 | --- procurement_list/procurement_list.py 1970-01-01 00:00:00 +0000 | |||
92 | +++ procurement_list/procurement_list.py 2011-03-16 16:41:25 +0000 | |||
93 | @@ -0,0 +1,217 @@ | |||
94 | 1 | #!/usr/bin/env python | ||
95 | 2 | # -*- encoding: utf-8 -*- | ||
96 | 3 | ############################################################################## | ||
97 | 4 | # | ||
98 | 5 | # OpenERP, Open Source Management Solution | ||
99 | 6 | # Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>). | ||
100 | 7 | # | ||
101 | 8 | # This program is free software: you can redistribute it and/or modify | ||
102 | 9 | # it under the terms of the GNU Affero General Public License as | ||
103 | 10 | # published by the Free Software Foundation, either version 3 of the | ||
104 | 11 | # License, or (at your option) any later version. | ||
105 | 12 | # | ||
106 | 13 | # This program is distributed in the hope that it will be useful, | ||
107 | 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
108 | 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
109 | 16 | # GNU Affero General Public License for more details. | ||
110 | 17 | # | ||
111 | 18 | # You should have received a copy of the GNU Affero General Public License | ||
112 | 19 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
113 | 20 | # | ||
114 | 21 | ############################################################################## | ||
115 | 22 | |||
116 | 23 | import time | ||
117 | 24 | import netsvc | ||
118 | 25 | |||
119 | 26 | from osv import osv | ||
120 | 27 | from osv import fields | ||
121 | 28 | from tools.translate import _ | ||
122 | 29 | |||
123 | 30 | class procurement_list(osv.osv): | ||
124 | 31 | _name = 'procurement.list' | ||
125 | 32 | _description = 'Procurement list' | ||
126 | 33 | |||
127 | 34 | _columns = { | ||
128 | 35 | 'name': fields.char(size=64, string='Ref.', required=True, readonly=True, | ||
129 | 36 | states={'draft': [('readonly', False)]}), | ||
130 | 37 | 'requestor': fields.char(size=20, string='Requestor',), | ||
131 | 38 | 'order_date': fields.date(string='Order date', required=True), | ||
132 | 39 | 'warehouse_id': fields.many2one('stock.warehouse', string='Warehouse'), | ||
133 | 40 | 'origin': fields.char(size=64, string='Origin'), | ||
134 | 41 | 'state': fields.selection([('draft', 'Draft'),('done', 'Done'), ('cancel', 'Cancel')], | ||
135 | 42 | string='State', readonly=True), | ||
136 | 43 | 'line_ids': fields.one2many('procurement.list.line', 'list_id', string='Lines', readonly=True, | ||
137 | 44 | states={'draft': [('readonly', False)]}), | ||
138 | 45 | 'notes': fields.text(string='Notes'), | ||
139 | 46 | 'supplier_ids': fields.many2many('res.partner', 'procurement_list_supplier_rel', | ||
140 | 47 | 'list_id', 'supplier_id', string='Suppliers', | ||
141 | 48 | domain="[('supplier', '=', True)]", | ||
142 | 49 | states={'done': [('readonly', True)]}), | ||
143 | 50 | 'order_ids': fields.many2many('purchase.order', 'procurement_list_order_rel', | ||
144 | 51 | 'list_id', 'order_id', string='Orders', readonly=True), | ||
145 | 52 | } | ||
146 | 53 | |||
147 | 54 | _defaults = { | ||
148 | 55 | 'name': lambda obj, cr, uid, context: obj.pool.get('ir.sequence').get(cr, uid, 'procurement.list'), | ||
149 | 56 | 'state': lambda *a: 'draft', | ||
150 | 57 | 'order_date': lambda *a: time.strftime('%Y-%m-%d'), | ||
151 | 58 | } | ||
152 | 59 | |||
153 | 60 | def copy(self, cr, uid, ids, default={}, context={}): | ||
154 | 61 | ''' | ||
155 | 62 | Increments the sequence for the new list | ||
156 | 63 | ''' | ||
157 | 64 | default['name'] = self.pool.get('ir.sequence').get(cr, uid, 'procurement.list') | ||
158 | 65 | |||
159 | 66 | res = super(procurement_list, self).copy(cr, uid, ids, default, context=context) | ||
160 | 67 | |||
161 | 68 | return res | ||
162 | 69 | |||
163 | 70 | def cancel(self, cr, uid, ids, context={}): | ||
164 | 71 | ''' | ||
165 | 72 | Sets the procurement list to the 'Cancel' state | ||
166 | 73 | ''' | ||
167 | 74 | self.write(cr, uid, ids, {'state': 'cancel'}) | ||
168 | 75 | |||
169 | 76 | return True | ||
170 | 77 | |||
171 | 78 | def create_rfq(self, cr, uid, ids, context={}): | ||
172 | 79 | ''' | ||
173 | 80 | Create a RfQ per supplier with all products | ||
174 | 81 | ''' | ||
175 | 82 | purchase_obj = self.pool.get('purchase.order') | ||
176 | 83 | line_obj = self.pool.get('purchase.order.line') | ||
177 | 84 | |||
178 | 85 | order_ids = [] | ||
179 | 86 | |||
180 | 87 | for list in self.browse(cr, uid, ids, context=context): | ||
181 | 88 | # Returns an error message if no suppliers or no products | ||
182 | 89 | if not list.supplier_ids or len(list.supplier_ids) == 0: | ||
183 | 90 | raise osv.except_osv(_('Error'), _('No supplier defined for this list !')) | ||
184 | 91 | if not list.line_ids or len(list.line_ids) == 0: | ||
185 | 92 | raise osv.except_osv(_('Error'), _('No line defined for this list !')) | ||
186 | 93 | |||
187 | 94 | location_id = self._get_location(cr, uid, list.warehouse_id) | ||
188 | 95 | # Creates a RfQ for each supplier... | ||
189 | 96 | for supplier in list.supplier_ids: | ||
190 | 97 | po_id = purchase_obj.create(cr, uid, {'partner_id': supplier.id, | ||
191 | 98 | 'partner_address_id': supplier.address_get().get('default'), | ||
192 | 99 | 'pricelist_id': supplier.property_product_pricelist.id, | ||
193 | 100 | 'origin': list.name, | ||
194 | 101 | 'location_id': location_id}) | ||
195 | 102 | order_ids.append(po_id) | ||
196 | 103 | |||
197 | 104 | # ... with all lines... | ||
198 | 105 | for line in list.line_ids: | ||
199 | 106 | # ... which aren't from stock | ||
200 | 107 | if not line.from_stock: | ||
201 | 108 | line_obj.create(cr, uid, {'product_uom': line.product_uom_id.id, | ||
202 | 109 | 'product_id': line.product_id.id, | ||
203 | 110 | 'order_id': po_id, | ||
204 | 111 | 'price_unit': 0.00, | ||
205 | 112 | 'date_planned': list.order_date, | ||
206 | 113 | 'product_qty': line.product_qty, | ||
207 | 114 | 'procurement_line_id': line.id, | ||
208 | 115 | 'name': line.product_id.name,}) | ||
209 | 116 | self.pool.get('procurement.list.line').write(cr, uid, line.id, {'latest': 'RfQ In Progress'}) | ||
210 | 117 | |||
211 | 118 | self.write(cr, uid, ids, {'state': 'done', 'order_ids': [(6, 0, order_ids)]}) | ||
212 | 119 | |||
213 | 120 | return {'type': 'ir.actions.act_window', | ||
214 | 121 | 'res_model': 'purchase.order', | ||
215 | 122 | 'view_type': 'form', | ||
216 | 123 | 'view_mode': 'tree,form', | ||
217 | 124 | 'domain': [('id', 'in', order_ids)]} | ||
218 | 125 | |||
219 | 126 | def reset(self, cr, uid, ids, context={}): | ||
220 | 127 | ''' | ||
221 | 128 | Sets the procurement list to the 'Draft' state | ||
222 | 129 | ''' | ||
223 | 130 | self.write(cr, uid, ids, {'state': 'draft'}) | ||
224 | 131 | |||
225 | 132 | return True | ||
226 | 133 | |||
227 | 134 | def _get_location(self, cr, uid, warehouse=None): | ||
228 | 135 | ''' | ||
229 | 136 | Returns the default input location for product | ||
230 | 137 | ''' | ||
231 | 138 | if warehouse: | ||
232 | 139 | return warehouse.lot_input_id.id | ||
233 | 140 | warehouse_obj = self.pool.get('stock.warehouse') | ||
234 | 141 | warehouse_id = warehouse_obj.search(cr, uid, [])[0] | ||
235 | 142 | return warehouse_obj.browse(cr, uid, warehouse_id).lot_input_id.id | ||
236 | 143 | |||
237 | 144 | procurement_list() | ||
238 | 145 | |||
239 | 146 | |||
240 | 147 | class procurement_list_line(osv.osv): | ||
241 | 148 | _name = 'procurement.list.line' | ||
242 | 149 | _description = 'Procurement line' | ||
243 | 150 | _rec_name = 'product_id' | ||
244 | 151 | |||
245 | 152 | _columns = { | ||
246 | 153 | 'product_id': fields.many2one('product.product', string='Product', required=True), | ||
247 | 154 | 'product_uom_id': fields.many2one('product.uom', string='UoM', required=True), | ||
248 | 155 | 'product_qty': fields.float(digits=(16,4), string='Quantity', required=True), | ||
249 | 156 | 'comment': fields.char(size=128, string='Comment'), | ||
250 | 157 | 'from_stock': fields.boolean(string='From stock ?'), | ||
251 | 158 | 'latest': fields.char(size=64, string='Latest document', readonly=True), | ||
252 | 159 | 'list_id': fields.many2one('procurement.list', string='List', required=True, ondelete='cascade'), | ||
253 | 160 | } | ||
254 | 161 | |||
255 | 162 | _defaults = { | ||
256 | 163 | 'latest': lambda *a: '', | ||
257 | 164 | } | ||
258 | 165 | |||
259 | 166 | def copy_data(self, cr, uid, id, default={}, context={}): | ||
260 | 167 | ''' | ||
261 | 168 | Initializes the 'latest' fields to an empty field | ||
262 | 169 | ''' | ||
263 | 170 | default['latest'] = '' | ||
264 | 171 | |||
265 | 172 | res = super(procurement_list_line, self).copy_data(cr, uid, id, default, context=context) | ||
266 | 173 | |||
267 | 174 | return res | ||
268 | 175 | |||
269 | 176 | def product_id_change(self, cr, uid, ids, product_id, context={}): | ||
270 | 177 | ''' | ||
271 | 178 | Fills automatically the product_uom_id field on the line when the | ||
272 | 179 | product was changed. | ||
273 | 180 | ''' | ||
274 | 181 | product_obj = self.pool.get('product.product') | ||
275 | 182 | |||
276 | 183 | v = {} | ||
277 | 184 | if not product_id: | ||
278 | 185 | v.update({'product_uom_id': False}) | ||
279 | 186 | else: | ||
280 | 187 | product = product_obj.browse(cr, uid, product_id, context=context) | ||
281 | 188 | v.update({'product_uom_id': product.uom_id.id}) | ||
282 | 189 | |||
283 | 190 | return {'value': v} | ||
284 | 191 | |||
285 | 192 | procurement_list_line() | ||
286 | 193 | |||
287 | 194 | |||
288 | 195 | class purchase_order_line(osv.osv): | ||
289 | 196 | _name = 'purchase.order.line' | ||
290 | 197 | _inherit = 'purchase.order.line' | ||
291 | 198 | |||
292 | 199 | _columns = { | ||
293 | 200 | 'procurement_line_id': fields.many2one('procurement.list.line', string='Procurement Line', readonly=True, ondelete='set null'), | ||
294 | 201 | } | ||
295 | 202 | |||
296 | 203 | def action_confirm(self, cr, uid, ids, context={}): | ||
297 | 204 | ''' | ||
298 | 205 | Changes the status of the procurement line | ||
299 | 206 | ''' | ||
300 | 207 | proc_line_obj = self.pool.get('procurement.list.line') | ||
301 | 208 | for line in self.browse(cr, uid, ids): | ||
302 | 209 | if line.procurement_line_id and line.procurement_line_id.id: | ||
303 | 210 | proc_line_obj.write(cr, uid, [line.procurement_line_id.id], {'latest': line.order_id.name}) | ||
304 | 211 | |||
305 | 212 | return super(purchase_order_line, self).action_confirm(cr, uid, ids, context=context) | ||
306 | 213 | |||
307 | 214 | purchase_order_line() | ||
308 | 215 | |||
309 | 216 | # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: | ||
310 | 217 | |||
311 | 0 | 218 | ||
312 | === added file 'procurement_list/procurement_list_sequence.xml' | |||
313 | --- procurement_list/procurement_list_sequence.xml 1970-01-01 00:00:00 +0000 | |||
314 | +++ procurement_list/procurement_list_sequence.xml 2011-03-16 16:41:25 +0000 | |||
315 | @@ -0,0 +1,20 @@ | |||
316 | 1 | <?xml version="1.0" encoding="utf-8" ?> | ||
317 | 2 | <openerp> | ||
318 | 3 | <data> | ||
319 | 4 | |||
320 | 5 | <!-- Sequences for procurement.list --> | ||
321 | 6 | <record id="seq_type_procurement_list" model="ir.sequence.type"> | ||
322 | 7 | <field name="name">Procurement List Order</field> | ||
323 | 8 | <field name="code">procurement.list</field> | ||
324 | 9 | </record> | ||
325 | 10 | |||
326 | 11 | <record id="seq_procurement_list" model="ir.sequence"> | ||
327 | 12 | <field name="name">Procurement List</field> | ||
328 | 13 | <field name="code">procurement.list</field> | ||
329 | 14 | <field name="prefix">PR/</field> | ||
330 | 15 | <field name="padding">5</field> | ||
331 | 16 | </record> | ||
332 | 17 | |||
333 | 18 | </data> | ||
334 | 19 | </openerp> | ||
335 | 20 | |||
336 | 0 | 21 | ||
337 | === added file 'procurement_list/procurement_list_view.xml' | |||
338 | --- procurement_list/procurement_list_view.xml 1970-01-01 00:00:00 +0000 | |||
339 | +++ procurement_list/procurement_list_view.xml 2011-03-16 16:41:25 +0000 | |||
340 | @@ -0,0 +1,111 @@ | |||
341 | 1 | <?xml version="1.0" encoding="utf-8" ?> | ||
342 | 2 | <openerp> | ||
343 | 3 | <data> | ||
344 | 4 | |||
345 | 5 | <record id="procurement_list_form_view" model="ir.ui.view"> | ||
346 | 6 | <field name="name">procurement.list.form.view</field> | ||
347 | 7 | <field name="model">procurement.list</field> | ||
348 | 8 | <field name="type">form</field> | ||
349 | 9 | <field name="arch" type="xml"> | ||
350 | 10 | <form string="Procurement list"> | ||
351 | 11 | <group colspan="4" col="6"> | ||
352 | 12 | <field name="name" /> | ||
353 | 13 | <field name="order_date" /> | ||
354 | 14 | <field name="warehouse_id" widget="selection" /> | ||
355 | 15 | <field name="requestor" /> | ||
356 | 16 | <field name="origin" /> | ||
357 | 17 | </group> | ||
358 | 18 | <notebook colspan="4"> | ||
359 | 19 | <page string="Products"> | ||
360 | 20 | <field name="line_ids" mode="tree" colspan="4" nolabel="1"> | ||
361 | 21 | <tree editable="top" string="Products"> | ||
362 | 22 | <field name="product_id" on_change="product_id_change(product_id)" /> | ||
363 | 23 | <field name="product_uom_id" /> | ||
364 | 24 | <field name="product_qty" /> | ||
365 | 25 | <field name="comment" /> | ||
366 | 26 | <field name="from_stock" /> | ||
367 | 27 | <field name="latest" /> | ||
368 | 28 | </tree> | ||
369 | 29 | </field> | ||
370 | 30 | <group colspan="4" col="6"> | ||
371 | 31 | <field name="state" /> | ||
372 | 32 | <button name="cancel" string="Cancel" icon="gtk-cancel" type="object" states="draft"/> | ||
373 | 33 | <button name="create_rfq" string="Create RfQ" icon="gtk-execute" type="object" states="draft" /> | ||
374 | 34 | <button name="reset" string="Reset to Draft" icon="gtk-ok" type="object" states="cancel" /> | ||
375 | 35 | </group> | ||
376 | 36 | </page> | ||
377 | 37 | <page string="Suppliers"> | ||
378 | 38 | <field name="supplier_ids" nolabel="1" /> | ||
379 | 39 | </page> | ||
380 | 40 | <page string="Sourcing Documents"> | ||
381 | 41 | <field name="order_ids" nolabel="1" colspan="4"> | ||
382 | 42 | <tree string="Sourcing Documents" colors="blue:state=='draft'"> | ||
383 | 43 | <field name="name" /> | ||
384 | 44 | <field name="partner_id" /> | ||
385 | 45 | <field name="state" /> | ||
386 | 46 | </tree> | ||
387 | 47 | </field> | ||
388 | 48 | </page> | ||
389 | 49 | <page string="Notes"> | ||
390 | 50 | <field name="notes" nolabel="1" /> | ||
391 | 51 | </page> | ||
392 | 52 | </notebook> | ||
393 | 53 | </form> | ||
394 | 54 | </field> | ||
395 | 55 | </record> | ||
396 | 56 | |||
397 | 57 | <record id="procurement_list_tree_view" model="ir.ui.view"> | ||
398 | 58 | <field name="name">procurement.list.tree.view</field> | ||
399 | 59 | <field name="model">procurement.list</field> | ||
400 | 60 | <field name="type">tree</field> | ||
401 | 61 | <field name="arch" type="xml"> | ||
402 | 62 | <tree string="Procurement lists"> | ||
403 | 63 | <field name="name" /> | ||
404 | 64 | <field name="order_date" /> | ||
405 | 65 | <field name="requestor" /> | ||
406 | 66 | </tree> | ||
407 | 67 | </field> | ||
408 | 68 | </record> | ||
409 | 69 | |||
410 | 70 | <record id="procurement_list_filter_view" model="ir.ui.view"> | ||
411 | 71 | <field name="name">procurement.list.filter.view</field> | ||
412 | 72 | <field name="model">procurement.list</field> | ||
413 | 73 | <field name="type">search</field> | ||
414 | 74 | <field name="arch" type="xml"> | ||
415 | 75 | <search string="Search Procurement List"> | ||
416 | 76 | <group col="10" colspan="4"> | ||
417 | 77 | <filter icon="terp-document-new" string="Draft" domain="[('state', '=', 'draft')]" help="Draft Procurement list" /> | ||
418 | 78 | <filter icon="terp-dialog-close" string="Done" domain="[('state', '=', 'done')]" help="Done Procurement list" /> | ||
419 | 79 | <separator orientation="vertical" /> | ||
420 | 80 | <field name="name" /> | ||
421 | 81 | <field name="order_date" /> | ||
422 | 82 | <field name="requestor" /> | ||
423 | 83 | </group> | ||
424 | 84 | <newline /> | ||
425 | 85 | <group expand="0" string="Group By..." colspan="4" col="10" groups="base.group_extended"> | ||
426 | 86 | <filter string="Responsible" icon="terp-personal" domain="[]" context="{'group_by': 'user_id'}" /> | ||
427 | 87 | <separator orientation="vertical" /> | ||
428 | 88 | </group> | ||
429 | 89 | </search> | ||
430 | 90 | </field> | ||
431 | 91 | </record> | ||
432 | 92 | |||
433 | 93 | <record id="action_procurement_list_tree" model="ir.actions.act_window"> | ||
434 | 94 | <field name="name">Procurement Lists</field> | ||
435 | 95 | <field name="res_model">procurement.list</field> | ||
436 | 96 | <field name="view_type">form</field> | ||
437 | 97 | <field name="view_mode">tree,form</field> | ||
438 | 98 | <field name="search_id" ref="procurement_list_filter_view" /> | ||
439 | 99 | <field name="help">A procurement list is a list of items to supply. After creation of the list of items, you can choose | ||
440 | 100 | a list of suppliers and create automatically a Request for Quotation for each supplier.</field> | ||
441 | 101 | </record> | ||
442 | 102 | |||
443 | 103 | <menuitem | ||
444 | 104 | action="action_procurement_list_tree" | ||
445 | 105 | id="menu_procurement_list" | ||
446 | 106 | sequence="0" | ||
447 | 107 | parent="purchase.menu_procurement_management" /> | ||
448 | 108 | |||
449 | 109 | </data> | ||
450 | 110 | </openerp> | ||
451 | 111 | |||
452 | 0 | 112 | ||
453 | === added file 'procurement_list/procurement_list_wizard.xml' | |||
454 | --- procurement_list/procurement_list_wizard.xml 1970-01-01 00:00:00 +0000 | |||
455 | +++ procurement_list/procurement_list_wizard.xml 2011-03-16 16:41:25 +0000 | |||
456 | @@ -0,0 +1,21 @@ | |||
457 | 1 | <?xml version="1.0" encoding="utf-8" ?> | ||
458 | 2 | <openerp> | ||
459 | 3 | <data> | ||
460 | 4 | |||
461 | 5 | <wizard | ||
462 | 6 | id="wizard_list_to_order" | ||
463 | 7 | model="procurement.list" | ||
464 | 8 | name="wizard_list_to_order" | ||
465 | 9 | keyword="client_action_relate" | ||
466 | 10 | string="Purchase Orders" /> | ||
467 | 11 | |||
468 | 12 | <wizard | ||
469 | 13 | id="wizard_list_to_rfq" | ||
470 | 14 | model="procurement.list" | ||
471 | 15 | name="wizard_list_to_rfq" | ||
472 | 16 | keyword="client_action_relate" | ||
473 | 17 | string="Requests for Quotation" /> | ||
474 | 18 | |||
475 | 19 | </data> | ||
476 | 20 | </openerp> | ||
477 | 21 | |||
478 | 0 | 22 | ||
479 | === added directory 'procurement_list/security' | |||
480 | === added file 'procurement_list/security/ir.model.access.csv' | |||
481 | --- procurement_list/security/ir.model.access.csv 1970-01-01 00:00:00 +0000 | |||
482 | +++ procurement_list/security/ir.model.access.csv 2011-03-16 16:41:25 +0000 | |||
483 | @@ -0,0 +1,3 @@ | |||
484 | 1 | "id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink" | ||
485 | 2 | "access_procurement_list_all","procurement.list all","model_procurement_list",,1,1,1,1 | ||
486 | 3 | "access_procurement_list_line_all","procurement.list.line all","model_procurement_list_line",,1,1,1,1 | ||
487 | 0 | 4 | ||
488 | === added directory 'procurement_list/test' | |||
489 | === added file 'procurement_list/test/list_import.csv' | |||
490 | --- procurement_list/test/list_import.csv 1970-01-01 00:00:00 +0000 | |||
491 | +++ procurement_list/test/list_import.csv 2011-03-16 16:41:25 +0000 | |||
492 | @@ -0,0 +1,5 @@ | |||
493 | 1 | 'CPU1';'Processor AMD Athlon XP 1800+';'PCE';12,00;'test import'; | ||
494 | 2 | 'CPU2';'High speed processor config';'PCE';15,00;;'True' | ||
495 | 3 | 'CPU3';'Processor AMD Athlon XP 2200+';'PCE';25,00;; | ||
496 | 4 | 'CPU_DEM';'Processor on demand';'PCE';30,00;; | ||
497 | 5 | 'CPU_GEN';'Regular processor config';'PCE';32,00;; | ||
498 | 0 | 6 | ||
499 | === added file 'procurement_list/test/procurement_list.yml' | |||
500 | --- procurement_list/test/procurement_list.yml 1970-01-01 00:00:00 +0000 | |||
501 | +++ procurement_list/test/procurement_list.yml 2011-03-16 16:41:25 +0000 | |||
502 | @@ -0,0 +1,143 @@ | |||
503 | 1 | - | ||
504 | 2 | In order to test the procurement list module, I start by creating a new product category | ||
505 | 3 | - | ||
506 | 4 | !record {model: product.category, id: product_cat1}: | ||
507 | 5 | name: Categ1 | ||
508 | 6 | - | ||
509 | 7 | I create new product 'P1' | ||
510 | 8 | - | ||
511 | 9 | !record {model: product.product, id: product1}: | ||
512 | 10 | categ_id: product_cat1 | ||
513 | 11 | cost_method: standard | ||
514 | 12 | mes_type: fixed | ||
515 | 13 | name: P1 | ||
516 | 14 | price_margin: 2.0 | ||
517 | 15 | procure_method: make_to_stock | ||
518 | 16 | property_stock_inventory: stock.location_inventory | ||
519 | 17 | property_stock_procurement: stock.location_procurement | ||
520 | 18 | property_stock_production: stock.location_production | ||
521 | 19 | seller_delay: '1' | ||
522 | 20 | standard_price: 100.0 | ||
523 | 21 | supply_method: buy | ||
524 | 22 | type: product | ||
525 | 23 | uom_id: product.product_uom_unit | ||
526 | 24 | uom_po_id: product.product_uom_unit | ||
527 | 25 | volume: 0.0 | ||
528 | 26 | warranty: 0.0 | ||
529 | 27 | weight: 0.0 | ||
530 | 28 | weight_net: 0.0 | ||
531 | 29 | - | ||
532 | 30 | I create a second product, P2 | ||
533 | 31 | - | ||
534 | 32 | !record {model: product.product, id: product2}: | ||
535 | 33 | categ_id: product_cat1 | ||
536 | 34 | cost_method: standard | ||
537 | 35 | mes_type: fixed | ||
538 | 36 | name: P2 | ||
539 | 37 | price_margin: 2.0 | ||
540 | 38 | procure_method: make_to_stock | ||
541 | 39 | property_stock_inventory: stock.location_inventory | ||
542 | 40 | property_stock_procurement: stock.location_procurement | ||
543 | 41 | property_stock_production: stock.location_production | ||
544 | 42 | seller_delay: '1' | ||
545 | 43 | standard_price: 100.0 | ||
546 | 44 | supply_method: buy | ||
547 | 45 | type: product | ||
548 | 46 | uom_id: product.product_uom_unit | ||
549 | 47 | uom_po_id: product.product_uom_unit | ||
550 | 48 | volume: 0.0 | ||
551 | 49 | warranty: 0.0 | ||
552 | 50 | weight: 0.0 | ||
553 | 51 | weight_net: 0.0 | ||
554 | 52 | - | ||
555 | 53 | I create a partner | ||
556 | 54 | - | ||
557 | 55 | !record {model: res.partner, id: partner1}: | ||
558 | 56 | name: Supplier 1 | ||
559 | 57 | - | ||
560 | 58 | I create an address for this partner | ||
561 | 59 | - | ||
562 | 60 | !record {model: res.partner.address, id: addr1}: | ||
563 | 61 | partner_id: partner1 | ||
564 | 62 | name: Supplier1 | ||
565 | 63 | - | ||
566 | 64 | I create a second partner | ||
567 | 65 | - | ||
568 | 66 | !record {model: res.partner, id: partner2}: | ||
569 | 67 | name: Supplier 2 | ||
570 | 68 | - | ||
571 | 69 | I create an address for this second partner | ||
572 | 70 | - | ||
573 | 71 | !record {model: res.partner.address, id: addr2}: | ||
574 | 72 | partner_id: partner2 | ||
575 | 73 | name: Supplier2 | ||
576 | 74 | - | ||
577 | 75 | I create a procurement list for these two products | ||
578 | 76 | - | ||
579 | 77 | !record {model: procurement.list, id: list1}: | ||
580 | 78 | requestor: Administration | ||
581 | 79 | warehouse_id: stock.warehouse0 | ||
582 | 80 | origin: R 20043 | ||
583 | 81 | supplier_ids: | ||
584 | 82 | - partner1 | ||
585 | 83 | - partner2 | ||
586 | 84 | - | ||
587 | 85 | I add two lines in this procurement list | ||
588 | 86 | - | ||
589 | 87 | !record {model: procurement.list.line, id: list1_line1}: | ||
590 | 88 | product_id: product1 | ||
591 | 89 | product_uom_id: product.product_uom_unit | ||
592 | 90 | product_qty: 100.00 | ||
593 | 91 | comment: special comment | ||
594 | 92 | from_stock: False | ||
595 | 93 | list_id: list1 | ||
596 | 94 | - | ||
597 | 95 | The second line | ||
598 | 96 | - | ||
599 | 97 | !record {model: procurement.list.line, id: list1_line2}: | ||
600 | 98 | product_id: product2 | ||
601 | 99 | product_uom_id: product.product_uom_unit | ||
602 | 100 | product_qty: 50.0 | ||
603 | 101 | from_stock: True | ||
604 | 102 | list_id: list1 | ||
605 | 103 | - | ||
606 | 104 | I check that the list which was initially in the draft state | ||
607 | 105 | - | ||
608 | 106 | !assert {model: procurement.list, id: list1}: | ||
609 | 107 | - state == 'draft' | ||
610 | 108 | - requestor == 'Administration' | ||
611 | 109 | - origin == 'R 20043' | ||
612 | 110 | - | ||
613 | 111 | I create RfQ from this list | ||
614 | 112 | - | ||
615 | 113 | !python {model: procurement.list}: | | ||
616 | 114 | pl_obj = self.pool.get('procurement.list') | ||
617 | 115 | pl_id1 = pl_obj.browse(cr, uid, ref('list1')) | ||
618 | 116 | pl_id1.create_rfq() | ||
619 | 117 | - | ||
620 | 118 | I check if the latest message in procurement line is 'RfQ In Progress' | ||
621 | 119 | - | ||
622 | 120 | !assert {model: procurement.list.line, id: list1_line1}: | ||
623 | 121 | - latest == 'RfQ In Progress' | ||
624 | 122 | - | ||
625 | 123 | I check if only one RfQ will be created for the | ||
626 | 124 | - | ||
627 | 125 | !python {model: procurement.list}: | | ||
628 | 126 | pl_obj = self.pool.get('procurement.list') | ||
629 | 127 | pol_obj = self.pool.get('purchase.order.line') | ||
630 | 128 | order_obj = self.pool.get('purchase.order') | ||
631 | 129 | pol_ids = pol_obj.search(cr, uid, [('product_id', '=', ref('product1'))]) | ||
632 | 130 | pl = pl_obj.browse(cr, uid, ref('list1')) | ||
633 | 131 | |||
634 | 132 | for pol in pol_obj.browse(cr, uid, pol_ids): | ||
635 | 133 | assert pol.order_id.origin == pl.name, "Bad name for the name of the generated Purchase Order" | ||
636 | 134 | order_obj.wkf_confirm_order(cr, uid, [pol.order_id.id]) | ||
637 | 135 | assert pol.procurement_line_id.latest == pol.order_id.name, "Procurement line not updated" | ||
638 | 136 | - | ||
639 | 137 | I check that no purchase order line with P2 | ||
640 | 138 | - | ||
641 | 139 | !python {model: procurement.list}: | | ||
642 | 140 | pl_obj = self.pool.get('procurement.list') | ||
643 | 141 | pol_obj = self.pool.get('purchase.order.line') | ||
644 | 142 | pol_ids = pol_obj.search(cr, uid, [('product_id', '=', ref('product2'))]) | ||
645 | 143 | assert len(pol_ids) == 0, "No purchase order line found !" | ||
646 | 0 | 144 | ||
647 | === added directory 'procurement_list/wizard' | |||
648 | === added file 'procurement_list/wizard/__init__.py' | |||
649 | --- procurement_list/wizard/__init__.py 1970-01-01 00:00:00 +0000 | |||
650 | +++ procurement_list/wizard/__init__.py 2011-03-16 16:41:25 +0000 | |||
651 | @@ -0,0 +1,28 @@ | |||
652 | 1 | #!/usr/bin/env python | ||
653 | 2 | # -*- encoding: utf-8 -*- | ||
654 | 3 | ############################################################################## | ||
655 | 4 | # | ||
656 | 5 | # OpenERP, Open Source Management Solution | ||
657 | 6 | # Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>). | ||
658 | 7 | # | ||
659 | 8 | # This program is free software: you can redistribute it and/or modify | ||
660 | 9 | # it under the terms of the GNU Affero General Public License as | ||
661 | 10 | # published by the Free Software Foundation, either version 3 of the | ||
662 | 11 | # License, or (at your option) any later version. | ||
663 | 12 | # | ||
664 | 13 | # This program is distributed in the hope that it will be useful, | ||
665 | 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
666 | 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
667 | 16 | # GNU Affero General Public License for more details. | ||
668 | 17 | # | ||
669 | 18 | # You should have received a copy of the GNU Affero General Public License | ||
670 | 19 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
671 | 20 | # | ||
672 | 21 | ############################################################################## | ||
673 | 22 | |||
674 | 23 | import wizard_list_to_order | ||
675 | 24 | import wizard_list_to_rfq | ||
676 | 25 | import wizard_import_list | ||
677 | 26 | |||
678 | 27 | # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: | ||
679 | 28 | |||
680 | 0 | 29 | ||
681 | === added file 'procurement_list/wizard/wizard_import_list.py' | |||
682 | --- procurement_list/wizard/wizard_import_list.py 1970-01-01 00:00:00 +0000 | |||
683 | +++ procurement_list/wizard/wizard_import_list.py 2011-03-16 16:41:25 +0000 | |||
684 | @@ -0,0 +1,196 @@ | |||
685 | 1 | #!/usr/bin/env python | ||
686 | 2 | # -*- encoding: utf-8 -*- | ||
687 | 3 | ############################################################################## | ||
688 | 4 | # | ||
689 | 5 | # OpenERP, Open Source Management Solution | ||
690 | 6 | # Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>). | ||
691 | 7 | # | ||
692 | 8 | # This program is free software: you can redistribute it and/or modify | ||
693 | 9 | # it under the terms of the GNU Affero General Public License as | ||
694 | 10 | # published by the Free Software Foundation, either version 3 of the | ||
695 | 11 | # License, or (at your option) any later version. | ||
696 | 12 | # | ||
697 | 13 | # This program is distributed in the hope that it will be useful, | ||
698 | 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
699 | 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
700 | 16 | # GNU Affero General Public License for more details. | ||
701 | 17 | # | ||
702 | 18 | # You should have received a copy of the GNU Affero General Public License | ||
703 | 19 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
704 | 20 | # | ||
705 | 21 | ############################################################################## | ||
706 | 22 | |||
707 | 23 | from osv import osv | ||
708 | 24 | from osv import fields | ||
709 | 25 | |||
710 | 26 | from tools.translate import _ | ||
711 | 27 | |||
712 | 28 | from tempfile import TemporaryFile | ||
713 | 29 | |||
714 | 30 | import base64 | ||
715 | 31 | import csv | ||
716 | 32 | |||
717 | 33 | |||
718 | 34 | |||
719 | 35 | class wizard_import_list(osv.osv_memory): | ||
720 | 36 | _name = 'procurement.list.import' | ||
721 | 37 | _description = 'Import of Procurement List' | ||
722 | 38 | |||
723 | 39 | _columns = { | ||
724 | 40 | 'file': fields.binary(strign='File to import', required=True), | ||
725 | 41 | 'message': fields.text(string='Message', readonly=True), | ||
726 | 42 | 'info': fields.text(string='Info', readonly=True), | ||
727 | 43 | } | ||
728 | 44 | |||
729 | 45 | _defaults = { | ||
730 | 46 | 'info': lambda *a : """ | ||
731 | 47 | The file should be in CSV format (with ';' character as delimiter). | ||
732 | 48 | The columns should be in this order : | ||
733 | 49 | * Product code | ||
734 | 50 | * Product name | ||
735 | 51 | * UoM | ||
736 | 52 | * Quantity | ||
737 | 53 | * Comment | ||
738 | 54 | * From stock ? (Write True if you want that the product will be supply from stock, leave blank if not) | ||
739 | 55 | """ | ||
740 | 56 | } | ||
741 | 57 | |||
742 | 58 | def close_window(self, cr, uid, ids, context={}): | ||
743 | 59 | ''' | ||
744 | 60 | Simply close the wizard | ||
745 | 61 | ''' | ||
746 | 62 | return {'type': 'ir.actions.act_window', | ||
747 | 63 | 'res_model': 'procurement.list', | ||
748 | 64 | 'view_type': 'form', | ||
749 | 65 | 'view_mode': 'form,tree', | ||
750 | 66 | 'res_id': context.get('list_id'), | ||
751 | 67 | 'target': 'crush'} | ||
752 | 68 | |||
753 | 69 | def default_get(self, cr, uid, fields, context={}): | ||
754 | 70 | ''' | ||
755 | 71 | Check if the Procurement List is saved and | ||
756 | 72 | set the error message | ||
757 | 73 | ''' | ||
758 | 74 | res = super(wizard_import_list, self).default_get(cr, uid, fields, context=context) | ||
759 | 75 | |||
760 | 76 | # If we are after the importation | ||
761 | 77 | if context.get('step', False) and context.get('step', False) == 'import': | ||
762 | 78 | res['message'] = context.get('message', '') | ||
763 | 79 | |||
764 | 80 | return res | ||
765 | 81 | else: | ||
766 | 82 | if not context.get('active_id', False): | ||
767 | 83 | raise osv.except_osv(_('Warning'), _('Please save the Procurement List before importing lines')) | ||
768 | 84 | |||
769 | 85 | # We check if the Procurement List is in 'Draft' state | ||
770 | 86 | list_id = self.pool.get('procurement.list').browse(cr, uid, context.get('active_id', [])) | ||
771 | 87 | if not list_id or list_id.state != 'draft': | ||
772 | 88 | raise osv.except_osv(_('Warning'), _('You cannot import lines in a confirmed Procurement List')) | ||
773 | 89 | |||
774 | 90 | return res | ||
775 | 91 | |||
776 | 92 | |||
777 | 93 | def import_file(self, cr, uid, ids, context={}): | ||
778 | 94 | ''' | ||
779 | 95 | Import the file passed on the wizard in the | ||
780 | 96 | Procurement List | ||
781 | 97 | ''' | ||
782 | 98 | list_line_obj = self.pool.get('procurement.list.line') | ||
783 | 99 | list_obj = self.pool.get('procurement.list') | ||
784 | 100 | product_obj = self.pool.get('product.product') | ||
785 | 101 | uom_obj = self.pool.get('product.uom') | ||
786 | 102 | model_data_obj = self.pool.get('ir.model.data') | ||
787 | 103 | |||
788 | 104 | list_id = context.get('active_id', False) | ||
789 | 105 | |||
790 | 106 | if not list_id: | ||
791 | 107 | raise osv.except_osv(_('Error'), _('The system hasn\'t found a Procurement List to import lines')) | ||
792 | 108 | |||
793 | 109 | import_list = self.browse(cr, uid, ids[0], context) | ||
794 | 110 | |||
795 | 111 | fileobj = TemporaryFile('w+') | ||
796 | 112 | fileobj.write(base64.decodestring(import_list.file)) | ||
797 | 113 | |||
798 | 114 | # now we determine the file format | ||
799 | 115 | fileobj.seek(0) | ||
800 | 116 | |||
801 | 117 | reader = csv.reader(fileobj, quotechar='\'', delimiter=';') | ||
802 | 118 | |||
803 | 119 | error = '' | ||
804 | 120 | |||
805 | 121 | line_num = 0 | ||
806 | 122 | |||
807 | 123 | for line in reader: | ||
808 | 124 | line_num += 1 | ||
809 | 125 | if len(line) < 6: | ||
810 | 126 | error += 'Line %s is not valid !' % (line_num) | ||
811 | 127 | error += '\n' | ||
812 | 128 | continue | ||
813 | 129 | # Get the product | ||
814 | 130 | product_ids = product_obj.search(cr, uid, [('default_code', '=', line[0])], context=context) | ||
815 | 131 | if not product_ids: | ||
816 | 132 | product_ids = product_obj.search(cr, uid, [('name', '=', line[1])], context=context) | ||
817 | 133 | |||
818 | 134 | if not product_ids: | ||
819 | 135 | error += 'Product [%s] %s not found !' % (line[0], line[1]) | ||
820 | 136 | error += '\n' | ||
821 | 137 | continue | ||
822 | 138 | |||
823 | 139 | product_id = product_ids[0] | ||
824 | 140 | |||
825 | 141 | # Get the UoM | ||
826 | 142 | uom_ids = uom_obj.search(cr, uid, [('name', '=', line[2])]) | ||
827 | 143 | if not uom_ids: | ||
828 | 144 | error += 'Uom %s not found !' % line[2] | ||
829 | 145 | error += '\n' | ||
830 | 146 | continue | ||
831 | 147 | |||
832 | 148 | uom_id = uom_ids[0] | ||
833 | 149 | |||
834 | 150 | # Get the quantity | ||
835 | 151 | product_qty = float(line[3].replace(',', '.')) | ||
836 | 152 | |||
837 | 153 | # Get the comment | ||
838 | 154 | comment = line[4] | ||
839 | 155 | |||
840 | 156 | # Get the method | ||
841 | 157 | from_stock = False | ||
842 | 158 | if line[5] == 'True': | ||
843 | 159 | from_stock = True | ||
844 | 160 | |||
845 | 161 | |||
846 | 162 | list_line_obj.create(cr, uid, {'product_id': product_id, | ||
847 | 163 | 'product_uom_id': uom_id, | ||
848 | 164 | 'product_qty': product_qty, | ||
849 | 165 | 'comment': comment, | ||
850 | 166 | 'from_stock': from_stock, | ||
851 | 167 | 'list_id': list_id}) | ||
852 | 168 | |||
853 | 169 | view_ids = model_data_obj.search(cr, uid, | ||
854 | 170 | [('module', '=', 'procurement_list'), | ||
855 | 171 | ('name', '=', 'wizard_import_list_done')], | ||
856 | 172 | offset=0, limit=1)[0] | ||
857 | 173 | view_id = model_data_obj.browse(cr, uid, view_ids).res_id | ||
858 | 174 | |||
859 | 175 | if error and error != '': | ||
860 | 176 | context['message'] = error | ||
861 | 177 | else: | ||
862 | 178 | context['message'] = 'All lines have been succesfully imported !' | ||
863 | 179 | |||
864 | 180 | context['step'] = 'import' | ||
865 | 181 | context['list_id'] = list_id | ||
866 | 182 | |||
867 | 183 | return {'type': 'ir.actions.act_window', | ||
868 | 184 | 'res_model': 'procurement.list.import', | ||
869 | 185 | 'view_type': 'form', | ||
870 | 186 | 'view_mode': 'form', | ||
871 | 187 | 'target': 'new', | ||
872 | 188 | 'view_id': [view_id], | ||
873 | 189 | 'context': context, | ||
874 | 190 | } | ||
875 | 191 | |||
876 | 192 | wizard_import_list() | ||
877 | 193 | |||
878 | 194 | |||
879 | 195 | # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: | ||
880 | 196 | |||
881 | 0 | 197 | ||
882 | === added file 'procurement_list/wizard/wizard_import_list_view.xml' | |||
883 | --- procurement_list/wizard/wizard_import_list_view.xml 1970-01-01 00:00:00 +0000 | |||
884 | +++ procurement_list/wizard/wizard_import_list_view.xml 2011-03-16 16:41:25 +0000 | |||
885 | @@ -0,0 +1,48 @@ | |||
886 | 1 | <?xml version="1.0" encoding="utf-8" ?> | ||
887 | 2 | <openerp> | ||
888 | 3 | <data> | ||
889 | 4 | |||
890 | 5 | |||
891 | 6 | <record id="wizard_import_list_init" model="ir.ui.view"> | ||
892 | 7 | <field name="name">wizard.import.list.init</field> | ||
893 | 8 | <field name="model">procurement.list.import</field> | ||
894 | 9 | <field name="type">form</field> | ||
895 | 10 | <field name="arch" type="xml"> | ||
896 | 11 | <form string="Import lines"> | ||
897 | 12 | <separator string="Information" colspan="4" /> | ||
898 | 13 | <field name="info" colspan="4" nolabel="1" /> | ||
899 | 14 | <separator string="File to import" colspan="4" /> | ||
900 | 15 | <field name="file" nolabel="1" colspan="4" /> | ||
901 | 16 | <button special="cancel" string="Cancel" icon="gtk-cancel" /> | ||
902 | 17 | <button name="import_file" string="Import file" type="object" icon="gtk-convert" /> | ||
903 | 18 | </form> | ||
904 | 19 | </field> | ||
905 | 20 | </record> | ||
906 | 21 | |||
907 | 22 | <record id="wizard_import_list_done" model="ir.ui.view"> | ||
908 | 23 | <field name="name">wizard.import.list.done</field> | ||
909 | 24 | <field name="model">procurement.list.import</field> | ||
910 | 25 | <field name="type">form</field> | ||
911 | 26 | <field name="arch" type="xml"> | ||
912 | 27 | <form string="Result of importation"> | ||
913 | 28 | <separator colspan="4" string="Result of importation" /> | ||
914 | 29 | <field name="message" colspan="4" nolabel="1" /> | ||
915 | 30 | <button name="close_window" string="Close" icon="gtk-close" type="object" /> | ||
916 | 31 | </form> | ||
917 | 32 | </field> | ||
918 | 33 | </record> | ||
919 | 34 | |||
920 | 35 | <act_window | ||
921 | 36 | name="Import lines" | ||
922 | 37 | res_model="procurement.list.import" | ||
923 | 38 | src_model="procurement.list" | ||
924 | 39 | view_mode="form" | ||
925 | 40 | view_type="form" | ||
926 | 41 | view_id="wizard_import_list_init" | ||
927 | 42 | target="new" | ||
928 | 43 | key2="client_action_multi" | ||
929 | 44 | id="action_open_wizard_import" /> | ||
930 | 45 | |||
931 | 46 | </data> | ||
932 | 47 | </openerp> | ||
933 | 48 | |||
934 | 0 | 49 | ||
935 | === added file 'procurement_list/wizard/wizard_list_to_order.py' | |||
936 | --- procurement_list/wizard/wizard_list_to_order.py 1970-01-01 00:00:00 +0000 | |||
937 | +++ procurement_list/wizard/wizard_list_to_order.py 2011-03-16 16:41:25 +0000 | |||
938 | @@ -0,0 +1,63 @@ | |||
939 | 1 | #!/usr/bin/env python | ||
940 | 2 | # -*- encoding: utf-8 -*- | ||
941 | 3 | ############################################################################## | ||
942 | 4 | # | ||
943 | 5 | # OpenERP, Open Source Management Solution | ||
944 | 6 | # Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>). | ||
945 | 7 | # | ||
946 | 8 | # This program is free software: you can redistribute it and/or modify | ||
947 | 9 | # it under the terms of the GNU Affero General Public License as | ||
948 | 10 | # published by the Free Software Foundation, either version 3 of the | ||
949 | 11 | # License, or (at your option) any later version. | ||
950 | 12 | # | ||
951 | 13 | # This program is distributed in the hope that it will be useful, | ||
952 | 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
953 | 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
954 | 16 | # GNU Affero General Public License for more details. | ||
955 | 17 | # | ||
956 | 18 | # You should have received a copy of the GNU Affero General Public License | ||
957 | 19 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
958 | 20 | # | ||
959 | 21 | ############################################################################## | ||
960 | 22 | |||
961 | 23 | import wizard | ||
962 | 24 | import pooler | ||
963 | 25 | |||
964 | 26 | class wizard_list_to_order(wizard.interface): | ||
965 | 27 | |||
966 | 28 | def _get_order(self, cr, uid, data, context={}): | ||
967 | 29 | ''' | ||
968 | 30 | Returns the Purchase Orders generated by the current | ||
969 | 31 | Procurement List | ||
970 | 32 | ''' | ||
971 | 33 | pool_obj = pooler.get_pool(cr.dbname) | ||
972 | 34 | list_obj = pool_obj.get('procurement.list') | ||
973 | 35 | |||
974 | 36 | order_ids = [] | ||
975 | 37 | |||
976 | 38 | for l in list_obj.browse(cr, uid, data['ids'], context=context): | ||
977 | 39 | for o in l.order_ids: | ||
978 | 40 | order_ids.append(o.id) | ||
979 | 41 | |||
980 | 42 | return {'type': 'ir.actions.act_window', | ||
981 | 43 | 'res_model': 'purchase.order', | ||
982 | 44 | 'view_type': 'form', | ||
983 | 45 | 'view_mode': 'tree,form', | ||
984 | 46 | 'domain': [('state', '!=', 'draft'), ('id', 'in', order_ids)], | ||
985 | 47 | } | ||
986 | 48 | |||
987 | 49 | states = { | ||
988 | 50 | 'init': { | ||
989 | 51 | 'actions': [], | ||
990 | 52 | 'result': { | ||
991 | 53 | 'type': 'action', | ||
992 | 54 | 'action': _get_order, | ||
993 | 55 | 'state': 'end', | ||
994 | 56 | }, | ||
995 | 57 | }, | ||
996 | 58 | } | ||
997 | 59 | |||
998 | 60 | wizard_list_to_order('wizard_list_to_order') | ||
999 | 61 | |||
1000 | 62 | # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: | ||
1001 | 63 | |||
1002 | 0 | 64 | ||
1003 | === added file 'procurement_list/wizard/wizard_list_to_rfq.py' | |||
1004 | --- procurement_list/wizard/wizard_list_to_rfq.py 1970-01-01 00:00:00 +0000 | |||
1005 | +++ procurement_list/wizard/wizard_list_to_rfq.py 2011-03-16 16:41:25 +0000 | |||
1006 | @@ -0,0 +1,63 @@ | |||
1007 | 1 | #!/usr/bin/env python | ||
1008 | 2 | # -*- encoding: utf-8 -*- | ||
1009 | 3 | ############################################################################## | ||
1010 | 4 | # | ||
1011 | 5 | # OpenERP, Open Source Management Solution | ||
1012 | 6 | # Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>). | ||
1013 | 7 | # | ||
1014 | 8 | # This program is free software: you can redistribute it and/or modify | ||
1015 | 9 | # it under the terms of the GNU Affero General Public License as | ||
1016 | 10 | # published by the Free Software Foundation, either version 3 of the | ||
1017 | 11 | # License, or (at your option) any later version. | ||
1018 | 12 | # | ||
1019 | 13 | # This program is distributed in the hope that it will be useful, | ||
1020 | 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
1021 | 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
1022 | 16 | # GNU Affero General Public License for more details. | ||
1023 | 17 | # | ||
1024 | 18 | # You should have received a copy of the GNU Affero General Public License | ||
1025 | 19 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1026 | 20 | # | ||
1027 | 21 | ############################################################################## | ||
1028 | 22 | |||
1029 | 23 | import wizard | ||
1030 | 24 | import pooler | ||
1031 | 25 | |||
1032 | 26 | class wizard_list_to_rfq(wizard.interface): | ||
1033 | 27 | |||
1034 | 28 | def _get_order(self, cr, uid, data, context={}): | ||
1035 | 29 | ''' | ||
1036 | 30 | Returns the Requests for Quotation generated by the current | ||
1037 | 31 | Procurement List | ||
1038 | 32 | ''' | ||
1039 | 33 | pool_obj = pooler.get_pool(cr.dbname) | ||
1040 | 34 | list_obj = pool_obj.get('procurement.list') | ||
1041 | 35 | |||
1042 | 36 | order_ids = [] | ||
1043 | 37 | |||
1044 | 38 | for l in list_obj.browse(cr, uid, data['ids'], context=context): | ||
1045 | 39 | for o in l.order_ids: | ||
1046 | 40 | order_ids.append(o.id) | ||
1047 | 41 | |||
1048 | 42 | return {'type': 'ir.actions.act_window', | ||
1049 | 43 | 'res_model': 'purchase.order', | ||
1050 | 44 | 'view_type': 'form', | ||
1051 | 45 | 'view_mode': 'tree,form', | ||
1052 | 46 | 'domain': [('state', '=', 'draft'), ('id', 'in', order_ids)], | ||
1053 | 47 | } | ||
1054 | 48 | |||
1055 | 49 | states = { | ||
1056 | 50 | 'init': { | ||
1057 | 51 | 'actions': [], | ||
1058 | 52 | 'result': { | ||
1059 | 53 | 'type': 'action', | ||
1060 | 54 | 'action': _get_order, | ||
1061 | 55 | 'state': 'end', | ||
1062 | 56 | }, | ||
1063 | 57 | }, | ||
1064 | 58 | } | ||
1065 | 59 | |||
1066 | 60 | wizard_list_to_rfq('wizard_list_to_rfq') | ||
1067 | 61 | |||
1068 | 62 | # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: | ||
1069 | 63 |