[IMP]Parser algorithm improvement

bzr revid: dle@openerp.com-20121205170650-a6ydpo9qa14d2c55
This commit is contained in:
dle@openerp.com
2012-12-05 18:06:50 +01:00
parent 0b32c75f74
commit 652f81427e
4 changed files with 659 additions and 251 deletions
+1 -1
View File
@@ -546,7 +546,7 @@ class account_bank_statement_line(osv.osv):
_name = "account.bank.statement.line"
_description = "Bank Statement Line"
_columns = {
'name': fields.char('Communication', size=256, required=True),
'name': fields.char('Communication',size=64, required=True),
'date': fields.date('Date', required=True),
'amount': fields.float('Amount', digits_compute=dp.get_precision('Account')),
'type': fields.selection([
+1 -1
View File
@@ -575,7 +575,7 @@
<tree editable="bottom" string="Statement lines">
<field name="sequence" readonly="1" invisible="1"/>
<field name="date"/>
<field name="name"/>
<field name="note"/>
<field name="ref"/>
<field name="partner_id" on_change="onchange_partner_id(partner_id)"/>
<field name="type" on_change="onchange_type(partner_id, type)"/>
@@ -973,8 +973,7 @@ class account_coda_import(osv.osv_memory):
# handling non-transactional records : line['type'] in ['information', 'communication']
if line['type'] == 'information':
if line['ref_move_detail'] == '0000':
glob_id_stack = [(0, '', 0, '')] # initialise stack with tuples (glob_lvl_flag, glob_code, glob_id, glob_name)
#Check if this line can be deleted. glob_id_stack marked as undefined here
line['globalisation_id'] = glob_id_stack[-1][2]
@@ -45,6 +45,7 @@ class account_coda_import(osv.osv_memory):
if context is None:
context = {}
if batch:
print
codafile = str(codafile)
codafilename = codafilename
else:
@@ -59,273 +60,681 @@ class account_coda_import(osv.osv_memory):
statements = []
for line in recordlist:
if not line:
continue
pass
elif line[0] == '0':
#Begin of a new Bank statement
statement = {}
statements.append(statement)
statement['error'] = False
statement['errors'] = []
statement['version'] = line[127]
if statement['version'] not in ['1', '2']:
statement['error'] = True
statement['errors'].append(('R0001', _('CODA V%s statements are not supported, please contact your bank!') % statement['version']))
continue
raise osv.except_osv(_('Error R001!'), _('CODA V%s statements are not supported, please contact your bank!') % statement['version'])
statement['globalisation_stack'] = []
statement['lines'] = []
statement['date'] = time.strftime(tools.DEFAULT_SERVER_DATE_FORMAT, time.strptime(rmspaces(line[5:11]), '%d%m%y'))
statement['separateApplication'] = rmspaces(line[83:88])
elif not statement['error']:
if line[0] == '1':
#Statement details
if statement['version'] == '1':
elif line[0] == '1':
#Statement details
if statement['version'] == '1':
statement['accountNumber'] = rmspaces(line[5:17])
statement['currency'] = rmspaces(line[18:21])
elif statement['version'] == '2':
if line[1] == '0': # Belgian bank account BBAN structure
statement['accountNumber'] = rmspaces(line[5:17])
statement['currency'] = rmspaces(line[18:21])
elif statement['version'] == '2':
if line[1] == '0': # Belgian bank account BBAN structure
statement['accountNumber'] = rmspaces(line[5:17])
statement['currency'] = rmspaces(line[18:21])
elif line[1] == '1': # foreign bank account BBAN structure
statement['error'] = True
statement['errors'].append(('R1001', _('Foreign bank accounts with BBAN structure are not supported !')))
continue
elif line[1] == '2': # Belgian bank account IBAN structure
statement['accountNumber'] = rmspaces(line[5:21])
statement['currency'] = rmspaces(line[39:42])
elif line[1] == '3': # foreign bank account IBAN structure
statement['error'] = True
statement['errors'].append(('R1002', _('Foreign bank accounts with IBAN structure are not supported !')))
continue
else: # Something else, not supported
statement['error'] = True
statement['errors'].append(('R1003', _('\nUnsupported bank account structure !')))
continue
statement['description'] = rmspaces(line[90:125])
statement['balance_start'] = float(rmspaces(line[43:58])) / 1000
statement['balance_start_date'] = time.strftime(tools.DEFAULT_SERVER_DATE_FORMAT, time.strptime(rmspaces(line[58:64]), '%d%m%y'))
statement['accountHolder'] = rmspaces(line[64:90])
statement['paperSeqNumber'] = rmspaces(line[2:5])
statement['codaSeqNumber'] = rmspaces(line[125:128])
elif line[0] == '2':
if line[1] == '1':
#New statement line
statementLine = {}
statementLine['type'] = 'general'
statementLine['ref'] = rmspaces(line[2:10])
statementLine['ref_move'] = rmspaces(line[2:6])
statementLine['ref_move_detail'] = rmspaces(line[6:10])
statementLine['sequence'] = len(statement['lines']) + 1
if statementLine['sequence'] == 1:
main_move_stack = [statementLine]
glob_lvl_stack = [0] # initialise globalisation stack
elif statementLine['ref_move_detail'] == '0000':
glob_lvl_stack = [0] # re-initialise globalisation stack
statementLine['transactionRef'] = rmspaces(line[10:31])
statementLine['debit'] = line[31] # 0 = Credit, 1 = Debit
statementLine['amount'] = float(rmspaces(line[32:47])) / 1000
if statementLine['debit'] == '1':
statementLine['amount'] = - statementLine['amount']
statementLine['transactionType'] = line[53]
#TODO Handling severals transactions types
statementLine['transactionDate'] = time.strftime(tools.DEFAULT_SERVER_DATE_FORMAT, time.strptime(rmspaces(line[47:53]), '%d%m%y'))
statementLine['transactionFamily'] = rmspaces(line[54:56])
#TODO Handling severals transactions Family
statementLine['transactionCode'] = rmspaces(line[56:58])
#TODO Handling severals transactions code
statementLine['transactionCategory'] = rmspaces(line[58:61])
#TODO Handling severals transactions category
statementLine['communication'] = rmspaces(line[65:115])
#TODO Handling structured communication
statementLine['entryDate'] = rmspaces(line[115:121])
glob_lvl_flag = int(line[124])
if glob_lvl_flag > 0:
if glob_lvl_stack[-1] == glob_lvl_flag:
statementLine['glob_lvl_flag'] = glob_lvl_flag
statementLine['amount'] = statementLine['amount']
glob_lvl_stack.pop()
else:
glob_lvl_stack.append(glob_lvl_flag)
statementLine['type'] = 'globalisation'
statementLine['glob_lvl_flag'] = glob_lvl_flag
statementLine['globalisation_amount'] = statementLine['amount']
del statementLine['amount']
# The 'globalisation' concept can also be implemented without the globalisation level flag.
# This is e.g. used by Europabank to give the details of Card Payments.
if statementLine['ref_move'] == main_move_stack[-1]['ref_move']:
if statementLine['ref_move_detail'] == '9999':
statement['error'] = True
statement['errors'].append(('R1003', _('\nUnsupported bank account structure !')))
continue
elif statementLine['ref_move_detail'] != '0000':
if glob_lvl_stack[-1] == 0:
# promote associated move record into a globalisation
glob_lvl_flag = 1
glob_lvl_stack.append(glob_lvl_flag)
main_st_line_seq = main_move_stack[-1]['sequence']
to_promote = statement['lines'][main_st_line_seq]
if not main_move_stack[-1].get('detail_cnt'):
to_promote.update({
'type': 'globalisation',
'glob_lvl_flag': glob_lvl_flag,
'globalisation_amount': main_move_stack[-1]['amount'],
'amount': False,
'account_id': 0,
})
main_move_stack[-1]['promoted'] = True
if not main_move_stack[-1].get('detail_cnt'):
main_move_stack[-1]['detail_cnt'] = 1
else:
main_move_stack[-1]['detail_cnt'] += 1
statement['lines'].append(statementLine)
if statementLine['ref_move'] != main_move_stack[-1]['ref_move']:
if main_move_stack[-1].get('detail_cnt') and main_move_stack[-1].get('promoted'):
# add closing globalisation level on previous detail record in order to correctly close
# moves that have been 'promoted' to globalisation
closeglobalise = statement['lines'][len(statement['lines']) - 1]
closeglobalise.update({
'glob_lvl_flag': main_move_stack[-1]['glob_lvl_flag'],
})
else:
# demote record with globalisation code from 'globalisation' to 'general' when no detail records
# the same logic is repeated on the New Balance Record ('8 Record') in order to cope with CODA files
# containing a single 2.1 record that needs to be 'demoted'.
if main_move_stack[-1]['type'] == 'globalisation' and not main_move_stack[-1].get('detail_cnt'):
# demote record with globalisation code from 'globalisation' to 'general' when no detail records
main_st_line_seq = main_move_stack[-1]['sequence']
to_demote = statement['lines'][main_st_line_seq]
to_demote.update({
'type': 'general',
'glob_lvl_flag': 0,
'globalisation_amount': False,
'amount': main_move_stack[-1]['globalisation_amount'],
})
main_move_stack.pop()
main_move_stack.append(statementLine)
elif line[1] == '2':
if statement['lines'][-1]['ref'][0:4] != line[2:6]:
statement['error'] = True
statement['errors'].append(('R2004', _('CODA parsing error on movement data record 2.2, seq nr %s! Please report this issue via your OpenERP support channel.') % line[2:10]))
continue
statement['lines'][-1]['communication'] += rmspaces(line[10:63])
statement['lines'][-1]['payment_reference'] = rmspaces(line[63:98])
statement['lines'][-1]['counterparty_bic'] = rmspaces(line[98:109])
elif line[1] == '3':
if statement['lines'][-1]['ref'][0:4] != line[2:6]:
statement['error'] = True
statement['errors'].append(('R2004', _('CODA parsing error on movement data record 2.2, seq nr %s! Please report this issue via your OpenERP support channel.') % line[2:10]))
continue
if statement['version'] == '1':
statement['lines'][-1]['counterpartyNumber'] = rmspaces(line[10:22])
statement['lines'][-1]['counterpartyName'] = rmspaces(line[47:125])
statement['lines'][-1]['counterpartyCurrency'] = ''
elif line[1] == '1': # foreign bank account BBAN structure
raise osv.except_osv(_('Error R1001!'), _('Foreign bank accounts with BBAN structure are not supported !'))
elif line[1] == '2': # Belgian bank account IBAN structure
statement['accountNumber'] = rmspaces(line[5:21])
statement['currency'] = rmspaces(line[39:42])
elif line[1] == '3': # foreign bank account IBAN structure
raise osv.except_osv(_('Error R1002!'), _('Foreign bank accounts with IBAN structure are not supported !'))
else: # Something else, not supported
raise osv.except_osv(_('Error R1003!'), _('\nUnsupported bank account structure !'))
statement['description'] = rmspaces(line[90:125])
statement['balance_start'] = float(rmspaces(line[43:58])) / 1000
statement['balance_start_date'] = time.strftime(tools.DEFAULT_SERVER_DATE_FORMAT, time.strptime(rmspaces(line[58:64]), '%d%m%y'))
statement['accountHolder'] = rmspaces(line[64:90])
statement['paperSeqNumber'] = rmspaces(line[2:5])
statement['codaSeqNumber'] = rmspaces(line[125:128])
elif line[0] == '2':
if line[1] == '1':
#New statement line
statementLine = {}
statementLine['type'] = 'general'
statementLine['ref'] = rmspaces(line[2:10])
statementLine['ref_move'] = rmspaces(line[2:6])
statementLine['ref_move_detail'] = rmspaces(line[6:10])
statementLine['sequence'] = len(statement['lines']) + 1
statementLine['transactionRef'] = rmspaces(line[10:31])
statementLine['debit'] = line[31] # 0 = Credit, 1 = Debit
statementLine['amount'] = float(rmspaces(line[32:47])) / 1000
if statementLine['debit'] == '1':
statementLine['amount'] = - statementLine['amount']
statementLine['transaction_type'] = line[53]
if statementLine['transaction_type'] not in transaction_types:
raise osv.except_osv(_('Error R2001!'), _('The File contains an invalid CODA Transaction Type : %s!') % statementLine['transaction_type'])
statementLine['transactionDate'] = time.strftime(tools.DEFAULT_SERVER_DATE_FORMAT, time.strptime(rmspaces(line[47:53]), '%d%m%y'))
statementLine['transaction_family'] = rmspaces(line[54:56])
#TODO Handling severals transactions Family
statementLine['transaction_code'] = rmspaces(line[56:58])
#TODO Handling severals transactions code
statementLine['transaction_category'] = rmspaces(line[58:61])
#TODO Handling severals transactions category
statementLine['communication'] = rmspaces(line[62:115])
#TODO Handling structured communication
statementLine['entryDate'] = rmspaces(line[115:121])
statementLine['type'] = 'normal'
statementLine['globalisation'] = int(line[124])
if len(statement['globalisation_stack']) > 0:
statementLine['communication'] = "\n".join([statement['globalisation_stack'][-1]['communication'], statementLine['communication']])
if statementLine['globalisation'] > 0:
if len(statement['globalisation_stack']) > 0 and statement['globalisation_stack'][-1]['globalisation'] == statementLine['globalisation']:
# Destack
statement['globalisation_stack'].pop()
else:
if line[22] == ' ':
statement['lines'][-1]['counterpartyNumber'] = rmspaces(line[10:22])
statement['lines'][-1]['counterpartyCurrency'] = rmspaces(line[23:26])
else:
statement['lines'][-1]['counterpartyNumber'] = rmspaces(line[10:44])
statement['lines'][-1]['counterpartyCurrency'] = rmspaces(line[44:47])
statement['lines'][-1]['counterpartyName'] = rmspaces(line[47:82])
statement['lines'][-1]['communication'] += rmspaces(line[82:125])
#Stack
statementLine['type'] = 'globalisation'
statement['globalisation_stack'].append(statementLine)
statement['lines'].append(statementLine)
elif line[1] == '2':
if statement['lines'][-1]['ref'][0:4] != line[2:6]:
raise osv.except_osv(_('Error R2004!'), _('CODA parsing error on movement data record 2.2, seq nr %s! Please report this issue via your OpenERP support channel.') % line[2:10])
statement['lines'][-1]['communication'] += rmspaces(line[10:63])
statement['lines'][-1]['payment_reference'] = rmspaces(line[63:98])
statement['lines'][-1]['counterparty_bic'] = rmspaces(line[98:109])
elif line[1] == '3':
if statement['lines'][-1]['ref'][0:4] != line[2:6]:
raise osv.except_osv(_('Error R2005!'), _('CODA parsing error on movement data record 2.3, seq nr %s! Please report this issue via your OpenERP support channel.') % line[2:10])
if statement['version'] == '1':
statement['lines'][-1]['counterpartyNumber'] = rmspaces(line[10:22])
statement['lines'][-1]['counterpartyName'] = rmspaces(line[47:125])
statement['lines'][-1]['counterpartyCurrency'] = ''
else:
# movement data record 2.x (x != 1,2,3)
statement['error'] = True
statement['errors'].append(('R2009', _('\nMovement data records of type 2.%s are not supported !') % line[1]))
elif line[0] == '3':
if line[1] == '1':
infoLine = {}
infoLine['entryDate'] = statement['lines'][-1]['entryDate']
infoLine['type'] = 'information'
infoLine['sequence'] = len(statement['lines']) + 1
infoLine['ref'] = rmspaces(line[2:10])
infoLine['transactionRef'] = rmspaces(line[10:31])
infoLine['transactionType'] = line[31]
infoLine['transactionFamily'] = rmspaces(line[32:34])
infoLine['transactionCode'] = rmspaces(line[34:36])
infoLine['transactioncategory'] = rmspaces(line[36:39])
infoLine['communication'] = rmspaces(line[40:113])
statement['lines'].append(infoLine)
elif line[1] == '2':
if statement['lines'][-1]['ref'] != rmspaces(line[2:10]):
statement['error'] = True
statement['errors'].append(('R3004', _('CODA parsing error on information data record 3.2, seq nr %s! Please report this issue via your OpenERP support channel.') % line[2:10]))
continue
statement['lines'][-1]['communication'] += rmspaces(line[10:100])
elif line[1] == '3':
if statement['lines'][-1]['ref'] != rmspaces(line[2:10]):
statement['error'] = True
statement['errors'].append(('R3005', _('CODA parsing error on information data record 3.3, seq nr %s! Please report this issue via your OpenERP support channel.') % line[2:10]))
continue
statement['lines'][-1]['communication'] += rmspaces(line[10:100])
elif line[0] == '4':
comm_line = {}
comm_line['type'] = 'communication'
comm_line['sequence'] = len(statement['lines']) + 1
comm_line['ref'] = rmspaces(line[2:10])
comm_line['communication'] = rmspaces(line[32:112])
statement['lines'].append(comm_line)
elif line[0] == '8':
# new balance record
last_transaction = main_move_stack[-1]
if last_transaction['type'] == 'globalisation' and not last_transaction.get('detail_cnt'):
# demote record with globalisation code from 'globalisation' to 'general' when no detail records
main_st_line_seq = main_move_stack[-1]['sequence']
to_demote = statement['lines'][main_st_line_seq]
to_demote.update({
'type': 'general',
'glob_lvl_flag': 0,
'globalisation_amount': False,
'amount': main_move_stack[-1]['globalisation_amount'],
})
# add closing globalisation level on previous detail record in order to correctly close
# moves that have been 'promoted' to globalisation
if main_move_stack[-1].get('detail_cnt') and main_move_stack[-1].get('promoted'):
closeglobalise = statement['lines'][-1]
closeglobalise.update({
'glob_lvl_flag': main_move_stack[-1]['glob_lvl_flag'],
})
statement['debit'] = line[41]
statement['paperSeqNumber'] = rmspaces(line[1:4])
statement['balance_end_real'] = float(rmspaces(line[42:57])) / 1000
statement['balance_end_realDate'] = time.strftime(tools.DEFAULT_SERVER_DATE_FORMAT, time.strptime(rmspaces(line[57:63]), '%d%m%y'))
if statement['debit'] == '1': # 1=Debit
statement['balance_end_real'] = - statement['balance_end_real']
if statement['balance_end_realDate']:
period_id = self.pool.get('account.period').search(cr, uid, [('date_start', '<=', statement['balance_end_realDate']), ('date_stop', '>=', statement['balance_end_realDate'])])
else:
period_id = self.pool.get('account.period').search(cr, uid, [('date_start', '<=', statement['date']), ('date_stop', '>=', statement['date'])])
if not period_id and len(period_id) == 0:
statement['error'] = True
statement['errors'].append(('R0002', _("The CODA Statement New Balance date doesn't fall within a defined Accounting Period! Please create the Accounting Period for date %s.") % statement['balance_end_realDate']))
continue
statement['period_id'] = period_id[0]
elif line[0] == '9':
statement['balanceMin'] = float(rmspaces(line[22:37])) / 1000
statement['balancePlus'] = float(rmspaces(line[37:52])) / 1000
if not statement['balance_end_real']:
statement['balance_end_real'] = statement['balance_start'] + statement['balancePlus'] - statement['balanceMin']
if line[22] == ' ':
statement['lines'][-1]['counterpartyNumber'] = rmspaces(line[10:22])
statement['lines'][-1]['counterpartyCurrency'] = rmspaces(line[23:26])
else:
statement['lines'][-1]['counterpartyNumber'] = rmspaces(line[10:44])
statement['lines'][-1]['counterpartyCurrency'] = rmspaces(line[44:47])
statement['lines'][-1]['counterpartyName'] = rmspaces(line[47:82])
statement['lines'][-1]['communication'] += rmspaces(line[82:125])
else:
# movement data record 2.x (x != 1,2,3)
raise osv.except_osv(_('Error R2009!'), _('\nMovement data records of type 2.%s are not supported !') % line[1])
elif line[0] == '3':
if line[1] == '1':
infoLine = {}
infoLine['entryDate'] = statement['lines'][-1]['entryDate']
infoLine['type'] = 'information'
infoLine['sequence'] = len(statement['lines']) + 1
infoLine['ref'] = rmspaces(line[2:10])
infoLine['transactionRef'] = rmspaces(line[10:31])
infoLine['transaction_type'] = line[31]
infoLine['transaction_family'] = rmspaces(line[32:34])
infoLine['transaction_code'] = rmspaces(line[34:36])
infoLine['transaction_category'] = rmspaces(line[36:39])
infoLine['communication'] = rmspaces(line[40:113])
infoLine['amount'] = 0.0
infoLine['type'] = 'information'
statement['lines'].append(infoLine)
elif line[1] == '2':
if infoLine['ref'] != rmspaces(line[2:10]):
raise osv.except_osv(_('Error R3004!'), _('CODA parsing error on information data record 3.2, seq nr %s! Please report this issue via your OpenERP support channel.') % line[2:10])
statement['lines'][-1]['communication'] += rmspaces(line[10:100])
elif line[1] == '3':
if infoLine['ref'] != rmspaces(line[2:10]):
raise osv.except_osv(_('Error R3005!'), _('CODA parsing error on information data record 3.3, seq nr %s! Please report this issue via your OpenERP support channel.') % line[2:10])
statement['lines'][-1]['communication'] += rmspaces(line[10:100])
elif line[0] == '4':
comm_line = {}
comm_line['type'] = 'communication'
comm_line['sequence'] = len(statement['lines']) + 1
comm_line['ref'] = rmspaces(line[2:10])
comm_line['communication'] = rmspaces(line[32:112])
comm_line['amount'] = 0.0
comm_line['type'] = 'communication'
statement['lines'].append(comm_line)
elif line[0] == '8':
# new balance record
statement['debit'] = line[41]
statement['paperSeqNumber'] = rmspaces(line[1:4])
statement['balance_end_real'] = float(rmspaces(line[42:57])) / 1000
statement['balance_end_realDate'] = time.strftime(tools.DEFAULT_SERVER_DATE_FORMAT, time.strptime(rmspaces(line[57:63]), '%d%m%y'))
if statement['debit'] == '1': # 1=Debit
statement['balance_end_real'] = - statement['balance_end_real']
if statement['balance_end_realDate']:
period_id = self.pool.get('account.period').search(cr, uid, [('date_start', '<=', statement['balance_end_realDate']), ('date_stop', '>=', statement['balance_end_realDate'])])
else:
period_id = self.pool.get('account.period').search(cr, uid, [('date_start', '<=', statement['date']), ('date_stop', '>=', statement['date'])])
if not period_id and len(period_id) == 0:
raise osv.except_osv(_('Error R0002!'), _("The CODA Statement New Balance date doesn't fall within a defined Accounting Period! Please create the Accounting Period for date %s.") % statement['balance_end_realDate'])
statement['period_id'] = period_id[0]
elif line[0] == '9':
statement['balanceMin'] = float(rmspaces(line[22:37])) / 1000
statement['balancePlus'] = float(rmspaces(line[37:52])) / 1000
if not statement['balance_end_real']:
statement['balance_end_real'] = statement['balance_start'] + statement['balancePlus'] - statement['balanceMin']
for i, statement in enumerate(statements):
print '---STATEMENT #' + str(i) + '---'
# print '---STATEMENT #' + str(i) + '---'
print statement
if not statement['error']:
data = {
'name': '[' + statement['date'] + ']' + statement['description'],
'date': statement['date'],
'journal_id': 18,
'period_id': statement['period_id'],
'balance_start': statement['balance_start'],
'balance_end_real': statement['balance_end_real'],
'account_id': 1
}
self.pool.get('account.bank.statement').create(cr, uid, data, context=context)
data = {
'name': '[' + statement['date'] + ']' + statement['description'],
'date': statement['date'],
'journal_id': 18,
'period_id': statement['period_id'],
'balance_start': statement['balance_start'],
'balance_end_real': statement['balance_end_real'],
'account_id': 1
}
statement['id'] = self.pool.get('account.bank.statement').create(cr, uid, data, context=context)
for line in statement['lines']:
if line['type'] == 'normal':
counterparty = []
if 'counterpartyName' in line:
counterparty.append(line['counterpartyName'])
if 'counterpartyNumber' in line:
counterparty.append(line['counterpartyNumber'])
if len(counterparty) > 0:
counterparty = '[' + ' / '.join(counterparty) + ']'
else:
counterparty = '/'
if line['transaction_type'] in transaction_types:
line['transaction_type'] = transaction_types[line['transaction_type']][1]
if line['transaction_category'] in transaction_categories:
line['transaction_category'] = transaction_categories[line['transaction_category']]
if line['transaction_family'] in transaction_codes:
transaction_family = transaction_codes[line['transaction_family']]
line['transaction_family'] = transaction_family[0]
if line['transaction_code'] in transaction_family[1]:
line['transaction_code'] = transaction_family[1][line['transaction_code']]
note = []
note.append(_('Counter Party') + ': ' + counterparty)
note.append(_('Communication') + ': ' + line['communication'])
note.append(_('Transaction type') + ': ' + line['transaction_type'])
note.append(_('Transaction family') + ': ' + line['transaction_family'])
note.append(_('Transaction code') + ': ' + line['transaction_code'])
note.append(_('Transaction category') + ': ' + line['transaction_category'])
try:
if 'counterpartyNumber' in line and int(line['counterpartyNumber']) == 0:
line['counterpartyNumber'] = False
except:
pass
if 'counterpartyNumber' in line and line['counterpartyNumber']:
ids = self.pool.get('res.partner.bank').search(cr, uid, [('acc_number', '=', str(line['counterpartyNumber']))])
if ids and len(ids) > 0:
partner_id = self.pool.get('res.partner.bank').browse(cr, uid, ids[0],context=context).partner_id.id
else:
partner_id = None
data = {
'name': line['communication'],
'note': "\n".join(note),
'date': line['entryDate'],
'amount': line['amount'],
# 'type': '',
'partner_id': partner_id,
'account_id': 1,
'statement_id': statement['id'],
# 'analytic_account_id': '',
# 'move_ids': '',
'ref': line['ref'],
'sequence': line['sequence'],
}
self.pool.get('account.bank.statement.line').create(cr, uid, data, context=context)
account_coda_import()
transaction_types = {
"0": ["", _("Simple amount without detailed data; e.g. : an individual credit transfer [free of charges].")],
"1": ["", _("Amount as totalised by the customer; e.g. a file regrouping payments of wages or payments made to suppliers or a file regrouping collections for which the customer is ]debited or credited with one single amount. As a matter of principle, this type is also used when no detailed data is following [type 5].")],
"5": ["1", _("Detail of 1. Standard procedure is no detailing. However, the customer may ask for detailed data to be included into his file after the overall record [type 1].")],
"2": ["", _("Amount as totalised by the bank; e.g. : the total amount of a series of credit transfers with a structured communication As a matter of principle, this type will also be used when no detailed data [type 6 or 7] is following.")],
"6": ["2", _("Detail of 2. Simple amount without detailed data. Normally, data of this kind comes after type 2. The customer may ask for a separate file containing the detailed data. In that case, one will speak of a ‘separate application’. The records in a separate application keep type 6.")],
"7": ["2", _("Detail of 2. Simple account with detailed data The records in a separate application keep type 7.")],
"9": ["7", _("Detail of 7. The records in a separate application keep type 9.")],
"3": ["", _("Simple amount with detailed data; e.g. in case of charges for cross-border credit transfers.")],
"8": ["3", _("Detail of 3.")],
}
transaction_codes = {
"00": [_("Undefined transactions"), {
"89": _("Cancellation of a transaction"),
"87": _("Costs refunded"),
"85": _("Correction"),
"83": _("Value correction"),
"39": _("Cancellation of a transaction"),
"37": _("Costs"),
"35": _("Correction"),
"33": _("Value correction"),
"00": _("Undefined transaction")
}],
"01": [_("Domestic or local SEPA credit transfers"), {
"99": _("Cancellation or correction"),
"87": _("Reimbursement of costs"),
"66": _("Financial centralization"),
"64": _("Transfer to your account"),
"62": _("Unpaid postal order"),
"60": _("Non-presented circular cheque"),
"54": _("Unexecutable transfer order"),
"52": _("Payment in your favour"),
"51": _("Transfer in your favour – initiated by the bank"),
"50": _("Transfer in your favour"),
"49": _("Cancellation or correction"),
"39": _("Your issue circular cheque"),
"37": _("Costs"),
"17": _("Financial centralisation"),
"15": _("Balance due insurance premium"),
"13": _("Transfer from your account"),
"11": _("Your semi-standing order – payment to employees"),
"09": _("Your semi-standing order"),
"07": _("Collective transfer"),
"05": _("Payment of wages etc."),
"03": _("Standing order"),
"02": _("Individual transfer order initiated by the bank"),
"01": _("Individual transfer order]"),
}],
"03": [_("Cheques"), {
"99": _("Cancellation or correction"),
"87": _("Reimbursement of cheque-related costs"),
"68": _("Credit of a payment via electronic purse"),
"66": _("Remittance of cheque by your branch - credit under usual reserve"),
"64": _("Reversal of settlement of credit card"),
"63": _("Second credit of unpaid cheque"),
"62": _("Reversal of cheque"),
"60": _("Reversal of voucher"),
"58": _("Remittance of cheques, vouchers, etc. credit after collection"),
"56": _("Non-presented certified cheques"),
"52": _("First credit of cheques, vouchers, luncheon vouchers, postal orders, credit under usual reserve"),
"50": _("Credit of a payment via terminal"),
"49": _("Cancellation or correction"),
"39": _("Provisionally unpaid due to other reason than manual presentation"),
"38": _("Provisionally unpaid"),
"37": _("Cheque-related costs"),
"35": _("Cash advance"),
"19": _("Settlement of credit cards"),
"17": _("Your certified cheque"),
"15": _("Your purchase bank cheque"),
"13": _("Eurocheque written out abroad"),
"11": _("Department store cheque"),
"09": _("Unpaid voucher"),
"07": _("Definitely unpaid cheque"),
"05": _("Payment of voucher"),
"03": _("Your purchase by payment card"),
"01": _("Payment of your cheque"),
}],
"04": [_("Cards"), {
"99": _("Cancellation or correction"),
"87": _("Reimbursement of costs"),
"68": _("Credit after Proton payments"),
"55": _("Income from payments by GSM"),
"53": _("Cash deposit at an ATM"),
"52": _("Loading GSM cards"),
"51": _("Unloading Proton"),
"50": _("Credit after a payment at a terminal"),
"49": _("Cancellation or correction"),
"37": _("Costs"),
"08": _("Payment by means of a payment card outside the Eurozone"),
"07": _("Payment by GSM"),
"06": _("Payment with tank card"),
"05": _("Loading Proton"),
"04": _("Cash withdrawal from an ATM"),
"03": _("Settlement credit cards"),
"02": _("Payment by means of a payment card within the Eurozone"),
"01": _("Loading a GSM card"),
}],
"05": [_("Direct debit"), {
"99": _("Cancellation or correction"),
"87": _("Reimbursement of costs"),
"58": _("Reversal"),
"56": _("Unexecutable reimbursement"),
"54": _("Reimbursement"),
"52": _("Credit under usual reserve"),
"50": _("Credit after collection"),
"49": _("Cancellation or correction"),
"37": _("Costs"),
"05": _("Reimbursement"),
"03": _("Unpaid debt"),
"01": _("Payment"),
}],
"07": [_("Domestic commercial paper"), {
"99": _("Cancellation or correction"),
"87": _("Reimbursement of costs"),
"86": _("Payment after cession"),
"64": _("Warrant"),
"58": _("Remittance of supplier's bill without guarantee"),
"56": _("Remittance of supplier's bill with guarantee"),
"54": _("Remittance of commercial paper for discount"),
"52": _("Remittance of commercial paper - credit under usual reserve"),
"50": _("Remittance of commercial paper - credit after collection"),
"49": _("Cancellation or correction"),
"39": _("Return of an irregular bill of exchange"),
"37": _("Costs related to commercial paper"),
"14": _("Warrant fallen due"),
"12": _("Safe custody"),
"10": _("Renewal of agreed maturity date"),
"09": _("Agio on supplier's bill"),
"08": _("Payment in advance"),
"07": _("Unpaid commercial paper"),
"06": _("Extension of maturity date"),
"05": _("Commercial paper claimed back"),
"03": _("Payment receipt card"),
"01": _("Payment commercial paper"),
}],
"09": [_("Counter transactions"), {
"99": _("Cancellation or correction"),
"87": _("Reimbursement of costs"),
"70": _("Sale of traveller’s cheque"),
"68": _("Difference in payment"),
"66": _("Repurchase of petrol coupons"),
"64": _("Your winning lottery ticket"),
"62": _("Sale of gold/pieces under usual reserve"),
"60": _("Sale of foreign bank notes"),
"58": _("Payment by your branch/agents"),
"56": _("Reserve"),
"54": _("Your payment ATM"),
"52": _("Payment night safe"),
"50": _("Cash payment"),
"49": _("Cancellation or correction"),
"37": _("Costs"),
"25": _("Purchase of traveller’s cheque"),
"21": _("Cash withdrawal on card (PROTON)"),
"19": _("Difference in payment"),
"17": _("Purchase of fiscal stamps"),
"15": _("Your purchase of lottery tickets"),
"13": _("Cash withdrawal by your branch or agents"),
"11": _("Your purchase of luncheon vouchers"),
"09": _("Purchase of petrol coupons"),
"07": _("Purchase of gold/pieces"),
"05": _("Purchase of foreign bank notes"),
"03": _("Cash withdrawal by card (ATM)"),
"01": _("Cash withdrawal"),
}],
"11": [_("Securities"), {
"99": _("Cancellation or correction"),
"87": _("Reimbursement of costs"),
"70": _("Settlement of securities"),
"68": _("Compensation for missing coupon"),
"66": _("Retrocession of issue commission"),
"64": _("Your issue"),
"62": _("Interim interest on subscription"),
"58": _("Repayable securities from a deposit or delivered at the counter - credit under usual reserve"),
"56": _("Reserve"),
"52": _("Payment of coupons from a deposit or settlement of coupons delivered over the counter - credit under usual reserve"),
"51": _("Tender"),
"50": _("Sale of securities"),
"49": _("Cancellation or correction"),
"37": _("Costs"),
"19": _("Regularisation costs"),
"17": _("Management fee"),
"15": _("Interim interest on subscription"),
"13": _("Your repurchase of issue"),
"11": _("Payable coupons/repayable securities"),
"09": _("Settlement of securities"),
"06": _("Share option plan – exercising an option"),
"05": _("Partial payment subscription"),
"04": _("Issues"),
"03": _("Subscription to securities"),
"02": _("Tenders"),
"01": _("Purchase of securities"),
}],
"13": [_("Credit"), {
"99": _("Cancellation or correction"),
"87": _("Reimbursement of costs"),
"70": _("Settlement of discount bank acceptance"),
"68": _("Documentary export credits"),
"62": _("Term loan"),
"60": _("Settlement of mortgage loan"),
"56": _("Subsidy"),
"55": _("Fixed advance – interest only"),
"54": _("Fixed advance – capital and interest"),
"50": _("Settlement of instalment credit"),
"49": _("Cancellation or correction"),
"37": _("Credit-related costs"),
"21": _("Other credit applications"),
"19": _("Documentary import credits"),
"15": _("Your repayment hire-purchase and similar claims"),
"13": _("Settlement of bank acceptances"),
"11": _("Your repayment mortgage loan"),
"07": _("Your repayment instalment credits"),
"05": _("Settlement of fixed advance"),
"02": _("Long-term loan"),
"01": _("Short-term loan"),
}],
"30": [_("Various transactions"), {
"99": _("Cancellation or correction"),
"89": _("Undefined transaction"),
"87": _("Reimbursement of costs"),
"83": _("Value (date) correction"),
"55": _("Interest term investment"),
"54": _("Capital and/or interest term investment"),
"52": _("Forward sale of foreign exchange"),
"50": _("Spot sale of foreign exchange"),
"49": _("Cancellation or correction"),
"39": _("Undefined transaction"),
"37": _("Costs"),
"33": _("Value (date) correction"),
"05": _("Capital and/or interest term investment"),
"03": _("Forward purchase of foreign exchange"),
"01": _("Spot purchase of foreign exchange"),
}],
"35": [_("Closing (periodical settlements for interest, costs,…)"), {
"99": _("Cancellation or correction"),
"87": _("Reimbursement of costs"),
"50": _("Closing"),
"49": _("Cancellation or correction"),
"37": _("Costs"),
"01": _("Closing"),
}],
"41": [_("International credit transfers - non-SEPA credit transfers"), {
"99": _("Cancellation or correction"),
"87": _("Reimbursement of costs"),
"66": _("Financial centralisation (credit)"),
"64": _("Transfer to your account"),
"50": _("Transfer"),
"49": _("Cancellation or correction"),
"38": _("Costs relating to incoming foreign and non-SEPA transfers"),
"37": _("Costs relating to outgoing foreign transfers and non-SEPA transfers"),
"17": _("Financial centralisation (debit)"),
"13": _("Transfer from your account"),
"07": _("Collective transfers"),
"05": _("Collective payments of wages"),
"03": _("Standing order"),
"01": _("Transfer"),
}],
"43": [_("Foreign cheques"), {
"99": _("Cancellation or correction"),
"87": _("Reimbursement of costs"),
"70": _("Purchase of traveller’s cheque"),
"62": _("Reversal of cheques"),
"58": _("Remittance of foreign cheque credit after collection"),
"52": _("Remittance of foreign cheque credit under usual reserve"),
"49": _("Cancellation or correction"),
"37": _("Costs relating to payment of foreign cheques"),
"15": _("Purchase of an international bank cheque"),
"07": _("Unpaid foreign cheque"),
"01": _("Payment of a foreign cheque"),
}],
"47": [_("Foreign commercial paper"), {
"99": _("Cancellation or correction"),
"87": _("Reimbursement of costs"),
"64": _("Warrant"),
"62": _("Remittance of documents abroad - credit after collection"),
"60": _("Remittance of documents abroad - credit under usual reserve"),
"58": _("Idem without guarantee"),
"56": _("Remittance of guaranteed foreign supplier's bill"),
"54": _("Discount abroad"),
"52": _("Remittance of foreign bill credit under usual reserve"),
"50": _("Remittance of foreign bill credit after collection"),
"49": _("Cancellation or correction"),
"37": _("Costs relating to the payment of a foreign bill"),
"14": _("Warrant fallen due"),
"13": _("Discount foreign supplier's bills"),
"11": _("Payment documents abroad"),
"07": _("Unpaid foreign bill"),
"06": _("Extension"),
"05": _("Bill claimed back"),
"01": _("Payment of foreign bill"),
}],
"49": [_("Foreign counter transactions"), {"03": _("ATM withdrawal")}],
"80": [_("Separately charged costs and provisions"), {
"01": _("Guarantee card charges"),
"02": _("Costs relating to electronic output"),
"03": _("Payment card charges"),
"04": _("Costs for holding a documentary cash credit"),
"05": _("Card charges"),
"06": _("Damage relating to bills and cheques"),
"07": _("Insurance costs"),
"08": _("Registering compensation for savings accounts"),
"09": _("Postage"),
"10": _("Purchase of Smartcard"),
"11": _("Costs for the safe custody of correspondence"),
"12": _("Costs for opening a bank guarantee"),
"13": _("Renting of safes"),
"14": _("Handling costs instalment credit"),
"15": _("Night safe"),
"16": _("Bank confirmation to revisor or accountant"),
"17": _("Charge for safe custody"),
"18": _("Trade information"),
"19": _("Special charge for safe custody"),
"20": _("Drawing up a certificate"),
"21": _("Pay-packet charges"),
"22": _("Management/custody"),
"23": _("Research costs"),
"24": _("Participation in and management of interest refund system"),
"25": _("Renting of direct debit box"),
"26": _("Travel insurance premium"),
"27": _("Subscription fee"),
"29": _("Information charges"),
"31": _("Writ service fee"),
"33": _("Miscellaneous fees and commissions"),
"35": _("Costs"),
"37": _("Access right to database"),
"39": _("Surety fee"),
"41": _("Research costs"),
"43": _("Printing of forms"),
"45": _("Documentary credit charges"),
"47": _("Charging fees for transactions"),
"49": _("Cancellation or correction"),
"99": _("Cancellation or correction"),
}],
}
transaction_categories = {
"000": _("Net amount"),
"001": _("Interest received"),
"002": _("Interest paid"),
"003": _("Credit commission"),
"004": _("Postage"),
"005": _("Renting of letterbox"),
"006": _("Various fees/commissions"),
"007": _("Access right to database"),
"008": _("Information charges"),
"009": _("Travelling expenses"),
"010": _("Writ service fee"),
"011": _("VAT"),
"012": _("Exchange commission"),
"013": _("Payment commission"),
"014": _("Collection commission"),
"015": _("Correspondent charges"),
"016": _("BLIW/IBLC dues"),
"017": _("Research costs"),
"018": _("Tental guarantee charges"),
"019": _("Tax on physical delivery"),
"020": _("Costs of physical delivery"),
"021": _("Costs for drawing up a bank cheque"),
"022": _("Priority costs"),
"023": _("Exercising fee"),
"024": _("Growth premium"),
"025": _("Individual entry for exchange charges"),
"026": _("Handling commission"),
"027": _("Charges for unpaid bills"),
"028": _("Fidelity premium"),
"029": _("Protest charges"),
"030": _("Account insurance"),
"031": _("Charges foreign cheque"),
"032": _("Drawing up a circular cheque"),
"033": _("Charges for a foreign bill"),
"034": _("Reinvestment fee"),
"035": _("Charges foreign documentary bill"),
"036": _("Costs relating to a refused cheque"),
"037": _("Commission for handling charges"),
"039": _("Telecommunications"),
"041": _("Credit card costs"),
"042": _("Payment card costs"),
"043": _("Insurance costs"),
"045": _("Handling costs"),
"047": _("Charges extension bill"),
"049": _("Fiscal stamps/stamp duty"),
"050": _("Capital term investment"),
"051": _("Withholding tax"),
"052": _("Residence state tax"),
"053": _("Printing of forms"),
"055": _("Repayment loan or credit capital"),
"057": _("Interest subsidy"),
"058": _("Capital premium"),
"059": _("Default interest"),
"061": _("Charging fees for transactions"),
"063": _("Rounding differences"),
"065": _("Interest payment advice"),
"066": _("Fixed loan advance - reimbursement"),
"067": _("Fixed loan advance - extension"),
"068": _("Countervalue of an entry"),
"069": _("Forward arbitrage contracts : sum to be supplied by customer"),
"070": _("Forward arbitrage contracts : sum to be supplied by bank"),
"071": _("Fixed loan advance - availability"),
"072": _("Countervalue of commission to third party"),
"073": _("Costs of ATM abroad"),
"074": _("Mailing costs"),
"100": _("Gross amount"),
"200": _("Overall documentary credit charges"),
"201": _("Advice notice commission"),
"202": _("Advising commission | Additional advising commission"),
"203": _("Confirmation fee | Additional confirmation fee | Commitment fee | Flat fee | Confirmation reservation commission | Additional reservation commission"),
"204": _("Amendment fee"),
"205": _("Documentary payment commission | Document commission | Drawdown fee | Negotiation fee"),
"206": _("Surety fee/payment under reserve"),
"207": _("Non-conformity fee"),
"208": _("Commitment fee deferred payment"),
"209": _("Transfer commission"),
"210": _("Commitment fee"),
"211": _("Credit arrangement fee | Additional credit arrangement fee"),
"212": _("Warehousing fee"),
"213": _("Financing fee"),
"214": _("Issue commission (delivery order)"),
"400": _("Acceptance fee"),
"401": _("Visa charges"),
"402": _("Certification costs"),
"403": _("Minimum discount rate"),
"404": _("Discount commission"),
"405": _("Bill guarantee commission"),
"406": _("Collection charges"),
"407": _("Costs Article 45"),
"408": _("Cover commission"),
"409": _("Safe deposit charges"),
"410": _("Reclamation charges"),
"411": _("Fixed collection charge"),
"412": _("Advice of expiry charges"),
"413": _("Acceptance charges"),
"414": _("Regularisation charges"),
"415": _("Surety fee"),
"416": _("Charges for the deposit of security"),
"418": _("Endorsement commission"),
"419": _("Bank service fee"),
"420": _("Retention charges"),
"425": _("Foreign broker's commission"),
"426": _("Belgian broker's commission"),
"427": _("Belgian Stock Exchange tax"),
"428": _("Interest accrued"),
"429": _("Foreign Stock Exchange tax"),
"430": _("Recovery of foreign tax"),
"431": _("Delivery of a copy"),
}
def rmspaces(s):
return " ".join(s.split())
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: