[REM] account: Removed unnecessary arguments from name_search.
[odoo/odoo.git] / addons / account / wizard / account_invoice_refund.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 time
23
24 from osv import fields, osv
25 from tools.translate import _
26 import netsvc
27
28 class account_invoice_refund(osv.osv_memory):
29
30     """Refunds invoice"""
31
32     _name = "account.invoice.refund"
33     _description = "Invoice Refund"
34     _columns = {
35        'date': fields.date('Operation date', help='This date will be used as the invoice date for Refund Invoice and Period will be chosen accordingly!'),
36        'period': fields.many2one('account.period', 'Force period'),
37        'journal_id': fields.many2one('account.journal', 'Refund Journal', help='You can select here the journal to use for the refund invoice that will be created. If you leave that field empty, it will use the same journal as the current invoice.'),
38        'description': fields.char('Description', size=128, required=True),
39        'filter_refund': fields.selection([('refund', 'Refund'), ('cancel', 'Cancel'),('modify', 'Modify')], "Refund Type", required=True, help='Refund invoice base on this type. You can not Modify and Cancel if the invoice is already reconciled'),
40     }
41
42     def _get_journal(self, cr, uid, context=None):
43         obj_journal = self.pool.get('account.journal')
44         user_obj = self.pool.get('res.users')
45         if context is None:
46             context = {}
47         inv_type = context.get('type', 'out_invoice')
48         company_id = user_obj.browse(cr, uid, uid, context=context).company_id.id
49         type = (inv_type == 'out_invoice') and 'sale_refund' or \
50                (inv_type == 'out_refund') and 'sale' or \
51                (inv_type == 'in_invoice') and 'purchase_refund' or \
52                (inv_type == 'in_refund') and 'purchase'
53         journal = obj_journal.search(cr, uid, [('type', '=', type), ('company_id','=',company_id)], limit=1, context=context)
54         return journal and journal[0] or False
55
56     _defaults = {
57         'date': lambda *a: time.strftime('%Y-%m-%d'),
58         'journal_id': _get_journal,
59         'filter_refund': 'refund',
60     }
61
62     def fields_view_get(self, cr, uid, view_id=None, view_type=False, context=None, toolbar=False, submenu=False):
63         journal_obj = self.pool.get('account.journal')
64         user_obj = self.pool.get('res.users')
65         res = super(account_invoice_refund,self).fields_view_get(cr, uid, view_id=view_id, view_type=view_type, context=context, toolbar=toolbar, submenu=submenu)
66         type = context.get('type', 'out_invoice')
67         company_id = user_obj.browse(cr, uid, uid, context=context).company_id.id
68         journal_type = (type == 'out_invoice') and 'sale_refund' or \
69                        (type == 'out_refund') and 'sale' or \
70                        (type == 'in_invoice') and 'purchase_refund' or \
71                        (type == 'in_refund') and 'purchase'
72         for field in res['fields']:
73             if field == 'journal_id':
74                 journal_select = journal_obj._name_search(cr, uid, '', [('type', '=', journal_type), ('company_id','child_of',[company_id])], context=context)
75                 res['fields'][field]['selection'] = journal_select
76         return res
77
78     def compute_refund(self, cr, uid, ids, mode='refund', context=None):
79         """
80         @param cr: the current row, from the database cursor,
81         @param uid: the current user’s ID for security checks,
82         @param ids: the account invoice refund’s ID or list of IDs
83
84         """
85         inv_obj = self.pool.get('account.invoice')
86         reconcile_obj = self.pool.get('account.move.reconcile')
87         account_m_line_obj = self.pool.get('account.move.line')
88         mod_obj = self.pool.get('ir.model.data')
89         act_obj = self.pool.get('ir.actions.act_window')
90         wf_service = netsvc.LocalService('workflow')
91         inv_tax_obj = self.pool.get('account.invoice.tax')
92         inv_line_obj = self.pool.get('account.invoice.line')
93         res_users_obj = self.pool.get('res.users')
94         if context is None:
95             context = {}
96
97         for form in self.browse(cr, uid, ids, context=context):
98             created_inv = []
99             date = False
100             period = False
101             description = False
102             company = res_users_obj.browse(cr, uid, uid, context=context).company_id
103             journal_id = form.journal_id.id
104             for inv in inv_obj.browse(cr, uid, context.get('active_ids'), context=context):
105                 if inv.state in ['draft', 'proforma2', 'cancel']:
106                     raise osv.except_osv(_('Error !'), _('Can not %s draft/proforma/cancel invoice.') % (mode))
107                 if inv.reconciled and mode in ('cancel', 'modify'):
108                     raise osv.except_osv(_('Error !'), _('Can not %s invoice which is already reconciled, invoice should be unreconciled first. You can only Refund this invoice') % (mode))
109                 if form.period.id:
110                     period = form.period.id
111                 else:
112                     period = inv.period_id and inv.period_id.id or False
113
114                 if not journal_id:
115                     journal_id = inv.journal_id.id
116
117                 if form.date:
118                     date = form.date
119                     if not form.period.id:
120                             cr.execute("select name from ir_model_fields \
121                                             where model = 'account.period' \
122                                             and name = 'company_id'")
123                             result_query = cr.fetchone()
124                             if result_query:
125                                 cr.execute("""select p.id from account_fiscalyear y, account_period p where y.id=p.fiscalyear_id \
126                                     and date(%s) between p.date_start AND p.date_stop and y.company_id = %s limit 1""", (date, company.id,))
127                             else:
128                                 cr.execute("""SELECT id
129                                         from account_period where date(%s)
130                                         between date_start AND  date_stop  \
131                                         limit 1 """, (date,))
132                             res = cr.fetchone()
133                             if res:
134                                 period = res[0]
135                 else:
136                     date = inv.date_invoice
137                 if form.description:
138                     description = form.description
139                 else:
140                     description = inv.name
141
142                 if not period:
143                     raise osv.except_osv(_('Data Insufficient !'), \
144                                             _('No Period found on Invoice!'))
145
146                 refund_id = inv_obj.refund(cr, uid, [inv.id], date, period, description, journal_id)
147                 refund = inv_obj.browse(cr, uid, refund_id[0], context=context)
148                 inv_obj.write(cr, uid, [refund.id], {'date_due': date,
149                                                 'check_total': inv.check_total})
150                 inv_obj.button_compute(cr, uid, refund_id)
151
152                 created_inv.append(refund_id[0])
153                 if mode in ('cancel', 'modify'):
154                     movelines = inv.move_id.line_id
155                     to_reconcile_ids = {}
156                     for line in movelines:
157                         if line.account_id.id == inv.account_id.id:
158                             to_reconcile_ids[line.account_id.id] = [line.id]
159                         if type(line.reconcile_id) != osv.orm.browse_null:
160                             reconcile_obj.unlink(cr, uid, line.reconcile_id.id)
161                     wf_service.trg_validate(uid, 'account.invoice', \
162                                         refund.id, 'invoice_open', cr)
163                     refund = inv_obj.browse(cr, uid, refund_id[0], context=context)
164                     for tmpline in  refund.move_id.line_id:
165                         if tmpline.account_id.id == inv.account_id.id:
166                             to_reconcile_ids[tmpline.account_id.id].append(tmpline.id)
167                     for account in to_reconcile_ids:
168                         account_m_line_obj.reconcile(cr, uid, to_reconcile_ids[account],
169                                         writeoff_period_id=period,
170                                         writeoff_journal_id = inv.journal_id.id,
171                                         writeoff_acc_id=inv.account_id.id
172                                         )
173                     if mode == 'modify':
174                         invoice = inv_obj.read(cr, uid, [inv.id],
175                                     ['name', 'type', 'number', 'reference',
176                                     'comment', 'date_due', 'partner_id',
177                                     'address_contact_id', 'address_invoice_id',
178                                     'partner_insite', 'partner_contact',
179                                     'partner_ref', 'payment_term', 'account_id',
180                                     'currency_id', 'invoice_line', 'tax_line',
181                                     'journal_id', 'period_id'], context=context)
182                         invoice = invoice[0]
183                         del invoice['id']
184                         invoice_lines = inv_line_obj.read(cr, uid, invoice['invoice_line'], context=context)
185                         invoice_lines = inv_obj._refund_cleanup_lines(cr, uid, invoice_lines)
186                         tax_lines = inv_tax_obj.read(cr, uid, invoice['tax_line'], context=context)
187                         tax_lines = inv_obj._refund_cleanup_lines(cr, uid, tax_lines)
188                         invoice.update({
189                             'type': inv.type,
190                             'date_invoice': date,
191                             'state': 'draft',
192                             'number': False,
193                             'invoice_line': invoice_lines,
194                             'tax_line': tax_lines,
195                             'period_id': period,
196                             'name': description
197                         })
198                         for field in ('address_contact_id', 'address_invoice_id', 'partner_id',
199                                 'account_id', 'currency_id', 'payment_term', 'journal_id'):
200                                 invoice[field] = invoice[field] and invoice[field][0]
201                         inv_id = inv_obj.create(cr, uid, invoice, {})
202                         if inv.payment_term.id:
203                             data = inv_obj.onchange_payment_term_date_invoice(cr, uid, [inv_id], inv.payment_term.id, date)
204                             if 'value' in data and data['value']:
205                                 inv_obj.write(cr, uid, [inv_id], data['value'])
206                         created_inv.append(inv_id)
207             xml_id = (inv.type == 'out_refund') and 'action_invoice_tree1' or \
208                      (inv.type == 'in_refund') and 'action_invoice_tree2' or \
209                      (inv.type == 'out_invoice') and 'action_invoice_tree3' or \
210                      (inv.type == 'in_invoice') and 'action_invoice_tree4'
211             result = mod_obj.get_object_reference(cr, uid, 'account', xml_id)
212             id = result and result[1] or False
213             result = act_obj.read(cr, uid, id, context=context)
214             invoice_domain = eval(result['domain'])
215             invoice_domain.append(('id', 'in', created_inv))
216             result['domain'] = invoice_domain
217             return result
218
219     def invoice_refund(self, cr, uid, ids, context=None):
220         data_refund = self.read(cr, uid, ids, ['filter_refund'],context=context)[0]['filter_refund']
221         return self.compute_refund(cr, uid, ids, data_refund, context=context)
222
223
224 account_invoice_refund()
225
226 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: