diff --git a/account_bank_statement_import_ofx/__init__.py b/account_bank_statement_import_ofx/__init__.py new file mode 100644 index 0000000..fe838c2 --- /dev/null +++ b/account_bank_statement_import_ofx/__init__.py @@ -0,0 +1,5 @@ +# -*- encoding: utf-8 -*- + +import account_bank_statement_import_ofx + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/account_bank_statement_import_ofx/__openerp__.py b/account_bank_statement_import_ofx/__openerp__.py new file mode 100644 index 0000000..8cd569b --- /dev/null +++ b/account_bank_statement_import_ofx/__openerp__.py @@ -0,0 +1,26 @@ +# -*- encoding: utf-8 -*- +{ + 'name': 'Import OFX Bank Statement', + 'version': '1.0', + 'author': 'OpenERP SA', + 'depends': ['account_bank_statement_import'], + 'demo': [], + 'description' : """ +Module to import OFX bank statements. +====================================== + +This module allows you to import the machine readable OFX Files in Odoo: they are parsed and stored in human readable format in +Accounting \ Bank and Cash \ Bank Statements. + +Bank Statements may be generated containing a subset of the OFX information (only those transaction lines that are required for the +creation of the Financial Accounting records). + +Backported from Odoo 9.0 + """, + 'data' : [], + 'demo': [], + 'auto_install': False, + 'installable': True, +} + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/account_bank_statement_import_ofx/account_bank_statement_import_ofx.py b/account_bank_statement_import_ofx/account_bank_statement_import_ofx.py new file mode 100644 index 0000000..13966c0 --- /dev/null +++ b/account_bank_statement_import_ofx/account_bank_statement_import_ofx.py @@ -0,0 +1,74 @@ +# -*- coding: utf-8 -*- + +import logging +import base64 +import os + +from openerp.osv import osv +from openerp.tools.translate import _ + +_logger = logging.getLogger(__name__) + +from openerp.addons.account_bank_statement_import import account_bank_statement_import as ibs +ibs.add_file_type(('ofx', 'OFX')) + +try: + from ofxparse import OfxParser as ofxparser +except ImportError: + _logger.warning("OFX parser unavailable because the `ofxparse` Python library cannot be found." + "It can be downloaded and installed from `https://pypi.python.org/pypi/ofxparse`.") + ofxparser = None + +class account_bank_statement_import(osv.TransientModel): + _inherit = 'account.bank.statement.import' + + def process_ofx(self, cr, uid, data_file, journal_id=False, context=None): + """ Import a file in the .OFX format""" + if ofxparser is None: + raise osv.except_osv(_("Error"), _("OFX parser unavailable because the `ofxparse` Python library cannot be found." + "It can be downloaded and installed from `https://pypi.python.org/pypi/ofxparse`.")) + try: + tempfile = open("temp.ofx", "w+") + tempfile.write(base64.decodestring(data_file)) + tempfile.read() + pathname = os.path.dirname('temp.ofx') + path = os.path.join(os.path.abspath(pathname), 'temp.ofx') + ofx = ofxparser.parse(file(path)) + except: + raise osv.except_osv(_('Import Error!'), _('Please check OFX file format is proper or not.')) + line_ids = [] + total_amt = 0.00 + try: + for transaction in ofx.account.statement.transactions: + bank_account_id, partner_id = self._detect_partner(cr, uid, transaction.payee, identifying_field='owner_name', context=context) + vals_line = { + 'date': transaction.date, + 'name': transaction.payee + ': ' + transaction.memo, + 'ref': transaction.id, + 'amount': transaction.amount, + 'partner_id': partner_id, + 'bank_account_id': bank_account_id, + } + total_amt += float(transaction.amount) + line_ids.append((0, 0, vals_line)) + except Exception, e: + raise osv.except_osv(_('Error!'), _("Following problem has been occurred while importing your file, Please verify the file is proper or not.\n\n %s" % e.message)) + st_start_date = ofx.account.statement.start_date or False + st_end_date = ofx.account.statement.end_date or False + period_obj = self.pool.get('account.period') + if st_end_date: + period_ids = period_obj.find(cr, uid, st_end_date, context=context) + else: + period_ids = period_obj.find(cr, uid, st_start_date, context=context) + vals_bank_statement = { + 'name': ofx.account.routing_number, + 'balance_start': ofx.account.statement.balance, + 'balance_end_real': float(ofx.account.statement.balance) + total_amt, + 'period_id': period_ids and period_ids[0] or False, + 'journal_id': journal_id + } + vals_bank_statement.update({'line_ids': line_ids}) + os.remove(path) + return [vals_bank_statement] + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/account_bank_statement_import_ofx/test_ofx_file/test_ofx.ofx b/account_bank_statement_import_ofx/test_ofx_file/test_ofx.ofx new file mode 100644 index 0000000..37df4d0 --- /dev/null +++ b/account_bank_statement_import_ofx/test_ofx_file/test_ofx.ofx @@ -0,0 +1,100 @@ + + + + + + + 0 + INFO + + 20130831165153.000[-8:PST] + ENG + + + + + 0 + + 0 + INFO + + + USD + + 000000123 + 123456 + CHECKING + + + 20130801 + 20130831165153.000[-8:PST] + + POS + 20130824080000 + -80 + 219378 + Agrolait + + + + 20130801 + 20130831165153.000[-8:PST] + + POS + 20130824080000 + -90 + 219379 + China Export + + + + 20130801 + 20130831165153.000[-8:PST] + + POS + 20130824080000 + -100 + 219380 + Axelor Scuba + + + + 20130801 + 20130831165153.000[-8:PST] + + POS + 20130824080000 + -90 + 219381 + China Scuba + + + + 2156.56 + 20130831165153 + + + + + + + 0 + + 0 + INFO + + + USD + + 123412341234 + + + + + -562.00 + 20130831165153 + + + + + diff --git a/account_bank_statement_import_ofx/tests/__init__.py b/account_bank_statement_import_ofx/tests/__init__.py new file mode 100644 index 0000000..8a5a8e9 --- /dev/null +++ b/account_bank_statement_import_ofx/tests/__init__.py @@ -0,0 +1,5 @@ +from . import test_import_bank_statement + +checks = [ + test_import_bank_statement +] diff --git a/account_bank_statement_import_ofx/tests/test_import_bank_statement.py b/account_bank_statement_import_ofx/tests/test_import_bank_statement.py new file mode 100644 index 0000000..967d647 --- /dev/null +++ b/account_bank_statement_import_ofx/tests/test_import_bank_statement.py @@ -0,0 +1,30 @@ +from openerp.tests.common import TransactionCase +from openerp.modules.module import get_module_resource + +class TestOfxFile(TransactionCase): + """Tests for import bank statement ofx file format (account.bank.statement.import) + """ + + def setUp(self): + super(TestOfxFile, self).setUp() + self.statement_import_model = self.registry('account.bank.statement.import') + self.bank_statement_model = self.registry('account.bank.statement') + + def test_ofx_file_import(self): + try: + from ofxparse import OfxParser as ofxparser + except ImportError: + #the Python library isn't installed on the server, the OFX import is unavailable and the test cannot be run + return True + cr, uid = self.cr, self.uid + ofx_file_path = get_module_resource('account_bank_statement_import_ofx', 'test_ofx_file', 'test_ofx.ofx') + ofx_file = open(ofx_file_path, 'rb').read().encode('base64') + bank_statement_id = self.statement_import_model.create(cr, uid, dict( + file_type='ofx', + data_file=ofx_file, + )) + self.statement_import_model.parse_file(cr, uid, [bank_statement_id]) + statement_id = self.bank_statement_model.search(cr, uid, [('name', '=', '000000123')])[0] + bank_st_record = self.bank_statement_model.browse(cr, uid, statement_id) + self.assertEquals(bank_st_record.balance_start, 2156.56) + self.assertEquals(bank_st_record.balance_end_real, 1796.56)