From 4c1b5c1702d1cc1f790d49345b7519c7cae0f909 Mon Sep 17 00:00:00 2001 From: Ilyas Date: Wed, 18 Nov 2015 14:50:48 +0500 Subject: [PATCH 1/3] Some changes for odoo 9.0 --- account_bank_statement_import_ofx/__manifest__.py | 2 +- .../account_bank_statement_import_ofx.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/account_bank_statement_import_ofx/__manifest__.py b/account_bank_statement_import_ofx/__manifest__.py index 275bff9..329859e 100644 --- a/account_bank_statement_import_ofx/__manifest__.py +++ b/account_bank_statement_import_ofx/__manifest__.py @@ -16,5 +16,5 @@ 'python': ['ofxparse'], }, 'auto_install': False, - 'installable': False, + 'installable': True, } 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 index 9358ae1..0a82d5f 100644 --- a/account_bank_statement_import_ofx/account_bank_statement_import_ofx.py +++ b/account_bank_statement_import_ofx/account_bank_statement_import_ofx.py @@ -46,7 +46,7 @@ class AccountBankStatementImport(models.TransientModel): # generic module uses to find partner/bank) bank_account_id = partner_id = False banks = self.env['res.partner.bank'].search( - [('owner_name', '=', transaction.payee)], limit=1) + [('bank_name', '=', transaction.payee)], limit=1) if banks: bank_account = banks[0] bank_account_id = bank_account.id From 9fa4ee26070fa6104a6880722fb6786f2f15d60f Mon Sep 17 00:00:00 2001 From: Sylvain LE GAL Date: Fri, 3 Jun 2016 16:04:20 +0200 Subject: [PATCH 2/3] [REF] OCA convention; [ADD] patch ofx parser to make this module work with some european bank like credit cooperatif; [IMP] wizard view to display OFX implementation; --- account_bank_statement_import_ofx/README.rst | 21 +++++++++- account_bank_statement_import_ofx/__init__.py | 5 +-- .../__manifest__.py | 15 +++++-- .../demo/demo_data.xml | 42 +++++++++---------- .../models/__init__.py | 2 + .../account_bank_statement_import.py} | 21 ++++------ .../models/ofx.py | 40 ++++++++++++++++++ .../tests/__init__.py | 4 +- .../tests/test_import_bank_statement.py | 2 +- .../{ => tests}/test_ofx_file/test_ofx.ofx | 0 .../view_account_bank_statement_import.xml | 12 ++++++ 11 files changed, 116 insertions(+), 48 deletions(-) create mode 100644 account_bank_statement_import_ofx/models/__init__.py rename account_bank_statement_import_ofx/{account_bank_statement_import_ofx.py => models/account_bank_statement_import.py} (84%) create mode 100644 account_bank_statement_import_ofx/models/ofx.py rename account_bank_statement_import_ofx/{ => tests}/test_ofx_file/test_ofx.ofx (100%) create mode 100644 account_bank_statement_import_ofx/views/view_account_bank_statement_import.xml diff --git a/account_bank_statement_import_ofx/README.rst b/account_bank_statement_import_ofx/README.rst index 6fb1260..cc06cc1 100644 --- a/account_bank_statement_import_ofx/README.rst +++ b/account_bank_statement_import_ofx/README.rst @@ -1,6 +1,7 @@ .. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg :alt: License: AGPL-3 +========================= Import OFX Bank Statement ========================= @@ -22,6 +23,21 @@ The module requires one additional python lib: * `ofxparse `_ +Technical Note +============== + +this module is based on ofxparse python lib and overload some of its functions. + +* For the time being the default ofxparse lib available with + 'pip install ofxparse' do not manage correctly european amount that are + written with ',' and not with '.'. (For exemple, The Credit Cooperatif + French Bank provides OFX 1.0 with amounts written with coma) + +April, 27 2016: this problem has been fixed here: +https://github.com/jseutter/ofxparse/commit/283f89c3246ed3fedccc3ef5c96078b7d5b94579 +but it is not available in the pip lib for the time being. + + Known issues / Roadmap ====================== @@ -40,12 +56,13 @@ Credits ======= Contributors ------------- +------------ -* Odoo SA +* Odoo SA * Alexis de Lattre * Laurent Mignon * Ronald Portier +* Sylvain LE GAL Maintainer ---------- diff --git a/account_bank_statement_import_ofx/__init__.py b/account_bank_statement_import_ofx/__init__.py index fb5e0c3..a0fdc10 100644 --- a/account_bank_statement_import_ofx/__init__.py +++ b/account_bank_statement_import_ofx/__init__.py @@ -1,3 +1,2 @@ -# -*- encoding: utf-8 -*- - -from . import account_bank_statement_import_ofx +# -*- coding: utf-8 -*- +from . import models diff --git a/account_bank_statement_import_ofx/__manifest__.py b/account_bank_statement_import_ofx/__manifest__.py index 329859e..7e02544 100644 --- a/account_bank_statement_import_ofx/__manifest__.py +++ b/account_bank_statement_import_ofx/__manifest__.py @@ -1,13 +1,20 @@ -# -*- encoding: utf-8 -*- +# -*- coding: utf-8 -*- { 'name': 'Import OFX Bank Statement', 'category': 'Banking addons', - 'version': '8.0.1.0.0', + 'version': '9.0.0.0.0', + 'license': 'AGPL-3', 'author': 'OpenERP SA,' + 'La Louve,' + 'GRAP,' 'Odoo Community Association (OCA)', - 'website': 'https://github.com/OCA/bank-statement-import', + 'website': 'https://odoo-community.org/', 'depends': [ - 'account_bank_statement_import' + 'l10n_generic_coa', + 'account_bank_statement_import', + ], + 'data': [ + 'views/view_account_bank_statement_import.xml', ], 'demo': [ 'demo/demo_data.xml', diff --git a/account_bank_statement_import_ofx/demo/demo_data.xml b/account_bank_statement_import_ofx/demo/demo_data.xml index 8387f27..3a7a352 100644 --- a/account_bank_statement_import_ofx/demo/demo_data.xml +++ b/account_bank_statement_import_ofx/demo/demo_data.xml @@ -1,27 +1,23 @@ - - + - - Bank Journal - (test ofx) - TBNKOFX - bank - - - - - - + + Bank Journal - (test ofx) + OFX/%(range_year)s/ + no_gap + 4 + 1 + - - Your Company - 123456 - - - - bank - - - - + + Bank Journal - (test ofx) + 123456 + TBNKOFX + bank + + + + + + diff --git a/account_bank_statement_import_ofx/models/__init__.py b/account_bank_statement_import_ofx/models/__init__.py new file mode 100644 index 0000000..5dfe830 --- /dev/null +++ b/account_bank_statement_import_ofx/models/__init__.py @@ -0,0 +1,2 @@ +# -*- coding: utf-8 -*- +from . import account_bank_statement_import diff --git a/account_bank_statement_import_ofx/account_bank_statement_import_ofx.py b/account_bank_statement_import_ofx/models/account_bank_statement_import.py similarity index 84% rename from account_bank_statement_import_ofx/account_bank_statement_import_ofx.py rename to account_bank_statement_import_ofx/models/account_bank_statement_import.py index 0a82d5f..c05ee73 100644 --- a/account_bank_statement_import_ofx/account_bank_statement_import_ofx.py +++ b/account_bank_statement_import_ofx/models/account_bank_statement_import.py @@ -5,15 +5,11 @@ import StringIO from openerp import api, models from openerp.tools.translate import _ -from openerp.exceptions import Warning +from openerp.exceptions import Warning as UserError -_logger = logging.getLogger(__name__) +from .ofx import OfxParser, OfxParser_ok -try: - from ofxparse import OfxParser as ofxparser -except ImportError: - _logger.warn("ofxparse not found, OFX parsing disabled.") - ofxparser = None +_logger = logging.getLogger(__name__) class AccountBankStatementImport(models.TransientModel): @@ -21,11 +17,12 @@ class AccountBankStatementImport(models.TransientModel): @api.model def _check_ofx(self, data_file): - if ofxparser is None: + if not OfxParser_ok: return False try: - ofx = ofxparser.parse(StringIO.StringIO(data_file)) - except: + ofx = OfxParser.parse(StringIO.StringIO(data_file)) + except Exception as e: + _logger.debug(e) return False return ofx @@ -64,7 +61,7 @@ class AccountBankStatementImport(models.TransientModel): total_amt += float(transaction.amount) transactions.append(vals_line) except Exception, e: - raise Warning(_("The following problem occurred during import. " + raise UserError(_("The following problem occurred during import. " "The file might not be valid.\n\n %s" % e.message)) vals_bank_statement = { @@ -72,7 +69,7 @@ class AccountBankStatementImport(models.TransientModel): 'transactions': transactions, 'balance_start': ofx.account.statement.balance, 'balance_end_real': - float(ofx.account.statement.balance) + total_amt, + float(ofx.account.statement.balance) + total_amt, } return ofx.account.statement.currency, ofx.account.number, [ vals_bank_statement] diff --git a/account_bank_statement_import_ofx/models/ofx.py b/account_bank_statement_import_ofx/models/ofx.py new file mode 100644 index 0000000..d746938 --- /dev/null +++ b/account_bank_statement_import_ofx/models/ofx.py @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- + +import logging + +_logger = logging.getLogger(__name__) + +try: + from ofxparse import OfxParser as OfxParserOriginal + OfxParser_ok = True +except ImportError: + _logger.warn("ofxparse not found, OFX parsing disabled.") + OfxParserOriginal = object + OfxParser_ok = False + + +class OfxParser(OfxParserOriginal): + """ Custom changes in the OFX Parser. + """ + + @classmethod + def _tagToDecimal(self, tag): + tag.string = tag.string.replace(',', '.') + + @classmethod + def parseStatement(cls_, stmt_ofx): + """Amount with ',' replaced by '.' in the following tags : + //LEDGERBAL/BALAMT + """ + ledgerbal_tag = stmt_ofx.find('ledgerbal') + if hasattr(ledgerbal_tag, "contents"): + cls_._tagToDecimal(ledgerbal_tag.find('balamt')) + return super(OfxParser, cls_).parseStatement(stmt_ofx) + + @classmethod + def parseTransaction(cls_, txn_ofx): + """Amount with ',' replaced by '.' in the following tags : + //TRNAMT + """ + cls_._tagToDecimal(txn_ofx.find('trnamt')) + return super(OfxParser, cls_).parseTransaction(txn_ofx) diff --git a/account_bank_statement_import_ofx/tests/__init__.py b/account_bank_statement_import_ofx/tests/__init__.py index 15a0140..9ce25a7 100644 --- a/account_bank_statement_import_ofx/tests/__init__.py +++ b/account_bank_statement_import_ofx/tests/__init__.py @@ -1,4 +1,2 @@ -# -*- encoding: utf-8 -*- -# noqa: This is a backport from Odoo. OCA has no control over style here. -# flake8: noqa +# -*- coding: utf-8 -*- from . import 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 index b35afa1..0efe690 100644 --- a/account_bank_statement_import_ofx/tests/test_import_bank_statement.py +++ b/account_bank_statement_import_ofx/tests/test_import_bank_statement.py @@ -16,7 +16,7 @@ class TestOfxFile(TransactionCase): def test_ofx_file_import(self): ofx_file_path = get_module_resource( 'account_bank_statement_import_ofx', - 'test_ofx_file', 'test_ofx.ofx') + 'tests/test_ofx_file/', 'test_ofx.ofx') ofx_file = open(ofx_file_path, 'rb').read().encode('base64') bank_statement = self.statement_import_model.create( dict(data_file=ofx_file)) diff --git a/account_bank_statement_import_ofx/test_ofx_file/test_ofx.ofx b/account_bank_statement_import_ofx/tests/test_ofx_file/test_ofx.ofx similarity index 100% rename from account_bank_statement_import_ofx/test_ofx_file/test_ofx.ofx rename to account_bank_statement_import_ofx/tests/test_ofx_file/test_ofx.ofx diff --git a/account_bank_statement_import_ofx/views/view_account_bank_statement_import.xml b/account_bank_statement_import_ofx/views/view_account_bank_statement_import.xml new file mode 100644 index 0000000..3f0892f --- /dev/null +++ b/account_bank_statement_import_ofx/views/view_account_bank_statement_import.xml @@ -0,0 +1,12 @@ + + + + account.bank.statement.import + + + +
  • Open Financial Exchange (.OFX Money)
  • +
    +
    +
    +
    From 2e30540217b62ce8048afcbd4572724fcb20325d Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Mon, 14 Nov 2016 17:21:14 +0100 Subject: [PATCH 3/3] [MIG] account_bank_statement_import_ofx: Migration to 10.0 * Remove the code that matches partners, which is wrong and cannot work * Better 'name' on bank statement * Move from models directory to wizard * Remove demo data to tests * Use latest version of ofxparse from github --- .travis.yml | 2 +- account_bank_statement_import_ofx/README.rst | 41 +++----- account_bank_statement_import_ofx/__init__.py | 2 +- .../__manifest__.py | 10 +- .../demo/demo_data.xml | 23 ----- .../models/account_bank_statement_import.py | 75 --------------- .../models/ofx.py | 40 -------- .../tests/test_import_bank_statement.py | 39 +++++--- .../view_account_bank_statement_import.xml | 2 +- .../{models => wizard}/__init__.py | 0 .../wizard/account_bank_statement_import.py | 94 +++++++++++++++++++ 11 files changed, 139 insertions(+), 189 deletions(-) delete mode 100644 account_bank_statement_import_ofx/demo/demo_data.xml delete mode 100644 account_bank_statement_import_ofx/models/account_bank_statement_import.py delete mode 100644 account_bank_statement_import_ofx/models/ofx.py rename account_bank_statement_import_ofx/{models => wizard}/__init__.py (100%) create mode 100644 account_bank_statement_import_ofx/wizard/account_bank_statement_import.py diff --git a/.travis.yml b/.travis.yml index b2ef337..715eebc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,7 +30,7 @@ virtualenv: install: - git clone https://github.com/OCA/maintainer-quality-tools.git ${HOME}/maintainer-quality-tools - export PATH=${HOME}/maintainer-quality-tools/travis:${PATH} - - pip install ofxparse + - pip install git+https://github.com/jseutter/ofxparse.git - travis_install_nightly # example: dependency # - git clone https://github.com/OCA/webkit-tools -b ${VERSION} $HOME/webkit-tools diff --git a/account_bank_statement_import_ofx/README.rst b/account_bank_statement_import_ofx/README.rst index cc06cc1..3262208 100644 --- a/account_bank_statement_import_ofx/README.rst +++ b/account_bank_statement_import_ofx/README.rst @@ -5,16 +5,10 @@ Import OFX Bank Statement ========================= -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. +This module adds support for the import of bank statements in `OFX format `_. -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). - -The module has been initiated by a backport of the new framework developed -by Odoo for V9 at its early stage. It's no more kept in sync with the V9 since -it has reach a stage where maintaining a pure backport of 9.0 in 8.0 is not -feasible anymore +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). Installation ============ @@ -23,20 +17,12 @@ The module requires one additional python lib: * `ofxparse `_ -Technical Note -============== - -this module is based on ofxparse python lib and overload some of its functions. - -* For the time being the default ofxparse lib available with - 'pip install ofxparse' do not manage correctly european amount that are - written with ',' and not with '.'. (For exemple, The Credit Cooperatif - French Bank provides OFX 1.0 with amounts written with coma) - -April, 27 2016: this problem has been fixed here: -https://github.com/jseutter/ofxparse/commit/283f89c3246ed3fedccc3ef5c96078b7d5b94579 -but it is not available in the pip lib for the time being. +Usage +===== +.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas + :alt: Try me on Runbot + :target: https://runbot.odoo-community.org/runbot/174/10.0 Known issues / Roadmap ====================== @@ -46,11 +32,10 @@ Known issues / Roadmap Bug Tracker =========== -Bugs are tracked on `GitHub Issues `_. -In case of trouble, please check there if your issue has already been reported. -If you spotted it first, help us smashing it by providing a detailed and welcomed feedback -`here `_. - +Bugs are tracked on `GitHub Issues +`_. In case of trouble, please +check there if your issue has already been reported. If you spotted it first, +help us smashing it by providing a detailed and welcomed feedback. Credits ======= @@ -77,4 +62,4 @@ OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use. -To contribute to this module, please visit http://odoo-community.org. +To contribute to this module, please visit https://odoo-community.org. diff --git a/account_bank_statement_import_ofx/__init__.py b/account_bank_statement_import_ofx/__init__.py index a0fdc10..02baef4 100644 --- a/account_bank_statement_import_ofx/__init__.py +++ b/account_bank_statement_import_ofx/__init__.py @@ -1,2 +1,2 @@ # -*- coding: utf-8 -*- -from . import models +from . import wizard diff --git a/account_bank_statement_import_ofx/__manifest__.py b/account_bank_statement_import_ofx/__manifest__.py index 7e02544..df4f07f 100644 --- a/account_bank_statement_import_ofx/__manifest__.py +++ b/account_bank_statement_import_ofx/__manifest__.py @@ -2,26 +2,22 @@ { 'name': 'Import OFX Bank Statement', 'category': 'Banking addons', - 'version': '9.0.0.0.0', + 'version': '10.0.1.0.0', 'license': 'AGPL-3', - 'author': 'OpenERP SA,' + 'author': 'Odoo SA,' + 'Akretion,' 'La Louve,' 'GRAP,' 'Odoo Community Association (OCA)', 'website': 'https://odoo-community.org/', 'depends': [ - 'l10n_generic_coa', 'account_bank_statement_import', ], 'data': [ 'views/view_account_bank_statement_import.xml', ], - 'demo': [ - 'demo/demo_data.xml', - ], 'external_dependencies': { 'python': ['ofxparse'], }, - 'auto_install': False, 'installable': True, } diff --git a/account_bank_statement_import_ofx/demo/demo_data.xml b/account_bank_statement_import_ofx/demo/demo_data.xml deleted file mode 100644 index 3a7a352..0000000 --- a/account_bank_statement_import_ofx/demo/demo_data.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - Bank Journal - (test ofx) - OFX/%(range_year)s/ - no_gap - 4 - 1 - - - - - Bank Journal - (test ofx) - 123456 - TBNKOFX - bank - - - - - - diff --git a/account_bank_statement_import_ofx/models/account_bank_statement_import.py b/account_bank_statement_import_ofx/models/account_bank_statement_import.py deleted file mode 100644 index c05ee73..0000000 --- a/account_bank_statement_import_ofx/models/account_bank_statement_import.py +++ /dev/null @@ -1,75 +0,0 @@ -# -*- coding: utf-8 -*- - -import logging -import StringIO - -from openerp import api, models -from openerp.tools.translate import _ -from openerp.exceptions import Warning as UserError - -from .ofx import OfxParser, OfxParser_ok - -_logger = logging.getLogger(__name__) - - -class AccountBankStatementImport(models.TransientModel): - _inherit = 'account.bank.statement.import' - - @api.model - def _check_ofx(self, data_file): - if not OfxParser_ok: - return False - try: - ofx = OfxParser.parse(StringIO.StringIO(data_file)) - except Exception as e: - _logger.debug(e) - return False - return ofx - - @api.model - def _parse_file(self, data_file): - ofx = self._check_ofx(data_file) - if not ofx: - return super(AccountBankStatementImport, self)._parse_file( - data_file) - - transactions = [] - total_amt = 0.00 - try: - for transaction in ofx.account.statement.transactions: - # Since ofxparse doesn't provide account numbers, we'll have - # to find res.partner and res.partner.bank here - # (normal behavious is to provide 'account_number', which the - # generic module uses to find partner/bank) - bank_account_id = partner_id = False - banks = self.env['res.partner.bank'].search( - [('bank_name', '=', transaction.payee)], limit=1) - if banks: - bank_account = banks[0] - bank_account_id = bank_account.id - partner_id = bank_account.partner_id.id - vals_line = { - 'date': transaction.date, - 'name': transaction.payee + ( - transaction.memo and ': ' + transaction.memo or ''), - 'ref': transaction.id, - 'amount': transaction.amount, - 'unique_import_id': transaction.id, - 'bank_account_id': bank_account_id, - 'partner_id': partner_id, - } - total_amt += float(transaction.amount) - transactions.append(vals_line) - except Exception, e: - raise UserError(_("The following problem occurred during import. " - "The file might not be valid.\n\n %s" % e.message)) - - vals_bank_statement = { - 'name': ofx.account.routing_number, - 'transactions': transactions, - 'balance_start': ofx.account.statement.balance, - 'balance_end_real': - float(ofx.account.statement.balance) + total_amt, - } - return ofx.account.statement.currency, ofx.account.number, [ - vals_bank_statement] diff --git a/account_bank_statement_import_ofx/models/ofx.py b/account_bank_statement_import_ofx/models/ofx.py deleted file mode 100644 index d746938..0000000 --- a/account_bank_statement_import_ofx/models/ofx.py +++ /dev/null @@ -1,40 +0,0 @@ -# -*- coding: utf-8 -*- - -import logging - -_logger = logging.getLogger(__name__) - -try: - from ofxparse import OfxParser as OfxParserOriginal - OfxParser_ok = True -except ImportError: - _logger.warn("ofxparse not found, OFX parsing disabled.") - OfxParserOriginal = object - OfxParser_ok = False - - -class OfxParser(OfxParserOriginal): - """ Custom changes in the OFX Parser. - """ - - @classmethod - def _tagToDecimal(self, tag): - tag.string = tag.string.replace(',', '.') - - @classmethod - def parseStatement(cls_, stmt_ofx): - """Amount with ',' replaced by '.' in the following tags : - //LEDGERBAL/BALAMT - """ - ledgerbal_tag = stmt_ofx.find('ledgerbal') - if hasattr(ledgerbal_tag, "contents"): - cls_._tagToDecimal(ledgerbal_tag.find('balamt')) - return super(OfxParser, cls_).parseStatement(stmt_ofx) - - @classmethod - def parseTransaction(cls_, txn_ofx): - """Amount with ',' replaced by '.' in the following tags : - //TRNAMT - """ - cls_._tagToDecimal(txn_ofx.find('trnamt')) - return super(OfxParser, cls_).parseTransaction(txn_ofx) 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 index 0efe690..4b5c1e5 100644 --- a/account_bank_statement_import_ofx/tests/test_import_bank_statement.py +++ b/account_bank_statement_import_ofx/tests/test_import_bank_statement.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -from openerp.tests.common import TransactionCase -from openerp.modules.module import get_module_resource +from odoo.tests.common import TransactionCase +from odoo.modules.module import get_module_resource class TestOfxFile(TransactionCase): @@ -10,26 +10,39 @@ class TestOfxFile(TransactionCase): def setUp(self): super(TestOfxFile, self).setUp() - self.statement_import_model = self.env['account.bank.statement.import'] - self.bank_statement_model = self.env['account.bank.statement'] + self.absi_model = self.env['account.bank.statement.import'] + self.abs_model = self.env['account.bank.statement'] + self.absl_model = self.env['account.bank.statement.line'] + cur = self.env.ref('base.USD') + self.env.ref('base.main_company').currency_id = cur.id + bank = self.env['res.partner.bank'].create({ + 'acc_number': '123456', + 'partner_id': self.env.ref('base.main_partner').id, + 'company_id': self.env.ref('base.main_company').id, + 'bank_id': self.env.ref('base.res_bank_1').id, + }) + self.env['account.journal'].create({ + 'name': 'Bank Journal TEST OFX', + 'code': 'BNK12', + 'type': 'bank', + 'bank_account_id': bank.id, + }) def test_ofx_file_import(self): ofx_file_path = get_module_resource( 'account_bank_statement_import_ofx', 'tests/test_ofx_file/', 'test_ofx.ofx') ofx_file = open(ofx_file_path, 'rb').read().encode('base64') - bank_statement = self.statement_import_model.create( + bank_statement = self.absi_model.create( dict(data_file=ofx_file)) bank_statement.import_file() - bank_st_record = self.bank_statement_model.search( - [('name', '=', '000000123')])[0] + bank_st_record = self.abs_model.search( + [('name', 'like', '123456')])[0] self.assertEquals(bank_st_record.balance_start, 2156.56) self.assertEquals(bank_st_record.balance_end_real, 1796.56) - line = bank_st_record.line_ids[0] - self.assertEquals(line.name, 'Agrolait') + line = self.absl_model.search([ + ('name', '=', 'Agrolait'), + ('statement_id', '=', bank_st_record.id)])[0] self.assertEquals(line.ref, '219378') - self.assertEquals(line.partner_id.id, self.ref('base.res_partner_2')) - self.assertEquals( - line.bank_account_id.id, - self.ref('account_bank_statement_import.ofx_partner_bank_1')) + self.assertEquals(line.date, '2013-08-24') diff --git a/account_bank_statement_import_ofx/views/view_account_bank_statement_import.xml b/account_bank_statement_import_ofx/views/view_account_bank_statement_import.xml index 3f0892f..046ed1e 100644 --- a/account_bank_statement_import_ofx/views/view_account_bank_statement_import.xml +++ b/account_bank_statement_import_ofx/views/view_account_bank_statement_import.xml @@ -1,4 +1,4 @@ - + account.bank.statement.import diff --git a/account_bank_statement_import_ofx/models/__init__.py b/account_bank_statement_import_ofx/wizard/__init__.py similarity index 100% rename from account_bank_statement_import_ofx/models/__init__.py rename to account_bank_statement_import_ofx/wizard/__init__.py diff --git a/account_bank_statement_import_ofx/wizard/account_bank_statement_import.py b/account_bank_statement_import_ofx/wizard/account_bank_statement_import.py new file mode 100644 index 0000000..4835be7 --- /dev/null +++ b/account_bank_statement_import_ofx/wizard/account_bank_statement_import.py @@ -0,0 +1,94 @@ +# -*- coding: utf-8 -*- + +import logging +import StringIO + +from odoo import api, models, fields, _ +from odoo.exceptions import UserError +from odoo.tools import float_is_zero + +_logger = logging.getLogger(__name__) + +try: + from ofxparse import OfxParser +except ImportError: + _logger.debug("ofxparse not found.") + OfxParser = None + + +class AccountBankStatementImport(models.TransientModel): + _inherit = 'account.bank.statement.import' + + @api.model + def _check_ofx(self, data_file): + if not OfxParser: + return False + try: + ofx = OfxParser.parse(StringIO.StringIO(data_file)) + except Exception as e: + _logger.debug(e) + return False + return ofx + + @api.model + def _prepare_ofx_transaction_line(self, transaction): + # since odoo 9, the account module defines a constraint + # on account.bank.statement.line: 'amount' must be != 0 + # But some banks have some transactions with amount=0 + # for bank charges that are offered, which blocks the import + precision = self.env['decimal.precision'].precision_get('Account') + if float_is_zero( + float(transaction.amount), precision_digits=precision): + return False + # Since ofxparse doesn't provide account numbers, + # we cannot provide the key 'bank_account_id', + # nor the key 'account_number' + # If you read odoo10/addons/account_bank_statement_import/ + # account_bank_statement_import.py, it's the only 2 keys + # we can provide to match a partner. + vals = { + 'date': transaction.date, + 'name': transaction.payee + ( + transaction.memo and ': ' + transaction.memo or ''), + 'ref': transaction.id, + 'amount': float(transaction.amount), + 'unique_import_id': transaction.id, + } + return vals + + @api.model + def _parse_file(self, data_file): + ofx = self._check_ofx(data_file) + if not ofx: + return super(AccountBankStatementImport, self)._parse_file( + data_file) + + transactions = [] + total_amt = 0.00 + start_date = end_date = False + try: + for transaction in ofx.account.statement.transactions: + vals = self._prepare_ofx_transaction_line(transaction) + if vals: + transactions.append(vals) + total_amt += vals['amount'] + tdate = fields.Date.to_string(vals['date']) + if not start_date or tdate < start_date: + start_date = tdate + if not end_date or tdate > end_date: + end_date = tdate + except Exception, e: + raise UserError(_( + "The following problem occurred during import. " + "The file might not be valid.\n\n %s") % e.message) + + vals_bank_statement = { + 'name': _('Account %s %s > %s') % ( + ofx.account.number, start_date, end_date), + 'transactions': transactions, + 'balance_start': ofx.account.statement.balance, + 'balance_end_real': + float(ofx.account.statement.balance) + total_amt, + } + return ofx.account.statement.currency, ofx.account.number, [ + vals_bank_statement]