← Back to team overview

clearcorp team mailing list archive

lp:~dr.clearcorp/openerp-costa-rica/l10n_cr_account_banking_cr_bcr into lp:openerp-costa-rica

 

Diana Rodríguez Martínez has proposed merging lp:~dr.clearcorp/openerp-costa-rica/l10n_cr_account_banking_cr_bcr into lp:openerp-costa-rica.

Requested reviews:
  CLEARCORP drivers (clearcorp-drivers)

For more details, see:
https://code.launchpad.net/~dr.clearcorp/openerp-costa-rica/l10n_cr_account_banking_cr_bcr/+merge/113688

[ADD] New module l10n_cr_account_banking_cr_bcr - Import statement and transactions 
-- 
https://code.launchpad.net/~dr.clearcorp/openerp-costa-rica/l10n_cr_account_banking_cr_bcr/+merge/113688
Your team CLEARCORP development team is subscribed to branch lp:openerp-costa-rica.
=== added directory 'l10n_cr_account_banking_cr_bcr'
=== added file 'l10n_cr_account_banking_cr_bcr/__init__.py'
--- l10n_cr_account_banking_cr_bcr/__init__.py	1970-01-01 00:00:00 +0000
+++ l10n_cr_account_banking_cr_bcr/__init__.py	2012-07-06 05:13:21 +0000
@@ -0,0 +1,24 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+#    Copyright (C) 2011 credativ Ltd (<http://www.credativ.co.uk>).
+#    All Rights Reserved
+#
+#    This program is free software: you can redistribute it and/or modify
+#    it under the terms of the GNU Affero 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 Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+import bcr_mt940
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

=== added file 'l10n_cr_account_banking_cr_bcr/__openerp__.py'
--- l10n_cr_account_banking_cr_bcr/__openerp__.py	1970-01-01 00:00:00 +0000
+++ l10n_cr_account_banking_cr_bcr/__openerp__.py	2012-07-06 05:13:21 +0000
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+#    OpenERP, Open Source Management Solution
+#    Addons modules by CLEARCORP S.A.
+#    Copyright (C) 2009-TODAY CLEARCORP S.A. (<http://clearcorp.co.cr>).
+#
+#    This program is free software: you can redistribute it and/or modify
+#    it under the terms of the GNU Affero 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 Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+{
+    'name': 'BCR Account Banking',
+    'version': '0.5',
+    'license': 'AGPL-3',
+    'author': 'CLEARCORP S.A.',
+    'website': 'http://www.clearcorp.co.cr',
+    'category': 'Account Banking',
+    'depends': ['account_banking'],
+    'init_xml': [],
+    'update_xml': [],
+    'demo_xml': [],
+    'description': '',
+    'active': False,
+    'installable': True,
+}

=== added file 'l10n_cr_account_banking_cr_bcr/bcr_mt940.py'
--- l10n_cr_account_banking_cr_bcr/bcr_mt940.py	1970-01-01 00:00:00 +0000
+++ l10n_cr_account_banking_cr_bcr/bcr_mt940.py	2012-07-06 05:13:21 +0000
@@ -0,0 +1,164 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+#    Copyright (C) 2011 credativ Ltd (<http://www.credativ.co.uk>).
+#    All Rights Reserved
+#
+#    This program is free software: you can redistribute it and/or modify
+#    it under the terms of the GNU Affero 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 Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+# Import of BAC data in Swift MT940 format
+#
+
+from account_banking.parsers import models
+from tools.translate import _
+from mt940_parser import BCRParser
+import re
+import osv
+import logging
+import pprint
+from datetime import datetime
+
+bt = models.mem_bank_transaction
+logger = logging.getLogger( 'bcr_mt940' )
+
+def record2float(record, value):
+    if record == 'C':
+        return float (value)
+    else:
+        return -float(value)
+
+class transaction(models.mem_bank_transaction):
+
+    mapping = {
+        'execution_date' : '',
+        'effective_date' : '',
+        'local_currency' : '',
+        'transfer_type' : '',
+        'reference' : '',
+        'message' : '',
+        'name' : '',
+        'amount': '',
+        'creditmarker': '',
+    }
+
+    def __init__(self, record, *args, **kwargs):
+        
+        '''
+        Transaction creation
+        '''
+        super(transaction, self).__init__(*args, **kwargs)
+        #for r in record:
+        for key, value in record.iteritems():
+            if record.has_key(key):
+                setattr(self, key, record[key])
+
+        if not self.is_valid():
+            logger.info("Invalid: %s", r)
+    
+    def is_valid(self):
+        '''
+        We don't have remote_account so override base
+        '''
+        return (self.execution_date
+                and self.transferred_amount and True) or False
+
+class statement(models.mem_bank_statement):
+    '''
+    Bank statement imported data    '''
+      
+    def _transmission_number(self, record):
+        self.id = record['transref']
+        
+    def _account_number(self, record):
+        self.local_account = record['account_number']
+        
+    def _statement_number(self, record):
+        self.id = self.local_account
+        
+    def _opening_balance(self, record):
+        self.start_balance = float(record['startingbalance'])
+        self.local_currency = record['currencycode']
+    
+    def _closing_balance(self, record):
+        self.end_balance = float(record['endingbalance'])
+        self.date = record['bookingdate']
+     
+    def _transaction_new(self, record):
+        parser = BCRParser()
+        sub_record = parser.statement_lines(record) #dictionary
+        for sub in sub_record:
+            self.transactions.append(transaction(sub))
+    
+    #def _transaction_info():
+        #self.transaction_info(record)
+    
+    def _not_used():
+        logger.info("Didn't use record: %s", record)
+        
+    def _forward_available(self, record):
+        self.end_balance =  float(record['endingbalance'])
+        self.date = record['bookingdate'] 
+    
+    def _execution_date_transferred_amount (self, record):        
+        self.execution_date = record['bookingdate']       
+        self.transferred_amount = float(record['ammount'])
+
+    def transaction_info(self, record):
+        '''
+        Add extra information to transaction
+        '''
+        # Additional information for previous transaction
+        if len(self.transactions) < 1:
+            logger.info("Received additional information for non existent transaction:")
+            logger.info(record)
+        else:
+            transaction = self.transactions[-1]
+            transaction.id = ','.join([record[k] for k in ['infoline{0}'.format(i) for i in range(2,5)] if record.has_key(k)])
+
+def raise_error(message, line):
+    raise osv.osv.except_osv(_('Import error'),
+        'Error in import:%s\n\n%s' % (message, line))
+
+class parser_bcr_mt940( models.parser ):
+    code = 'BCR-MT940'
+    name = _( 'BCR statement import' )
+    country_code = 'CR'
+    doc = _('''\
+            This format is available through
+            the BCR  web interface.
+            ''')
+
+    def parse(self, cr, data):
+        result = []
+        parser = BCRParser()
+        stmnt = statement()
+        
+        records = parser.parse_stamenent_record(data)        
+        
+        stmnt._transmission_number(records)
+        stmnt._account_number(records)
+        stmnt._statement_number(records)
+        stmnt._opening_balance(records)
+        stmnt._closing_balance(records)
+        stmnt._forward_available(records)
+        stmnt._execution_date_transferred_amount (records)
+        stmnt._transaction_new(data)
+                  
+        if stmnt.is_valid():
+            result.append(stmnt)
+                      
+        return result
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

=== added file 'l10n_cr_account_banking_cr_bcr/mt940_parser.py'
--- l10n_cr_account_banking_cr_bcr/mt940_parser.py	1970-01-01 00:00:00 +0000
+++ l10n_cr_account_banking_cr_bcr/mt940_parser.py	2012-07-06 05:13:21 +0000
@@ -0,0 +1,248 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+#    Copyright (C) 2011 credativ Ltd (<http://www.credativ.co.uk>).
+#    All Rights Reserved
+#
+#    This program is free software: you can redistribute it and/or modify
+#    it under the terms of the GNU Affero 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 Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+"""
+Parser for BAC CR MT940 format files
+Based on fi_patu's parser
+"""
+import re
+from datetime import datetime
+from dateutil import parser
+import pprint
+from copy import copy
+
+class BCRParser( object ):
+
+    def statement_record ( self, rec ):
+        lines = []
+        line_dict = {}
+
+        line_dict = {
+            'transref': 0.0, # _transmission_number
+            'account_number': '', #_account_number
+            'statementnr':'', # statement_number
+            'startingbalance': 0.0, #_opening_balance
+            'currencycode': 'CRC', #currencycode
+            'endingbalance': 0.0, #_closing_balance
+            'bookingdate': '', #moving_date
+            'ammount': 0.0,
+        }
+
+        #file = open( filename, 'r' )
+        #line = file.readline()
+        
+        list_split = rec.split('\r\n')
+
+        for l in list_split:
+            # _transmission_number
+            if l.find('Movimiento realizado el periodo', 0, len('Movimiento realizado el periodo')) > -1:
+                line_dict['statementnr'] = self.extract_number(l)
+            #_account_number
+            if l.find('Movimiento de Cuenta Corriente', 0, len('Movimiento de Cuenta Corriente')) > -1:
+                line_dict['account_number'] = self.extract_number(l)
+            # _transmission_number
+            if l.find('Solicitado el', 0, len('Solicitado el'))  > -1 :
+                line_dict['transref'] = self.extract_number(l)
+                line_dict['bookingdate'] = self.extract_number(l)               
+            #_opening_balance
+            if l.find('Saldo Inicial', 0, len('Saldo Inicial'))  > -1:
+                line_dict['startingbalance'] = self.extract_float(l)
+            #_closing_balance
+            if l.find('Saldo Final', 0, len('Saldo Final'))  > -1:
+                line_dict['endingbalance'] = self.extract_float(l)
+        
+        amount_statement = float( line_dict['startingbalance'] ) + float( line_dict['endingbalance'] )
+        line_dict['ammount'] = amount_statement
+
+        self.line_dict = line_dict
+
+        return line_dict
+            
+    def statement_lines ( self, rec ):
+        parser = BCRParser()
+        mapping = {
+            'execution_date' : '',
+            'effective_date' : '',
+            'local_currency' : '',
+            'transfer_type' : '',
+            'reference' : '',
+            'message' : '',
+            'name' : '',
+            'transferred_amount': '',
+            'creditmarker': '',
+        }
+        
+        lines = []
+        line_dict = {}
+        
+        list_split = rec.split('\r\n')
+        entrada = False
+        start = 0
+        end = 0
+        
+        for l in list_split: 
+            if l.find('TOTALES DEL MOVIMIENTO CONTABILIZADO', 0, len('TOTALES DEL MOVIMIENTO CONTABILIZADO')) <= -1:
+                end += 1
+            else:
+                break                
+        end = end - 1
+        
+        for l in list_split:           
+            if l.find('-CONTABLE-', 0, len('-CONTABLE-')) <= -1:
+                start += 1
+            else:
+                break
+        start += 1            
+            
+        sub_list = list_split [start:end]
+        for sub in sub_list:
+            #03-05-12
+            day = sub[0:2]
+            month = sub[3:5]            
+            date_n = datetime.now()                        
+            try:
+                date = datetime(int(date_n.year), int(month), int (day))
+            except Exception:
+                day = sub[1]
+                month = sub[4]
+                date_n = datetime.now()
+                date = datetime(int(date_n.year), int(month), int (day))
+                
+            mapping['execution_date'] = date                        
+            mapping['effective_date'] = date
+            mapping['local_currency'] = 'CRC'
+            mapping['transfer_type'] = 'NTRF'
+            mapping['reference'] = parser.extract_number(sub[25:40])
+            mapping['message'] = sub[26:92]                
+            mapping['name'] = sub[26:92]
+            
+            amount = sub[106:]
+            amount.replace('\t',' ')
+            debit = amount[0:16]
+            credit = amount[16:]
+            
+            if (parser.extract_float(debit) is not ''): #debit
+                cad = parser.extract_float(debit)
+                mapping['transferred_amount'] = -float(cad)      
+                mapping['creditmarker'] = 'C'
+                                      
+            else: #credit
+                cad = parser.extract_float (credit)
+                mapping['transferred_amount'] =  float(cad)
+            
+            lines.append(copy(mapping))
+                            
+        return lines 
+    
+    def parse_stamenent_record( self, rec ):
+
+        matchdict = dict()
+
+        matchdict = self.statement_record( rec );
+
+        # Remove members set to None
+        matchdict = dict( [( k, v ) for k, v in matchdict.iteritems() if v] )
+
+        matchkeys = set( matchdict.keys() )
+        needstrip = set( [ 'transref', 'account_number', 'statementnr', 'currencycode', 'endingbalance', 'bookingdate'] )
+
+        for field in matchkeys & needstrip:
+            matchdict[field] = matchdict[field].strip()
+
+        # Convert to float. Comma is decimal separator
+        needsfloat = set( ["startingbalance", "endingbalance", "amount"] )
+        for field in matchkeys & needsfloat:
+            matchdict[field] = float( matchdict[field].replace( ',', '.' ) )
+
+        # Convert date fields
+        needdate = set( ["bookingdate"] )
+                
+        for field in matchkeys & needdate:
+            datestring = matchdict[field]
+            try:
+                day = datestring[0:2]
+                month = datestring[2:4]
+                year = datestring[4:8]
+                hour = datestring[8:10]
+                minute = datestring[10:12]
+                second = datestring[12:14]
+            except Exception:
+                day = datestring[2]
+                month = datestring[4]
+                year = datestring[4:8]
+                hour = datestring[8:10]
+                minute = datestring[10:12]
+                second = datestring[12:14]          
+                       
+            date = datetime(int(year),int(month),int(day),int(hour),int(minute),int(second))
+            matchdict[field] = date
+        
+        return matchdict
+                    
+    def extract_number( self, account_number ):
+        cad = ''
+        result = re.findall(r'[0-9]+', account_number)
+               
+        for character in result:
+            cad = cad + character
+        return cad
+
+    def extract_float ( self, ammount ):
+        cad = ''
+        result = re.findall(r"[-+]?\d*\.\d+|\d+",ammount)
+        
+        for character in result:
+            cad = cad + character       
+        return cad   
+
+    def parse( self, cr, data ):
+        records = []
+        # Some records are multiline
+        for line in data:
+            if len(line) <= 1:
+                continue
+            if line[0] == ':' and len(line) > 1:
+                records.append(line)
+            else:
+                records[-1] = '\n'.join([records[-1], line])
+                
+        output = []
+
+        for rec in records:
+            output.append( self.parse_stamenent_record( rec ) )
+                
+        return output
+
+def parse_file( filename ):
+    bacfile = open( filename, "r" )
+    p = BCRParser().parse( bacfile.readlines() )
+
+def main():
+    """The main function, currently just calls a dummy filename
+
+    :returns: description
+    """
+    parse_file("testfile")
+
+if __name__ == '__main__':
+    main()
+


Follow ups