Remove unsed field
[odoo/odoo.git] / addons / account_payment / payment.py
1 ##############################################################################
2 #
3 # Copyright (c) 2005-2006 TINY SPRL. (http://tiny.be) All Rights Reserved.
4 #
5 # WARNING: This program as such is intended to be used by professional
6 # programmers who take the whole responsability of assessing all potential
7 # consequences resulting from its eventual inadequacies and bugs
8 # End users who are looking for a ready-to-use solution with commercial
9 # garantees and support are strongly adviced to contract a Free Software
10 # Service Company
11 #
12 # This program is Free Software; you can redistribute it and/or
13 # modify it under the terms of the GNU General Public License
14 # as published by the Free Software Foundation; either version 2
15 # of the License, or (at your option) any later version.
16 #
17 # This program is distributed in the hope that it will be useful,
18 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 # GNU General Public License for more details.
21 #
22 # You should have received a copy of the GNU General Public License
23 # along with this program; if not, write to the Free Software
24 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA      02111-1307, USA.
25 #
26 ##############################################################################
27
28 from osv import fields
29 from osv import osv
30 import time
31 import netsvc
32
33
34 class payment_type(osv.osv):
35         _name= 'payment.type'
36         _description= 'Payment type'
37         _columns= {
38                 'name': fields.char('Name', size=64, required=True),
39                 'code': fields.char('Code', size=64, required=True),
40                 'suitable_bank_types': fields.many2many('res.partner.bank.type',
41                         'bank_type_payment_type_rel',
42                         'pay_type_id','bank_type_id',
43                         'Suitable bank types')
44         }
45
46 payment_type()
47
48
49 class payment_mode(osv.osv):
50         _name= 'payment.mode'
51         _description= 'Payment mode'
52         _columns= {
53                 'name': fields.char('Name', size=64, required=True),
54                 'bank_id': fields.many2one('res.partner.bank', "Bank account",
55                         required=True),
56                 'journal': fields.many2one('account.journal', 'Journal', required=True,
57                         domain=[('type', '=', 'cash')]),
58                 'type': fields.many2one('payment.type','Payment type',required=True),
59         }
60
61         def suitable_bank_types(self,cr,uid,payment_code= 'manual',context={}):
62                 """Return the codes of the bank type that are suitable
63                 for the given payment type code"""
64                 cr.execute(""" select t.code
65                         from res_partner_bank_type t
66                         join bank_type_payment_type_rel r on (r.bank_type_id = t.id)
67                         join payment_type pt on (r.pay_type_id = pt.id)
68                         where pt.code = %s """, [payment_code])
69                 return [x[0] for x in cr.fetchall()]
70
71 payment_mode()
72
73
74 class payment_order(osv.osv):
75         _name = 'payment.order'
76         _description = 'Payment Order'
77         _rec_name = 'date'
78
79         def get_wizard(self,type):
80                 logger = netsvc.Logger()
81                 logger.notifyChannel("warning", netsvc.LOG_WARNING,
82                                 "No wizard found for the payment type '%s'." % type)
83                 return None
84
85         def _total(self, cursor, user, ids, name, args, context=None):
86                 if not ids:
87                         return {}
88                 res = {}
89                 for order in self.browse(cursor, user, ids, context=context):
90                         if order.line_ids:
91                                 res[order.id] = reduce(lambda x, y: x + y.amount, order.line_ids, 0.0)
92                         else:
93                                 res[order.id] = 0.0
94                 return res
95
96         def nb_line(self, cr, uid, ids, name, args, context={}):
97                 if not ids: return {}
98                 res= {}.fromkeys(ids,0)
99                 cr.execute("""SELECT "order_id", count(*)
100                         FROM payment_line
101                         WHERE "order_id" in (%s)
102                         GROUP BY "order_id" """ % ','.join(map(str,ids)))
103                 res.update(dict(cr.fetchall()))
104                 return res
105
106         _columns = {
107                 'date_planned': fields.date('Scheduled date if fixed'),
108                 'reference': fields.char('Reference',size=128),
109                 'mode': fields.many2one('payment.mode','Payment mode', select=True),
110                 'state': fields.selection([
111                         ('draft', 'Draft'),
112                         ('open','Open'),
113                         ('cancel','Cancelled'),
114                         ('done','Done')], 'State', select=True),
115                 'line_ids': fields.one2many('payment.line','order_id','Payment lines'),
116                 'total': fields.function(_total, string="Total", method=True,
117                         type='float'),
118                 'user_id': fields.many2one('res.users','User',required=True),
119                 'nb_line': fields.function(nb_line,string='Number of payment',
120                         method=True, type='integer'),
121                 'date_prefered': fields.selection([
122                         ('now', 'Directly'),
123                         ('due', 'Due date'),
124                         ('fixed', 'Fixed date')
125                         ], "Prefered date", required=True),
126                 'date_created': fields.date('Creation date', readonly=True),
127                 'date_done': fields.date('Execution date', readonly=True),
128         }
129
130         _defaults = {
131                 'user_id': lambda self,cr,uid,context: uid, 
132                 'state': lambda *a: 'draft',
133                 'date_prefered': lambda *a: 'due',
134                 'date_created': lambda *a: time.strftime('%Y-%m-%d'),
135                 'reference': lambda self,cr,uid,context: self.pool.get('ir.sequence'
136                         ).get(cr, uid, 'payment.order'),
137         }
138
139         def set_to_draft(self, cr, uid, ids, *args):
140                 self.write(cr, uid, ids, {'state':'draft'})
141                 wf_service = netsvc.LocalService("workflow")
142                 for id in ids:
143                         wf_service.trg_create(uid, 'payment.order', id, cr)
144                 return True
145
146         def action_open(self, cr, uid, ids, *args):
147                 for order in self.read(cr,uid,ids,['reference']):
148                         if not order['reference']:
149                                 reference = self.pool.get('ir.sequence').get(cr, uid, 'payment.order')
150                                 self.write(cr,uid,order['id'],{'reference':reference})
151                 return True
152
153         def set_done(self, cr, uid, id, *args):
154                 self.write(cr,uid,id,{'date_done': time.strftime('%Y-%m-%d'),
155                         'state': 'done',})
156                 wf_service = netsvc.LocalService("workflow")
157                 wf_service.trg_validate(uid, 'payment.order', id, 'done', cr)
158                 return True
159
160 payment_order()
161
162
163 class payment_line(osv.osv):
164         _name = 'payment.line'
165         _description = 'Payment Line'
166
167         def partner_payable(self, cr, uid, ids, name, args, context={}):
168                 if not ids: return {}
169                 partners= self.read(cr, uid, ids, ['partner_id'], context)
170                 partners= dict(map(lambda x: (x['id'], x['partner_id'][0]), partners))
171                 debit = self.pool.get('res.partner')._debit_get(cr, uid,
172                                 partners.values(), name, args, context)
173                 for i in partners:
174                         partners[i] = debit[partners[i]]
175                 return partners
176
177         def translate(self, orig):
178                 return {"to_pay": "credit",
179                                 "due_date": "date_maturity",
180                                 "reference": "ref"}.get(orig, orig)
181
182         def select_by_name(self, cr, uid, ids, name, args, context=None):
183                 if not ids: return {}
184
185                 partner_obj = self.pool.get('res.partner')
186                 cr.execute("""SELECT pl.id, ml.%s
187                         from account_move_line ml
188                                 inner join payment_line pl
189                                 on (ml.id = pl.move_line_id)
190                         where pl.id in (%s)"""%
191                         (self.translate(name), ','.join(map(str,ids))) )
192                 res = dict(cr.fetchall())
193
194                 if name == 'partner_id':
195                         partner_name = {}
196                         for p_id, p_name in partner_obj.name_get(cr,uid,
197                                 filter(lambda x:x and x != 0,res.values()),context=context):
198                                 partner_name[p_id] = p_name
199
200                         for id in ids:
201                                 if id in res:
202                                         res[id] = (res[id],partner_name[res[id]])
203                                 else:
204                                         res[id] = (False,False)
205                 else:
206                         for id in ids:
207                                 res.setdefault(id, (False, ""))
208                 return res
209
210         def _currency(self, cursor, user, ids, name, args, context=None):
211                 if not ids:
212                         return {}
213                 res = {}
214
215                 currency_obj = self.pool.get('res.currency')
216                 account_obj = self.pool.get('account.account')
217                 cursor.execute('''SELECT pl.id, ml.currency_id, ml.account_id
218                 FROM account_move_line ml
219                         INNER JOIN payment_line pl
220                                 ON (ml.id = pl.move_line_id)
221                 WHERE pl.id in (''' + ','.join([str(x) for x in ids]) + ')')
222
223                 res2 = {}
224                 account_ids = []
225                 for payment_line_id, currency_id, account_id in cursor.fetchall():
226                         res2[payment_line_id] = [currency_id, account_id]
227                         account_ids.append(account_id)
228
229                 account2currency_id = {}
230                 for account in account_obj.browse(cursor, user, account_ids,
231                                 context=context):
232                         account2currency_id[account.id] = account.company_currency_id.id
233
234                 for payment_line_id in ids:
235                         if res2[payment_line_id][0]:
236                                 res[payment_line_id] = res2[payment_line_id][0]
237                         else:
238                                 res[payment_line_id] = \
239                                                 account2currency_id[res2[payment_line_id][1]]
240
241                 currency_names = {}
242                 for currency_id, name in currency_obj.name_get(cursor, user, res.values(),
243                                 context=context):
244                         currency_names[currency_id] = name
245                 for payment_line_id in ids:
246                         res[payment_line_id] = (res[payment_line_id],
247                                         currency_names[res[payment_line_id]])
248                 return res
249
250         def _to_pay_currency(self, cursor, user, ids, name , args, context=None):
251                 if not ids:
252                         return {}
253
254                 cursor.execute('''SELECT pl.id,
255                         CASE WHEN ml.amount_currency < 0
256                                 THEN - ml.amount_currency
257                                 ELSE ml.credit
258                         END
259                 FROM account_move_line ml
260                         INNER JOIN payment_line pl
261                                 ON (ml.id = pl.move_line_id)
262                 WHERE pl.id in (''' + ','.join([str(x) for x in ids]) + ')')
263                 return dict(cursor.fetchall())
264
265         def _amount(self, cursor, user, ids, name, args, context=None):
266                 if not ids:
267                         return {}
268                 currency_obj = self.pool.get('res.currency')
269                 if context is None:
270                         context = {}
271                 res = {}
272                 for line in self.browse(cursor, user, ids, context=context):
273                         ctx = context.copy()
274                         ctx['date'] = line.order_id.date_done or time.strftime('%Y-%m-%d')
275                         res[line.id] = currency_obj.compute(cursor, user, line.currency.id,
276                                         line.move_line_id.account_id.company_currency_id.id,
277                                         line.amount_currency, context=ctx)
278                 return res
279
280         def _value_date(self, cursor, user, ids, name, args, context=None):
281                 if not ids:
282                         return {}
283                 res = {}
284                 for line in self.browse(cursor, user, ids, context=context):
285                         if line.order_id.date_prefered == 'fixed':
286                                 res[line.id] = line.order_id.date_planned
287                         elif line.order_id.date_prefered == 'due':
288                                 res[line.id] = line.due_date or time.strftime('%Y-%m-%d')
289                         else:
290                                 res[line.id] = time.strftime('%Y-%m-%d')
291                 return res
292
293         _columns = {
294                 'name': fields.char('Name', size=64, required=True, readonly=True),
295                 'move_line_id': fields.many2one('account.move.line','Entry line',
296                         required=True),
297                 'amount_currency': fields.float('Amount', digits=(16,2),
298                         required=True, help='Payment amount in the partner currency'),
299                 'to_pay_currency': fields.function(_to_pay_currency, string='To Pay',
300                         method=True, type='float',
301                         help='Amount to pay in the partner currency'),
302                 'currency': fields.function(_currency, string='Currency',
303                         method=True, type='many2one', obj='res.currency'),
304                 'bank_id': fields.many2one('res.partner.bank', 'Bank account'),
305                 'order_id': fields.many2one('payment.order', 'Order', required=True,
306                         ondelete='cascade', select=True),
307                 'partner_id': fields.function(select_by_name, string="Partner",
308                         method=True, type='many2one', obj='res.partner'),
309                 'amount': fields.function(_amount, string='Amount',
310                         method=True, type='float',
311                         help='Payment amount in the company currency'),
312                 'to_pay': fields.function(select_by_name, string="To Pay", method=True,
313                         type='float', help='Amount to pay in the company currency'),
314                 'due_date': fields.function(select_by_name, string="Due date",
315                         method=True, type='date'),
316                 'date_created': fields.function(select_by_name, string="Creation date",
317                         method=True, type='date'),
318                 'reference': fields.function(select_by_name, string="Ref", method=True,
319                         type='char'),
320                 'partner_payable': fields.function(partner_payable,
321                         string="Partner payable", method=True, type='float'),
322                 'value_date': fields.function(_value_date, string='Value Date',
323                         method=True, type='date'),
324          }
325         _defaults = {
326                 'name': lambda obj, cursor, user, context: obj.pool.get('ir.sequence'
327                         ).get(cursor, user, 'payment.line'),
328         }
329         _sql_constraints = [
330                 ('name_uniq', 'UNIQUE(name)', 'The payment line name must be unique!'),
331         ]
332
333         def onchange_move_line(self, cr, uid, id, move_line_id, payment_type,context=None):
334                 if not move_line_id:
335                         return {}
336                 line=self.pool.get('account.move.line').browse(cr,uid,move_line_id)
337                 return {'value': {
338                         'amount_currency': line.amount_to_pay,
339                         'to_pay_currency': line.amount_to_pay,
340                         'partner_id': line.partner_id.id,
341                         'reference': line.ref,
342                         'date_created': line.date_created,
343                         'bank_id': self.pool.get('account.move.line').line2bank(cr, uid,
344                                 [move_line_id],
345                                 payment_type or 'manual', context)[move_line_id]
346                         }}
347
348 payment_line()