1
# -*- encoding: utf-8 -*-
2
##############################################################################
4
# OpenERP, Open Source Management Solution
5
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved
8
# This program is free software: you can redistribute it and/or modify
9
# it under the terms of the GNU General Public License as published by
10
# the Free Software Foundation, either version 3 of the License, or
11
# (at your option) any later version.
13
# This program is distributed in the hope that it will be useful,
14
# but WITHOUT ANY WARRANTY; without even the implied warranty of
15
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
# GNU General Public License for more details.
18
# You should have received a copy of the GNU General Public License
19
# along with this program. If not, see <http://www.gnu.org/licenses/>.
21
##############################################################################
24
from osv import fields, osv
27
from tempfile import TemporaryFile
30
from tools.translate import _
32
class import_bank_statement(osv.osv):
33
_name = 'account.import_bank_statement'
34
_description = 'Import Bank Statement'
35
_inherit = ['mail.thread']
37
def default_state(self, cr, uid, context={}):
40
def default_company_id(self, cr, uid, context={}):
41
obj_user = self.pool.get('res.users')
43
user = obj_user.browse(cr, uid, [uid])[0]
45
return user.company_id.id
48
'name' : fields.char(string='Description', size=100, required=True, readonly=True, states={'draft':[('readonly',False)]}),
49
'company_id' : fields.many2one(string='Company', obj='res.company', required=True, readonly=True, states={'draft':[('readonly',False)]}),
50
'fiscalyear_id' : fields.many2one(string='Fiscal Year', obj='account.fiscalyear', required=True, readonly=True, states={'draft':[('readonly',False)]}),
51
'period_id' : fields.many2one(string='Period', obj='account.period', required=True, readonly=True, states={'draft':[('readonly',False)]}),
52
'file_name' : fields.binary(string='Bank Statement File', required=True, readonly=True, states={'draft':[('readonly',False)]}),
53
'journal_id' : fields.many2one(string='Journal', obj='account.journal', required=True, readonly=True, states={'draft':[('readonly',False)]}),
54
'temporary_account_id' : fields.many2one(string='Temporary Account', obj='account.account', required=True, readonly=True, states={'draft':[('readonly',False)]}),
55
'bank_statement_type_id' : fields.many2one(string='Statement Type', obj='account.bank_statement_type', required=True, readonly=True, states={'draft':[('readonly',False)]}),
56
'bank_statement_type' : fields.related('bank_statement_type_id','name', string='Statement Type', type='char', relation='account.bank_statement_type', store=True, readonly=True),
57
'import_bank_statement_ids' : fields.one2many(string='Detail', obj='account.import_bank_statement_detail', fields_id='import_bank_statement_id'),
58
'state' : fields.selection(string='State', selection=[('draft','Draft'),('imported','Imported'),('open','On Progress'),('done','Done'),('cancel','Cancelled')], readonly=True, required=True),
63
'state' : default_state,
64
'company_id' : default_company_id,
67
def unlink(self, cr, uid, ids, context=None):
68
raise osv.except_osv(_('Warning!'),_('You can not delete data, please cancel instead'))
71
def copy(self, cr, uid, id, defaults, context=None):
72
raise osv.except_osv(_('Warning!'),_('You can not copy data'))
76
def button_import(self, cr, uid, ids, context={}):
80
csv_file = self._open_file(cr, uid, id)
84
csv_file = self._cleanup_csv(cr, uid, id, csv_file)
88
csv_file = self._read_csv_row(cr, uid, id, csv_file)
92
if not self._import_result_list(cr, uid, id, csv_file):
97
def button_posted(self, cr, uid, ids, context={}):
99
if not self._create_bank_voucher(cr, uid, id):
104
def button_confirm(self, cr, uid, ids, context={}):
106
self.write(cr, uid, [id], {'state' : 'imported'})
110
def button_finished_assign_voucher(self, cr, uid, ids, context={}):
112
if not self._check_finished_assign(cr, uid, id):
115
self.write(cr, uid, [id], {'state' : 'open'})
119
def button_done(self, cr, uid, ids, context={}):
121
if not self._check_voucher_posted(cr, uid, id):
124
self.write(cr, uid, [id], {'state' : 'done'})
128
def button_cancel(self, cr, uid, ids, context={}):
130
if not self._check_voucher_cancel(cr, uid, id):
133
self.write(cr, uid, [id], {'state' : 'cancel'})
137
def button_set_to_draft(self, cr, uid, ids, context={}):
139
self.write(cr, uid, [id], {'state' : 'draft'})
143
def _import_csv(self, cr, uid, id):
147
def _create_bank_voucher(self, cr, uid, id):
148
obj_detail = self.pool.get('account.import_bank_statement_detail')
150
import_bank_statement = self.browse(cr, uid, [id])[0]
152
if import_bank_statement.import_bank_statement_ids:
153
for detail in import_bank_statement.import_bank_statement_ids:
154
if not obj_detail._create_account_voucher(cr, uid, detail.id):
159
def _open_file(self, cr, uid, id):
160
obj_import_bank_statement = self.pool.get('account.import_bank_statement')
162
import_bank_statement = obj_import_bank_statement.browse(cr, uid, [id])[0]
165
fileobj = TemporaryFile('w+')
166
fileobj.write(base64.decodestring(import_bank_statement.file_name))
168
raise osv.except_osv(_('Open file error'),_('%s') % e)
172
def _cleanup_csv(self, cr, uid, id, fileobj):
173
obj_import_bank_statement = self.pool.get('account.import_bank_statement')
175
import_bank_statement = obj_import_bank_statement.browse(cr, uid, [id])[0]
178
f = getattr(obj_import_bank_statement, import_bank_statement.bank_statement_type_id.csv_cleanup_function, None)
180
raise osv.except_osv(_('CSV cleanup error'),_('%s') % e)
182
result = f(cr, uid, id, fileobj)
186
def _read_csv_row(self, cr, uid, id, fileobj):
187
obj_import_bank_statement = self.pool.get('account.import_bank_statement')
189
import_bank_statement = obj_import_bank_statement.browse(cr, uid, [id])[0]
192
f = getattr(obj_import_bank_statement, import_bank_statement.bank_statement_type_id.csv_read_row_function, None)
194
raise osv.except_osv(_('CSV row reading error'),_('%s') % e)
196
result = f(cr, uid, id, fileobj)
200
def _generic_cleanup_function(self, cr, uid, id, fileobj):
204
def _generic_read_row_function(self, cr, uid, id, fileobj):
207
csvfile = csv.reader(fileobj,delimiter=';')
209
for baris in csvfile:
213
'transaction_type' : baris[2],
216
list_result.append(res)
221
def _import_result_list(self, cr, uid, id, list_result):
222
obj_detail = self.pool.get('account.import_bank_statement_detail')
224
for import_row in list_result:
225
import_row['import_bank_statement_id'] = id
226
obj_detail.create(cr, uid, import_row)
230
def _check_finished_assign(self, cr, uid, id):
231
import_bank_statement = self.browse(cr, uid, [id])[0]
233
for detail in import_bank_statement.import_bank_statement_ids:
234
if not detail.account_voucher_id:
235
raise osv.except_osv(_('Warning!'),_('Not all line have a voucher'))
240
def _check_voucher_posted(self, cr, uid, id):
241
import_bank_statement = self.browse(cr, uid, [id])[0]
243
for detail in import_bank_statement.import_bank_statement_ids:
244
if detail.account_voucher_id.state != 'posted':
245
raise osv.except_osv(_('Warning!'),_('No all voucher is posted'))
250
def _check_voucher_cancel(self, cr, uid, id):
251
import_bank_statement = self.browse(cr, uid, [id])[0]
253
for detail in import_bank_statement.import_bank_statement_ids:
254
if detail.account_voucher_id and detail.account_voucher_id.state != 'cancel':
255
raise osv.except_osv(_('Warning!'),_('Cancel or unassign voucher first'))
260
import_bank_statement()
262
class import_bank_statement_detail(osv.osv):
263
_name = 'account.import_bank_statement_detail'
264
_description = 'Import Bank Statement Detail'
266
def function_state(self, cr, uid, ids, field_name, args, context=None):
268
for detail in self.browse(cr, uid, ids):
269
res[detail.id] = 'unassigned'
271
if detail.account_voucher_id:
272
res[detail.id] = detail.account_voucher_id.state
276
def _get_import_bank_statement(self, cr, uid, ids, context=None):
277
obj_import_bs = self.pool.get('account.import_bank_statement')
280
for import_bs in obj_import_bs.browse(cr, uid, ids):
281
if import_bs.import_bank_statement_ids:
282
for detail in import_bs.import_bank_statement_ids:
283
result.append(detail.import_bank_statement_id.id)
287
def _get_account_voucher(self, cr, uid, ids, context=None):
289
obj_voucher = self.pool.get('account.voucher')
290
obj_detail = self.pool.get('account.import_bank_statement_detail')
292
for voucher in obj_voucher.browse(cr, uid, ids):
293
criteria = [('account_voucher_id','=',voucher.id)]
294
import_ids = obj_detail.search(cr, uid, criteria)
297
raise osv.except_osv('a','b')
300
def _get_bank_payment(self, cr, uid, ids, context=None):
302
obj_voucher = self.pool.get('account.bank_payment')
303
obj_detail = self.pool.get('account.import_bank_statement_detail')
305
for voucher in obj_voucher.browse(cr, uid, ids):
306
criteria = [('account_voucher_id','=',voucher.id)]
307
import_ids = obj_detail.search(cr, uid, criteria)
310
raise osv.except_osv('a','c')
313
def _get_bank_receipt(self, cr, uid, ids, context=None):
315
obj_voucher = self.pool.get('account.bank_receipt')
316
obj_detail = self.pool.get('account.import_bank_statement_detail')
318
for voucher in obj_voucher.browse(cr, uid, ids):
319
criteria = [('account_voucher_id','=',voucher.id)]
320
import_ids = obj_detail.search(cr, uid, criteria)
324
raise osv.except_osv('a','d')
328
'import_bank_statement_id' : fields.many2one(string='Import Bank Statement', obj='account.import_bank_statement', ondelete='cascade'),
329
'name' : fields.char(string='Description', size=255, required=True),
330
'date' : fields.date(string='Date', required=True), #TODO: Help tips
331
'transaction_type' : fields.selection(string='Type', selection=[('dr','DR'),('cr','CR')], required=True), #TODO: Help tips
332
'amount' : fields.float(string='Amount', required=True), #TODO: Help tips
333
'account_voucher_id' : fields.many2one(string='Bank Receipt/Payment', obj='account.voucher'), #TODO: Help tips
335
'state' : fields.function(string='Voucher State', fnct=function_state, type='selection', selection=[('unassigned','Unassigned'),('draft','Draft'),('confirm','Waiting For Approval'),('approve','Ready To Process'),('proforma','Pro-Forma'),('posted','Posted'),('cancel','Cancelled')],
337
'account.import_bank_statement_detail' : (lambda self, cr, uid, ids, c={}:ids, ['account_voucher_id'], 10),
338
'account.import_bank_statement' : (_get_import_bank_statement, None, 10),
339
'acount.voucher' : (_get_account_voucher, None, 10),
340
'account.bank_payment' : (_get_bank_payment, None, 10),
341
'account.bank_receipt' : (_get_bank_receipt, None, 10),
343
, method=True, readonly=True),
346
def button_unassign_voucher(self, cr, uid, ids, context={}):
348
if not self._unassign_voucher(cr, uid, id):
353
def _create_account_voucher(self, cr, uid, id):
354
obj_account_voucher = self.pool.get('account.voucher')
355
obj_detail_voucher = self.pool.get('account.voucher.line')
357
detail = self.browse(cr, uid, [id])[0]
359
if detail.account_voucher_id:
362
dict_voucher = self._prepare_voucher_header(cr, uid, id)
364
account_voucher_id = obj_account_voucher.create(cr, uid, dict_voucher)
366
dict_detail = self._prepare_voucher_detail(cr, uid, id, account_voucher_id)
368
detail_id = obj_detail_voucher.create(cr, uid, dict_detail)
370
self.write(cr, uid, [id], {'account_voucher_id' : account_voucher_id})
375
def _prepare_voucher_header(self, cr, uid, id):
376
obj_data = self.pool.get('ir.model.data')
378
detail = self.browse(cr, uid, [id])[0]
379
header = detail.import_bank_statement_id
381
if detail.transaction_type == 'dr':
382
account_id = header.journal_id.default_debit_account_id.id
383
voucher_type = 'receipt'
384
voucher_type_id = obj_data.get_object_reference(cr, uid, 'ar_account', 'data_voucherType_bankReceive')[1]
386
account_id = header.journal_id.default_credit_account_id.id
387
voucher_type = 'payment'
388
voucher_type_id = obj_data.get_object_reference(cr, uid, 'ar_account', 'data_voucherType_bankPayment')[1]
393
'name' : detail.name,
394
'date' : detail.date,
395
'period_id' : header.period_id.id, #TODO
396
'journal_id' : header.journal_id.id,
397
'company_id' : header.company_id.id, #TODO,
398
'account_id' : account_id, #TODO,
399
'type' : voucher_type, #TODO,
400
'voucher_type_id' : voucher_type_id, #TODO
401
'partner_id' : False,
402
'payment_method' : 'bank_transfer',
403
'amount' : abs(detail.amount), #TODO
408
def _prepare_voucher_detail(self, cr, uid, id, voucher_id):
409
detail = self.browse(cr, uid, [id])[0]
411
if detail.transaction_type == 'dr':
412
transaction_type = 'cr'
414
transaction_type = 'dr'
417
'voucher_id' : voucher_id,
418
'name' : detail.name,
419
'type' : transaction_type,
420
'partner_id' : False,
421
'account_id' : detail.import_bank_statement_id.temporary_account_id.id,
422
'amount' : abs(detail.amount), #TODO
427
def _unassign_voucher(self, cr, uid, id):
428
detail = self.browse(cr, uid, [id])[0]
430
if not detail.account_voucher_id:
431
raise osv.except_osv(_('Warning!'),_('No voucher assigned'))
434
if detail.account_voucher_id.state != 'cancel':
435
raise osv.except_osv(_('Warning!'),_('Please cancel the voucher first'))
438
self.write(cr, uid, [id], {'account_voucher_id' : False})
442
import_bank_statement_detail()