2010-06-22 11:05:43 +00:00
# -*- encoding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved
# $Id$
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import time
import base64
2010-08-16 11:44:46 +00:00
from osv import fields , osv
2010-06-23 07:48:35 +00:00
from tools . translate import _
2010-06-22 11:05:43 +00:00
def str2date ( date_str ) :
2010-06-23 09:03:29 +00:00
return time . strftime ( " % y/ % m/ %d " , time . strptime ( date_str , " %d % m % y " ) )
2010-06-22 11:05:43 +00:00
def str2float ( str ) :
try :
return float ( str )
except :
return 0.0
def list2float ( lst ) :
try :
return str2float ( ( lambda s : s [ : - 3 ] + ' . ' + s [ - 3 : ] ) ( lst ) )
except :
return 0.0
2010-06-23 09:03:29 +00:00
2010-06-22 11:05:43 +00:00
class account_coda_import ( osv . osv_memory ) :
_name = ' account.coda.import '
_description = ' Account Coda Import '
_columns = {
' journal_id ' : fields . many2one ( ' account.journal ' , ' Bank Journal ' , required = True ) ,
2010-06-23 09:03:29 +00:00
' def_payable ' : fields . many2one ( ' account.account ' , ' Default Payable Account ' , domain = [ ( ' type ' , ' = ' , ' payable ' ) ] , required = True , help = ' Set here the payable account that will be used, by default, if the partner is not found ' ) ,
' def_receivable ' : fields . many2one ( ' account.account ' , ' Default Receivable Account ' , domain = [ ( ' type ' , ' = ' , ' receivable ' ) ] , required = True , help = ' Set here the receivable account that will be used, by default, if the partner is not found ' , ) ,
' awaiting_account ' : fields . many2one ( ' account.account ' , ' Default Account for Unrecognized Movement ' , required = True , 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 ' , ) ,
' coda ' : fields . binary ( ' Coda File ' , required = True ) ,
' note ' : fields . text ( ' Log ' ) ,
2010-06-22 11:05:43 +00:00
}
2010-08-16 11:44:46 +00:00
2010-07-06 14:58:03 +00:00
def coda_parsing ( self , cr , uid , ids , context = None ) :
2010-06-23 09:03:29 +00:00
2010-06-22 11:05:43 +00:00
journal_obj = self . pool . get ( ' account.journal ' )
2010-06-23 09:03:29 +00:00
account_period_obj = self . pool . get ( ' account.period ' )
partner_bank_obj = self . pool . get ( ' res.partner.bank ' )
bank_statement_obj = self . pool . get ( ' account.bank.statement ' )
move_line_obj = self . pool . get ( ' account.move.line ' )
bank_statement_line_obj = self . pool . get ( ' account.bank.statement.line ' )
statement_reconcile_obj = self . pool . get ( ' account.bank.statement.reconcile ' )
account_coda_obj = self . pool . get ( ' account.coda ' )
2010-06-22 11:05:43 +00:00
mod_obj = self . pool . get ( ' ir.model.data ' )
2010-08-16 11:44:46 +00:00
2010-07-06 14:58:03 +00:00
if not context :
context = { }
2010-08-16 11:44:46 +00:00
2010-06-22 11:05:43 +00:00
data = self . read ( cr , uid , ids ) [ 0 ]
2010-06-23 09:03:29 +00:00
2010-06-22 11:05:43 +00:00
codafile = data [ ' coda ' ]
journal_code = journal_obj . browse ( cr , uid , data [ ' journal_id ' ] , context ) . code
2010-06-23 09:03:29 +00:00
2010-06-22 11:05:43 +00:00
period = account_period_obj . find ( cr , uid , context = context ) [ 0 ]
def_pay_acc = data [ ' def_payable ' ]
def_rec_acc = data [ ' def_receivable ' ]
2010-06-23 09:03:29 +00:00
2010-06-22 11:05:43 +00:00
str_log = " "
err_log = " Errors: \n ------ \n "
nb_err = 0
std_log = ' '
str_log1 = " Coda File is Imported : "
str_not = ' '
str_not1 = ' '
2010-06-23 09:03:29 +00:00
2010-08-16 11:44:46 +00:00
bank_statements = [ ]
2010-06-22 11:05:43 +00:00
bank_statement = { }
recordlist = base64 . decodestring ( codafile ) . split ( ' \n ' )
recordlist . pop ( )
for line in recordlist :
if line [ 0 ] == ' 0 ' :
# header data
2010-06-23 09:03:29 +00:00
2010-06-22 11:05:43 +00:00
bank_statement [ " bank_statement_line " ] = { }
bank_statement_lines = { }
bank_statement [ ' date ' ] = str2date ( line [ 5 : 11 ] )
bank_statement [ ' journal_id ' ] = data [ ' journal_id ' ]
2010-06-23 09:03:29 +00:00
period_id = account_period_obj . 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 " ) ) ) ] )
2010-06-22 11:05:43 +00:00
bank_statement [ ' period_id ' ] = period_id and period_id [ 0 ] or False
bank_statement [ ' state ' ] = ' draft '
elif line [ 0 ] == ' 1 ' :
# old balance data
bal_start = list2float ( line [ 43 : 58 ] )
if line [ 42 ] == ' 1 ' :
bal_start = - bal_start
bank_statement [ " balance_start " ] = bal_start
bank_statement [ " acc_number " ] = line [ 5 : 17 ]
bank_statement [ " acc_holder " ] = line [ 64 : 90 ]
bank_statement [ ' name ' ] = journal_code + ' ' + str ( line [ 2 : 5 ] )
2010-06-23 09:03:29 +00:00
2010-06-22 11:05:43 +00:00
elif line [ 0 ] == ' 2 ' :
# movement data record 2
if line [ 1 ] == ' 1 ' :
# movement data record 2.1
if bank_statement_lines . has_key ( line [ 2 : 6 ] ) :
continue
st_line = { }
st_line [ ' extra_note ' ] = ' '
st_line [ ' statement_id ' ] = 0
st_line [ ' ref ' ] = line [ 2 : 10 ]
2010-06-23 09:03:29 +00:00
st_line [ ' date ' ] = time . strftime ( ' % Y- % m- %d ' , time . strptime ( str2date ( line [ 115 : 121 ] ) , " % y/ % m/ %d " ) ) ,
2010-06-22 11:05:43 +00:00
st_line_amt = list2float ( line [ 32 : 47 ] )
2010-06-23 09:03:29 +00:00
2010-06-22 11:05:43 +00:00
if line [ 61 ] == ' 1 ' :
st_line [ ' toreconcile ' ] = True
st_line [ ' name ' ] = line [ 65 : 77 ]
else :
st_line [ ' toreconcile ' ] = False
st_line [ ' name ' ] = line [ 62 : 115 ]
2010-06-23 09:03:29 +00:00
2010-06-22 11:05:43 +00:00
st_line [ ' free_comm ' ] = st_line [ ' name ' ]
2010-06-23 09:03:29 +00:00
st_line [ ' val_date ' ] = time . strftime ( ' % Y- % m- %d ' , time . strptime ( str2date ( line [ 47 : 53 ] ) , " % y/ % m/ %d " ) ) ,
st_line [ ' entry_date ' ] = time . strftime ( ' % Y- % m- %d ' , time . strptime ( str2date ( line [ 115 : 121 ] ) , " % y/ % m/ %d " ) ) ,
2010-06-22 11:05:43 +00:00
st_line [ ' partner_id ' ] = 0
if line [ 31 ] == ' 1 ' :
st_line_amt = - st_line_amt
st_line [ ' account_id ' ] = def_pay_acc
else :
st_line [ ' account_id ' ] = def_rec_acc
st_line [ ' amount ' ] = st_line_amt
bank_statement_lines [ line [ 2 : 6 ] ] = st_line
bank_statement [ " bank_statement_line " ] = bank_statement_lines
elif line [ 1 ] == ' 2 ' :
st_line_name = line [ 2 : 6 ]
bank_statement_lines [ st_line_name ] . update ( { ' account_id ' : data [ ' awaiting_account ' ] } )
2010-06-23 09:03:29 +00:00
2010-06-22 11:05:43 +00:00
elif line [ 1 ] == ' 3 ' :
# movement data record 3.1
st_line_name = line [ 2 : 6 ]
st_line_partner_acc = str ( line [ 10 : 47 ] ) . strip ( )
cntry_number = line [ 10 : 47 ] . strip ( )
contry_name = line [ 47 : 125 ] . strip ( )
2010-06-23 09:03:29 +00:00
bank_ids = partner_bank_obj . search ( cr , uid , [ ( ' acc_number ' , ' = ' , st_line_partner_acc ) ] )
2010-06-22 11:05:43 +00:00
bank_statement_lines [ st_line_name ] . update ( { ' cntry_number ' : cntry_number , ' contry_name ' : contry_name } )
if bank_ids :
bank = partner_bank_obj . browse ( cr , uid , bank_ids [ 0 ] , context )
if line and bank . partner_id :
bank_statement_lines [ st_line_name ] . update ( { ' partner_id ' : bank . partner_id . id } )
if bank_statement_lines [ st_line_name ] [ ' amount ' ] < 0 :
bank_statement_lines [ st_line_name ] . update ( { ' account_id ' : bank . partner_id . property_account_payable . id } )
else :
bank_statement_lines [ st_line_name ] . update ( { ' account_id ' : bank . partner_id . property_account_receivable . id } )
else :
nb_err + = 1
2010-06-23 09:03:29 +00:00
err_log + = _ ( ' The bank account %s is not defined for the partner %s . \n ' ) % ( cntry_number , contry_name )
2010-06-22 11:05:43 +00:00
bank_statement_lines [ st_line_name ] . update ( { ' account_id ' : data [ ' awaiting_account ' ] } )
2010-06-23 09:03:29 +00:00
2010-06-22 11:05:43 +00:00
bank_statement [ " bank_statement_line " ] = bank_statement_lines
elif line [ 0 ] == ' 3 ' :
if line [ 1 ] == ' 1 ' :
st_line_name = line [ 2 : 6 ]
bank_statement_lines [ st_line_name ] [ ' extra_note ' ] + = ' \n ' + line [ 40 : 113 ]
elif line [ 1 ] == ' 2 ' :
st_line_name = line [ 2 : 6 ]
bank_statement_lines [ st_line_name ] [ ' extra_note ' ] + = ' \n ' + line [ 10 : 115 ]
elif line [ 1 ] == ' 3 ' :
st_line_name = line [ 2 : 6 ]
bank_statement_lines [ st_line_name ] [ ' extra_note ' ] + = ' \n ' + line [ 10 : 100 ]
elif line [ 0 ] == ' 8 ' :
# new balance record
bal_end = list2float ( line [ 42 : 57 ] )
if line [ 41 ] == ' 1 ' :
bal_end = - bal_end
bank_statement [ " balance_end_real " ] = bal_end
2010-06-23 09:03:29 +00:00
2010-06-22 11:05:43 +00:00
elif line [ 0 ] == ' 9 ' :
# footer record
2010-06-23 09:03:29 +00:00
2010-06-22 11:05:43 +00:00
bank_statements . append ( bank_statement )
#end for
bkst_list = [ ]
for statement in bank_statements :
try :
2010-06-23 09:03:29 +00:00
bk_st_id = bank_statement_obj . create ( cr , uid , {
2010-06-22 11:05:43 +00:00
' journal_id ' : statement [ ' journal_id ' ] ,
2010-08-16 11:44:46 +00:00
' date ' : time . strftime ( ' % Y- % m- %d ' , time . strptime ( statement [ ' date ' ] , " % y/ % m/ %d " ) ) ,
' period_id ' : statement [ ' period_id ' ] or period ,
2010-06-22 11:05:43 +00:00
' balance_start ' : statement [ " balance_start " ] ,
' balance_end_real ' : statement [ " balance_end_real " ] ,
' state ' : ' draft ' ,
' name ' : statement [ ' name ' ] ,
} )
lines = statement [ " bank_statement_line " ]
for value in lines :
line = lines [ value ]
reconcile_id = False
if line [ ' toreconcile ' ] :
2010-07-21 18:37:19 +00:00
name = line [ ' name ' ] [ : 3 ] + ' / ' + line [ ' name ' ] [ 3 : 7 ] + ' / ' + line [ ' name ' ] [ 7 : ]
2010-08-16 11:44:46 +00:00
rec_id = pool . get ( ' account.move.line ' ) . search ( cr , uid , [ ( ' name ' , ' = ' , name ) , ( ' reconcile_id ' , ' = ' , False ) , ( ' account_id.reconcile ' , ' = ' , True ) ] )
2010-06-22 11:05:43 +00:00
if rec_id :
reconcile_id = statement_reconcile_obj . create ( cr , uid , {
' line_ids ' : [ ( 6 , 0 , rec_id ) ]
} , context = context )
2010-08-12 10:25:00 +00:00
mv = pool . get ( ' account.move.line ' ) . browse ( cr , uid , rec_id [ 0 ] , context = context )
if mv . partner_id :
line [ ' partner_id ' ] = mv . partner_id . id
if line [ ' amount ' ] < 0 :
line [ ' account_id ' ] = mv . partner_id . property_account_payable . id
else :
line [ ' account_id ' ] = mv . partner_id . property_account_receivable . id
2010-06-22 11:05:43 +00:00
str_not1 = ' '
if line . has_key ( ' contry_name ' ) and line . has_key ( ' cntry_number ' ) :
2010-06-23 09:03:29 +00:00
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 ] )
id = bank_statement_line_obj . create ( cr , uid , {
2010-06-22 11:05:43 +00:00
' name ' : line [ ' name ' ] ,
' date ' : line [ ' date ' ] ,
' amount ' : line [ ' amount ' ] ,
' partner_id ' : line [ ' partner_id ' ] or 0 ,
' account_id ' : line [ ' account_id ' ] ,
' statement_id ' : bk_st_id ,
' reconcile_id ' : reconcile_id ,
' note ' : str_not1 ,
' ref ' : line [ ' ref ' ] ,
} )
2010-06-23 09:03:29 +00:00
str_not = " \n \n Account Number: %s \n Account Holder Name: %s " % ( statement [ " acc_number " ] , statement [ " acc_holder " ] )
2010-06-22 11:05:43 +00:00
std_log + = " \n Statement : %s , Date : %s , Starting Balance : %.2f , Ending Balance : %.2f \n " \
% ( statement [ ' name ' ] , statement [ ' date ' ] , float ( statement [ " balance_start " ] ) , float ( statement [ " balance_end_real " ] ) )
bkst_list . append ( bk_st_id )
2010-06-23 09:03:29 +00:00
2010-06-22 11:05:43 +00:00
except osv . except_osv , e :
cr . rollback ( )
2010-08-16 11:44:46 +00:00
nb_err + = 1
2010-06-22 11:05:43 +00:00
err_log + = ' \n Application Error : ' + str ( e )
raise # REMOVEME
2010-06-23 09:03:29 +00:00
2010-06-22 11:05:43 +00:00
except Exception , e :
cr . rollback ( )
2010-08-16 11:44:46 +00:00
nb_err + = 1
2010-06-22 11:05:43 +00:00
err_log + = ' \n System Error : ' + str ( e )
raise # REMOVEME
except :
cr . rollback ( )
nb_err + = 1
err_log + = ' \n Unknown Error '
raise
err_log + = ' \n \n Number of statements : ' + str ( len ( bkst_list ) )
err_log + = ' \n Number of error : ' + str ( nb_err ) + ' \n '
2010-06-23 09:03:29 +00:00
2010-06-22 11:05:43 +00:00
account_coda_obj . create ( cr , uid , {
2010-08-16 11:44:46 +00:00
' name ' : codafile ,
2010-06-22 11:05:43 +00:00
' statement_ids ' : [ ( 6 , 0 , bkst_list , ) ] ,
2010-08-16 11:44:46 +00:00
' note ' : str_log1 + str_not + std_log + err_log ,
' journal_id ' : data [ ' journal_id ' ] ,
' date ' : time . strftime ( " % Y- % m- %d " ) ,
' user_id ' : uid ,
} )
2010-06-23 09:03:29 +00:00
test = ' '
2010-08-16 11:44:46 +00:00
test = str_log1 + std_log + err_log
self . write ( cr , uid , ids , { ' note ' : test } , context = context )
extraction = { ' statment_ids ' : bkst_list }
context . update ( { ' statment_ids ' : bkst_list } )
2010-06-23 09:03:29 +00:00
model_data_ids = mod_obj . search ( cr , uid , [ ( ' model ' , ' = ' , ' ir.ui.view ' ) , ( ' name ' , ' = ' , ' account_coda_note_view ' ) ] , context = context )
2010-06-22 11:05:43 +00:00
resource_id = mod_obj . read ( cr , uid , model_data_ids , fields = [ ' res_id ' ] , context = context ) [ 0 ] [ ' res_id ' ]
2010-08-16 11:44:46 +00:00
2010-06-22 11:05:43 +00:00
return {
2010-08-16 11:44:46 +00:00
' name ' : _ ( ' Result ' ) ,
' res_id ' : ids [ 0 ] ,
' view_type ' : ' form ' ,
' view_mode ' : ' form ' ,
' res_model ' : ' account.coda.import ' ,
' view_id ' : False ,
' target ' : ' new ' ,
' views ' : [ ( resource_id , ' form ' ) ] ,
' context ' : context ,
' type ' : ' ir.actions.act_window ' ,
2010-06-22 11:05:43 +00:00
}
2010-08-16 11:44:46 +00:00
2010-07-06 14:58:03 +00:00
def action_open_window ( self , cr , uid , data , context = None ) :
if not context :
cotext = { }
2010-06-22 11:05:43 +00:00
return {
2010-06-23 09:03:29 +00:00
' domain ' : " [( ' id ' , ' in ' , %s )] " % ( context . get ( ' statment_ids ' , False ) ) ,
2010-06-22 11:05:43 +00:00
' name ' : ' Statement ' ,
' view_type ' : ' form ' ,
' view_mode ' : ' tree,form ' ,
' res_model ' : ' account.bank.statement ' ,
' view_id ' : False ,
' type ' : ' ir.actions.act_window ' ,
}
2010-08-16 11:44:46 +00:00
2010-06-23 07:19:45 +00:00
account_coda_import ( )
2010-06-22 11:05:43 +00:00
2010-08-16 11:44:46 +00:00
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: