[WIP] all: (work in progress) changing wizards to avoid using read() or at least...
[odoo/odoo.git] / addons / point_of_sale / wizard / pos_return.py
1 # -*- coding: utf-8 -*-
2 ##############################################################################
3 #    
4 #    OpenERP, Open Source Management Solution
5 #    Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
6 #
7 #    This program is free software: you can redistribute it and/or modify
8 #    it under the terms of the GNU Affero General Public License as
9 #    published by the Free Software Foundation, either version 3 of the
10 #    License, or (at your option) any later version.
11 #
12 #    This program is distributed in the hope that it will be useful,
13 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
14 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 #    GNU Affero General Public License for more details.
16 #
17 #    You should have received a copy of the GNU Affero General Public License
18 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.     
19 #
20 ##############################################################################
21
22 import netsvc
23 from osv import osv,fields
24 from tools.translate import _
25 import time
26
27 class pos_return(osv.osv_memory):
28     _name = 'pos.return'
29     _description = 'Point of sale return'
30
31     def default_get(self, cr, uid, fields, context=None):
32         """
33              To get default values for the object.
34
35              @param self: The object pointer.
36              @param cr: A database cursor
37              @param uid: ID of the user currently logged in
38              @param fields: List of fields for which we want default values
39              @param context: A standard dictionary
40
41              @return: A dictionary which of fields with values.
42
43         """
44
45         res = super(pos_return, self).default_get(cr, uid, fields, context=context)
46         order_obj = self.pool.get('pos.order')
47         if context is None:
48             context={}
49         active_ids = context.get('active_ids')
50         for order in order_obj.browse(cr, uid, active_ids, context=context):
51             for line in order.lines:
52                 if 'return%s'%(line.id) in fields:
53                     res['return%s'%(line.id)] = line.qty
54         return res
55
56     def view_init(self, cr, uid, fields_list, context=None):
57         """
58          Creates view dynamically and adding fields at runtime.
59          @param self: The object pointer.
60          @param cr: A database cursor
61          @param uid: ID of the user currently logged in
62          @param context: A standard dictionary
63          @return: New arch of view with new columns.
64         """
65         res = super(pos_return, self).view_init(cr, uid, fields_list, context=context)
66         order_obj=self.pool.get('pos.order')
67         if context is None:
68             context={}
69
70         active_ids=context.get('active_ids')
71         for order in order_obj.browse(cr, uid, active_ids, context=context):
72             for line in order.lines:
73                 if 'return%s'%(line.id) not in self._columns:
74                     self._columns['return%s'%(line.id)] = fields.float("Quantity")
75
76         return res
77
78     def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False,submenu=False):
79
80         """
81              Changes the view dynamically
82
83              @param self: The object pointer.
84              @param cr: A database cursor
85              @param uid: ID of the user currently logged in
86              @param context: A standard dictionary
87
88              @return: New arch of view.
89
90         """
91         result = super(pos_return, self).fields_view_get(cr, uid, view_id, view_type, context, toolbar,submenu)
92         if context is None:
93             context={}
94         active_model = context.get('active_model')
95         if not active_model and active_model != 'pos.order':
96             return result
97         order_obj = self.pool.get('pos.order')
98         active_id = context.get('active_id', False)
99         if active_id:
100             _moves_arch_lst="""<?xml version="1.0"?>
101                             <form string="Return lines">
102                             <label string="Quantities you enter, match to products that will return to the stock." colspan="4"/>"""
103             _line_fields = result['fields']
104             order=order_obj.browse(cr, uid, active_id, context=context)
105             for line in order.lines:
106                 quantity=line.qty
107                 _line_fields.update({
108                     'return%s'%(line.id) : {
109                         'string': line.product_id.name,
110                         'type' : 'float',
111                         'required': True,
112                         'default':quantity
113                     },
114                 })
115                 _moves_arch_lst += """
116                         <field name="return%s"/>
117                          <newline/>
118                 """%(line.id)
119
120             _moves_arch_lst+="""
121                     <newline/>
122                     <separator colspan="4"/>
123                    <button icon='gtk-cancel' special="cancel"
124                                string="Cancel" />
125                                    <button icon='gtk-ok' name= "create_returns"
126                        string="Return with Exchange" type="object"/>
127                                    <button icon='gtk-ok' name="create_returns2"
128                         string="Refund Without Exchange" type="object"/>
129                 </form>"""
130
131             result['arch'] = _moves_arch_lst
132             result['fields'] = _line_fields
133         return result
134
135
136     def  create_returns(self, cr, uid, data, context=None):
137         """
138              @param self: The object pointer.
139              @param cr: A database cursor
140              @param uid: ID of the user currently logged in
141              @param context: A standard dictionary
142
143              @return: Return the add product form again for adding more product
144
145         """
146         if context is None:
147             context = {}
148         current_rec = self.read(cr, uid, data[0], context=context)
149         order_obj =self.pool.get('pos.order')
150         line_obj = self.pool.get('pos.order.line')
151         pos_current = order_obj.browse(cr, uid, context.get('active_id'), context=context)
152         pos_line_ids = pos_current.lines
153         if pos_line_ids:
154             for pos_line in pos_line_ids:
155                 line_field = "return"+str(pos_line.id)
156                 pos_list = current_rec.keys()
157                 newline_vals = {}
158                 if line_field in pos_list :
159                     less_qty = current_rec.get(line_field)
160                     pos_cur_line = line_obj.browse(cr, uid, pos_line.id, context=context)
161                     qty = pos_cur_line.qty
162                     qty = qty - less_qty
163                     newline_vals.update({'qty':qty})
164                     line_obj.write(cr, uid, pos_line.id, newline_vals, context=context)
165         return {
166             'name': _('Add Product'),
167             'view_type': 'form',
168             'view_mode': 'form',
169             'res_model': 'pos.add.product',
170             'view_id': False,
171             'target':'new',
172             'views': False,
173             'context': context,
174             'type': 'ir.actions.act_window',
175         }
176     def create_returns2(self, cr, uid, ids, context=None):
177         if context is None:
178             context = {}
179         active_id = context.get('active_id', False)
180         order_obj =self.pool.get('pos.order')
181         line_obj = self.pool.get('pos.order.line')
182         picking_obj = self.pool.get('stock.picking')
183         stock_move_obj = self.pool.get('stock.move')
184         property_obj= self.pool.get("ir.property")
185         uom_obj =self. pool.get('product.uom')
186         statementl_obj = self.pool.get('account.bank.statement.line')
187         wf_service = netsvc.LocalService("workflow")
188         #Todo :Need to clean the code
189         if active_id:
190             data = self.read(cr, uid, ids)[0]
191             date_cur = time.strftime('%Y-%m-%d %H:%M:%S')
192
193             for order_id in order_obj.browse(cr, uid, [active_id], context=context):
194                 prop_ids = property_obj.search(cr, uid,[('name', '=', 'property_stock_customer')])
195                 val = property_obj.browse(cr, uid, prop_ids[0], context=context).value_reference
196                 cr.execute("SELECT s.id FROM stock_location s, stock_warehouse w "
197                             "WHERE w.lot_stock_id=s.id AND w.id=%s ", 
198                             (order_id.shop_id.warehouse_id.id,))
199                 res = cr.fetchone()
200                 location_id = res and res[0] or None
201                 stock_dest_id = val.id
202                 new_picking = picking_obj.copy(cr, uid, order_id.picking_id.id, {'name':'%s (return)' % order_id.name,
203                                                                                'move_lines': [],
204                                                                                'state':'draft',
205                                                                                'type': 'in',
206                                                                                'address_id': order_id.partner_id.id,
207                                                                                'date': date_cur })
208                 new_order = order_obj.copy(cr, uid, order_id.id, {'name': 'Refund %s'%order_id.name,
209                                                               'lines':[],
210                                                               'statement_ids':[],
211                                                               'picking_id':[]})
212                 account_def = property_obj.get(cr, uid, 'property_account_payable', 'res.partner', context=context)
213                 amount = 0.0
214                 for line in order_id.lines:
215                     if line.id:
216                         try:
217                             qty = data['return%s' %line.id]
218                             amount += qty * line.price_unit
219                         except :
220                             qty = line.qty
221                         stock_move_obj.create(cr, uid, {
222                             'product_qty': qty ,
223                             'product_uos_qty': uom_obj._compute_qty(cr, uid, qty ,line.product_id.uom_id.id),
224                             'picking_id': new_picking,
225                             'product_uom': line.product_id.uom_id.id,
226                             'location_id': location_id,
227                             'product_id': line.product_id.id,
228                             'location_dest_id': stock_dest_id,
229                             'name': '%s (return)' %order_id.name,
230                             'date': date_cur
231                         })
232                         if qty != 0.0:
233                             line_obj.copy(cr, uid, line.id, {'qty': -qty, 'order_id': new_order})
234                 statementl_obj.create(cr, uid, {
235                                                 'name': 'Refund %s'%order_id.name,
236                                                 'statement_id': order_id.statement_ids[0].statement_id.id,
237                                                 'pos_statement_id': new_order,
238                                                 'date': time.strftime('%Y-%m-%d'),
239                                                 'account_id': order_id.partner_id and order_id.partner_id.property_account_payable \
240                                                              and order_id.partner_id.property_account_payable.id or account_def.id,
241                                                 'amount': -amount,
242                                                 })
243                 order_obj.write(cr,uid, [active_id,new_order], {'state': 'done'})
244                 wf_service.trg_validate(uid, 'stock.picking', new_picking, 'button_confirm', cr)
245                 picking_obj.force_assign(cr, uid, [new_picking], context)
246             act = {
247                 'domain': "[('id', 'in', ["+str(new_order)+"])]",
248                 'name': 'Refunded Orders',
249                 'view_type': 'form',
250                 'view_mode': 'tree,form',
251                 'res_model': 'pos.order',
252                 'auto_refresh':0,
253                 'res_id':new_order,
254                 'view_id': False,
255                 'context':context,
256                 'type': 'ir.actions.act_window'
257             }
258         return act
259
260 pos_return()
261
262 class add_product(osv.osv_memory):
263     _inherit = 'pos.add.product'
264     def select_product(self, cr, uid, ids, context=None):
265         """
266              To get the product and quantity and add in order .
267              @param self: The object pointer.
268              @param cr: A database cursor
269              @param uid: ID of the user currently logged in
270              @param context: A standard dictionary
271              @return : Retrun the add product form again for adding more product
272         """
273         if context is None:
274             context = {}
275
276         active_id=context.get('active_id', False)
277         data =  self.read(cr, uid, ids)
278         data = data and data[0] or False
279         if active_id:
280             order_obj = self.pool.get('pos.order')
281             picking_obj = self.pool.get('stock.picking')
282             stock_move_obj = self.pool.get('stock.move')
283             property_obj= self.pool.get("ir.property")
284             date_cur=time.strftime('%Y-%m-%d')
285             uom_obj = self.pool.get('product.uom')
286             prod_obj=self.pool.get('product.product')
287             wf_service = netsvc.LocalService("workflow")
288             order_obj.add_product(cr, uid, active_id, data['product_id'], data['quantity'], context=context)
289
290             for order_id in order_obj.browse(cr, uid, [active_id], context=context):
291                 prod=data['product_id']
292                 qty=data['quantity']
293                 prop_ids = property_obj.search(cr, uid, [('name', '=', 'property_stock_customer')])
294                 val = property_obj.browse(cr, uid, prop_ids[0]).value_reference
295                 cr.execute("SELECT s.id FROM stock_location s, stock_warehouse w "
296                             "WHERE w.lot_stock_id=s.id AND w.id=%s ",
297                             (order_id.shop_id.warehouse_id.id,))
298                 res=cr.fetchone()
299                 location_id=res and res[0] or None
300                 stock_dest_id = val.id
301
302                 prod_id=prod_obj.browse(cr, uid, prod, context=context)
303                 new_picking=picking_obj.create(cr, uid, {
304                                 'name':'%s (Added)' %order_id.name,
305                                 'move_lines':[],
306                                 'state':'draft',
307                                 'type':'out',
308                                 'date':date_cur
309                             })
310                 stock_move_obj.create(cr, uid, {
311                                 'product_qty': qty,
312                                 'product_uos_qty': uom_obj._compute_qty(cr, uid, prod_id.uom_id.id, qty, prod_id.uom_id.id),
313                                 'picking_id':new_picking,
314                                 'product_uom':prod_id.uom_id.id,
315                                 'location_id':location_id,
316                                 'product_id':prod_id.id,
317                                 'location_dest_id':stock_dest_id,
318                                 'name':'%s (return)' %order_id.name,
319                                 'date':date_cur
320                             })
321
322                 wf_service.trg_validate(uid, 'stock.picking', new_picking, 'button_confirm', cr)
323                 picking_obj.force_assign(cr, uid, [new_picking], context)
324                 order_obj.write(cr,uid,active_id,{'picking_id':new_picking})
325
326         return {
327             'name': _('Add Product'),
328             'view_type': 'form',
329             'view_mode': 'form',
330             'res_model': 'pos.add.product',
331             'view_id': False,
332             'target':'new',
333             'context':context,
334             'views': False,
335             'type': 'ir.actions.act_window',
336         }
337
338     def close_action(self, cr, uid, ids, context=None):
339         if context is None: context = {}
340         active_ids=context.get('active_ids', False)
341         order_obj = self.pool.get('pos.order')
342         lines_obj = self.pool.get('pos.order.line')
343         picking_obj = self.pool.get('stock.picking')
344         stock_move_obj = self.pool.get('stock.move')
345         property_obj= self.pool.get("ir.property")
346         invoice_obj=self.pool.get('account.invoice')
347         date_cur=time.strftime('%Y-%m-%d %H:%M:%S')
348         uom_obj = self.pool.get('product.uom')
349         return_boj=self.pool.get('pos.return')
350         return_id = return_boj.search(cr,uid,[])
351         data = {}
352         if return_id:
353             data = return_boj.read(cr,uid,return_id,[])[0]
354
355         wf_service = netsvc.LocalService("workflow")
356         self_data = self.browse(cr, uid, ids)[0]
357         order_obj.add_product(cr, uid, active_ids[0], self_data.product_id.id, self_data.quantity, context=context)
358         
359         for order_id in order_obj.browse(cr, uid, active_ids, context=context):
360             prop_ids =property_obj.search(cr, uid, [('name', '=', 'property_stock_customer')])
361             val = property_obj.browse(cr, uid, prop_ids[0]).value_reference
362             cr.execute("SELECT s.id FROM stock_location s, stock_warehouse w "
363                         " WHERE w.lot_stock_id=s.id AND w.id=%s ",
364                         (order_id.shop_id.warehouse_id.id,))
365             res=cr.fetchone()
366             location_id=res and res[0] or None
367             stock_dest_id = val.id
368
369             order_obj.write(cr,uid,[order_id.id],{'type_rec':'Exchange'})
370             if order_id.invoice_id:
371                 invoice_obj.refund(cr, uid, [order_id.invoice_id.id], time.strftime('%Y-%m-%d'), False, order_id.name)
372             new_picking=picking_obj.create(cr, uid, {
373                             'name':'%s (return)' %order_id.name,
374                             'move_lines':[], 'state':'draft',
375                             'type':'in',
376                             'date':date_cur
377                         })
378             for line in order_id.lines:
379                 key= 'return%s' % line.id
380                 if line.id: 
381                     if data.has_key(key):
382                         qty = data[key]
383                         lines_obj.write(cr,uid,[line.id], {
384                                 'qty_rfd':(line.qty or 0.0) + data[key],
385                                 'qty':line.qty-(data[key] or 0.0)
386                         })
387                     else:
388                         qty = line.qty
389                     stock_move_obj.create(cr, uid, {
390                         'product_qty': qty,
391                         'product_uos_qty': uom_obj._compute_qty(cr, uid, qty, line.product_id.uom_id.id),
392                         'picking_id':new_picking,
393                         'product_uom':line.product_id.uom_id.id,
394                         'location_id':location_id,
395                         'product_id':line.product_id.id,
396                         'location_dest_id':stock_dest_id,
397                         'name':'%s (return)' % order_id.name,
398                         'date':date_cur,
399                     })
400             wf_service.trg_validate(uid, 'stock.picking',new_picking,'button_confirm', cr)
401             picking_obj.force_assign(cr, uid, [new_picking], context)
402         obj=order_obj.browse(cr,uid, active_ids[0])
403         context.update({'return':'return'})
404
405         if obj.amount_total != obj.amount_paid:
406             return {
407                 'name': _('Make Payment'),
408                 'context ':context,
409                 'view_type': 'form',
410                 'view_mode': 'form',
411                 'res_model': 'pos.make.payment',
412                 'view_id': False,
413                 'target': 'new',
414                 'views': False,
415                 'type': 'ir.actions.act_window',
416             }
417         return True
418
419 add_product()
420 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: