1 # -*- encoding: utf-8 -*-
2 ##############################################################################
4 # OpenERP, Open Source Management Solution
5 # Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
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.
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.
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/>.
20 ##############################################################################
29 from tools.translate import _
31 codawiz_form = """<?xml version="1.0"?>
32 <form string="Import Coda Statement">
33 <separator colspan="4" string="Select your bank journal :" />
34 <field name="journal_id" colspan="1" domain="[('type','=','cash')]" />
36 <field name="def_payable" /> <field name="def_receivable" />
38 <field name="awaiting_account" />
39 <separator string="Clic on 'New' to select your file :" colspan="4"/>
46 'string':'Bank Journal',
48 'relation':'account.journal',
58 'string' : 'Default Payable Account',
60 'relation': 'account.account',
62 'domain':[('type','=','payable')],
63 'help': 'Set here the payable account that will be used, by default, if the partner is not found',
66 'string' : 'Default receivable Account',
68 'relation': 'account.account',
70 'domain':[('type','=','receivable')],
71 'help': 'Set here the receivable account that will be used, by default, if the partner is not found',
73 'awaiting_account' : {
74 'string' : 'Default Account for Unrecognized Movement',
76 'relation': 'account.account',
78 'help': 'Set here the default account that will be used, if the partner is found but does not have the bank account , or if he is domiciled',
84 result_form = """<?xml version="1.0"?>
85 <form string="Import Coda Statement">
86 <separator colspan="4" string="Results :" />
87 <field name="note" colspan="4" nolabel="1" width="500"/>
93 'note' : {'string':'Log','type':'text'}
98 def _coda_parsing(self, cr, uid, data, context):
99 pool = pooler.get_pool(cr.dbname)
100 codafile = data['form']['coda']
101 journal_code = pool.get('account.journal').browse(cr, uid, data['form']['journal_id'], context).code
102 def_pay_acc = data['form']['def_payable']
103 def_rec_acc = data['form']['def_receivable']
106 err_log = "Errors:\n------\n"
109 str_log1 = "Coda File is Imported : "
114 recordlist = base64.decodestring(codafile).split('\n')
116 for line in recordlist:
120 bank_statement["bank_statement_line"]={}
121 bank_statement_lines = {}
122 bank_statement['date'] = str2date(line[5:11])
123 bank_statement['journal_id']=data['form']['journal_id']
124 period_id = pool.get('account.period').search(cr,uid,[('date_start','<=',time.strftime('%Y-%m-%d',time.strptime(bank_statement['date'],"%y/%m/%d"))),('date_stop','>=',time.strftime('%Y-%m-%d',time.strptime(bank_statement['date'],"%y/%m/%d")))])
125 bank_statement['period_id'] = period_id[0]
126 bank_statement['state']='draft'
129 bal_start = list2float(line[43:58])
131 bal_start = - bal_start
132 bank_statement["balance_start"]= bal_start
133 bank_statement["acc_number"]=line[5:17]
134 bank_statement["acc_holder"]=line[64:90]
135 bank_statement['name'] = journal_code + ' ' + str(line[2:5])
138 # movement data record 2
140 # movement data record 2.1
141 if bank_statement_lines.has_key(line[2:6]):
144 st_line['extra_note'] = ''
145 st_line['statement_id']=0
146 st_line['ref'] = line[2:10]
147 st_line['date'] = time.strftime('%Y-%m-%d',time.strptime(str2date(line[115:121]),"%y/%m/%d")),
148 st_line_amt = list2float(line[32:47])
151 st_line['toreconcile'] = True
152 st_line['name']=line[65:77]
154 st_line['toreconcile'] = False
155 st_line['name']=line[62:115]
157 st_line['free_comm'] = st_line['name']
158 st_line['val_date']=time.strftime('%Y-%m-%d',time.strptime(str2date(line[47:53]),"%y/%m/%d")),
159 st_line['entry_date']=time.strftime('%Y-%m-%d',time.strptime(str2date(line[115:121]),"%y/%m/%d")),
160 st_line['partner_id']=0
162 st_line_amt = - st_line_amt
163 st_line['account_id'] = def_pay_acc
165 st_line['account_id'] = def_rec_acc
166 st_line['amount'] = st_line_amt
167 bank_statement_lines[line[2:6]]=st_line
168 bank_statement["bank_statement_line"]=bank_statement_lines
170 st_line_name = line[2:6]
171 bank_statement_lines[st_line_name].update({'account_id': data['form']['awaiting_account']})
174 # movement data record 3.1
175 st_line_name = line[2:6]
176 st_line_partner_acc = str(line[10:47]).strip()
177 cntry_number=line[10:47].strip()
178 contry_name=line[47:125].strip()
179 bank_ids = pool.get('res.partner.bank').search(cr,uid,[('acc_number','=',st_line_partner_acc)])
180 bank_statement_lines[st_line_name].update({'cntry_number': cntry_number, 'contry_name': contry_name})
182 bank = pool.get('res.partner.bank').browse(cr,uid,bank_ids[0],context)
183 if line and bank.partner_id:
184 bank_statement_lines[st_line_name].update({'partner_id': bank.partner_id.id})
185 if bank_statement_lines[st_line_name]['amount'] < 0 :
186 bank_statement_lines[st_line_name].update({'account_id': bank.partner_id.property_account_payable.id})
188 bank_statement_lines[st_line_name].update({'account_id': bank.partner_id.property_account_receivable.id})
191 err_log += _('The bank account %s is not defined for the partner %s.\n')%(cntry_number,contry_name)
192 bank_statement_lines[st_line_name].update({'account_id': data['form']['awaiting_account']})
194 bank_statement["bank_statement_line"]=bank_statement_lines
197 st_line_name = line[2:6]
198 bank_statement_lines[st_line_name]['extra_note'] += '\n' + line[40:113]
200 st_line_name = line[2:6]
201 bank_statement_lines[st_line_name]['extra_note'] += '\n' + line[10:115]
203 st_line_name = line[2:6]
204 bank_statement_lines[st_line_name]['extra_note'] += '\n' + line[10:100]
207 bal_end = list2float(line[42:57])
210 bank_statement["balance_end_real"]= bal_end
214 bank_statements.append(bank_statement)
217 for statement in bank_statements:
219 bk_st_id = pool.get('account.bank.statement').create(cr,uid,{
220 'journal_id': statement['journal_id'],
221 'date':time.strftime('%Y-%m-%d',time.strptime(statement['date'],"%y/%m/%d")),
222 'period_id':statement['period_id'],
223 'balance_start': statement["balance_start"],
224 'balance_end_real': statement["balance_end_real"],
226 'name': statement['name'],
228 lines=statement["bank_statement_line"]
232 if line['toreconcile']:
233 rec_id = pool.get('account.move.line').search(cr, uid, [('name','=',line['name']),('reconcile_id','=',False),('account_id.reconcile','=',True)])
235 reconcile_id = pool.get('account.bank.statement.reconcile').create(cr, uid, {
236 'line_ids': [(6, 0, rec_id)]
239 if line.has_key('contry_name') and line.has_key('cntry_number'):
240 str_not1="Partner name:%s \n Partner Account Number:%s \n Communication:%s \n Value Date:%s \n Entry Date:%s \n"%(line["contry_name"],line["cntry_number"],line["free_comm"]+line['extra_note'],line["val_date"][0],line["entry_date"][0])
241 id=pool.get('account.bank.statement.line').create(cr,uid,{
243 'date': line['date'],
244 'amount': line['amount'],
245 'partner_id':line['partner_id'] or 0,
246 'account_id':line['account_id'],
247 'statement_id': bk_st_id,
248 'reconcile_id': reconcile_id,
253 str_not= "\n \n Account Number: %s \n Account Holder Name: %s " %(statement["acc_number"],statement["acc_holder"])
254 std_log += "\nStatement : %s , Date : %s, Starting Balance : %.2f , Ending Balance : %.2f \n"\
255 %(statement['name'], statement['date'], float(statement["balance_start"]), float(statement["balance_end_real"]))
256 bkst_list.append(bk_st_id)
258 except osv.except_osv, e:
261 err_log += '\n Application Error : ' + str(e)
267 err_log += '\n System Error : '+str(e)
272 err_log += '\n Unknown Error'
274 err_log += '\n\nNumber of statements : '+ str(len(bkst_list))
275 err_log += '\nNumber of error :'+ str(nb_err) +'\n'
277 pool.get('account.coda').create(cr, uid,{
279 'statement_ids': [(6, 0, bkst_list,)],
280 'note':str_log1+str_not+std_log+err_log,
281 'journal_id':data['form']['journal_id'],
282 'date':time.strftime("%Y-%m-%d"),
286 return {'note':str_log1 + std_log + err_log ,'journal_id': data['form']['journal_id'], 'coda': data['form']['coda'],'statment_ids':bkst_list}
289 def str2date(date_str):
290 return time.strftime("%y/%m/%d",time.strptime(date_str,"%d%m%y"))
300 return str2float((lambda s : s[:-3] + '.' + s[-3:])(lst))
304 class coda_import(wizard.interface):
305 def _action_open_window(self, cr, uid, data, context):
308 'domain':"[('id','in',%s)]"%(form['statment_ids']),
311 'view_mode': 'tree,form',
312 'res_model': 'account.bank.statement',
314 'type': 'ir.actions.act_window',
319 'result' : {'type' : 'form',
320 'arch' : codawiz_form,
321 'fields' : codawiz_fields,
322 'state' : [('end', '_Close'),('extraction', '_Ok') ]}
325 'actions' : [_coda_parsing],
326 'result' : {'type' : 'form',
327 'arch' : result_form,
328 'fields' : result_fields,
329 'state' : [('end', '_Close'),('open', '_Open Statement')]}
333 'result': {'type': 'action', 'action': _action_open_window, 'state': 'end'}
338 coda_import("account.coda_import")
339 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: