From c67c7ff7d79421311e44a2563867f6c1eeb2ad9f Mon Sep 17 00:00:00 2001 From: Emanuel Cino Date: Thu, 13 Apr 2017 11:47:46 +0200 Subject: [PATCH] [ADD] camt_details bank statement import --- .../README.rst | 48 ++++++++++++++ .../__init__.py | 4 ++ .../__openerp__.py | 20 ++++++ .../models/__init__.py | 5 ++ .../models/account_bank_statement_line.py | 27 ++++++++ .../models/camt_parser.py | 59 +++++++++++++++++ .../camt_details_reconciliation_layout.xml | 12 ++++ .../tests/__init__.py | 5 ++ .../tests/test_import_bank_statement.py | 64 +++++++++++++++++++ .../views/account_bank_statement_line.xml | 17 +++++ 10 files changed, 261 insertions(+) create mode 100644 account_bank_statement_import_camt_details/README.rst create mode 100644 account_bank_statement_import_camt_details/__init__.py create mode 100644 account_bank_statement_import_camt_details/__openerp__.py create mode 100644 account_bank_statement_import_camt_details/models/__init__.py create mode 100644 account_bank_statement_import_camt_details/models/account_bank_statement_line.py create mode 100644 account_bank_statement_import_camt_details/models/camt_parser.py create mode 100644 account_bank_statement_import_camt_details/static/src/xml/camt_details_reconciliation_layout.xml create mode 100644 account_bank_statement_import_camt_details/tests/__init__.py create mode 100644 account_bank_statement_import_camt_details/tests/test_import_bank_statement.py create mode 100644 account_bank_statement_import_camt_details/views/account_bank_statement_line.xml diff --git a/account_bank_statement_import_camt_details/README.rst b/account_bank_statement_import_camt_details/README.rst new file mode 100644 index 0000000..0281e89 --- /dev/null +++ b/account_bank_statement_import_camt_details/README.rst @@ -0,0 +1,48 @@ +.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg + :alt: License: AGPL-3 + +Bank Statement Parse Camt Debitor Details +========================================= + +Module to add debitor details in bank statement lines from SEPA CAMT.053 Format bank statement files. + +Based on the Banking addons framework. + +Known issues / Roadmap +====================== + +* None + +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 `_. + + +Credits +======= + +Contributors +------------ + +* Emanuel Cino + +Maintainer +---------- + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +This module is maintained by the OCA. + +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. +This module should make it easy to migrate bank statement import +modules written for earlies versions of Odoo/OpenERP. diff --git a/account_bank_statement_import_camt_details/__init__.py b/account_bank_statement_import_camt_details/__init__.py new file mode 100644 index 0000000..9b077d3 --- /dev/null +++ b/account_bank_statement_import_camt_details/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- +# © 2017 Compassion CH +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +from . import models diff --git a/account_bank_statement_import_camt_details/__openerp__.py b/account_bank_statement_import_camt_details/__openerp__.py new file mode 100644 index 0000000..ea63f25 --- /dev/null +++ b/account_bank_statement_import_camt_details/__openerp__.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# © 2017 Compassion CH +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +{ + 'name': 'CAMT Debitor Details Bank Statements Import', + 'version': '9.0.1.0.0', + 'license': 'AGPL-3', + 'author': 'Odoo Community Association (OCA), Compassion CH', + 'website': 'https://github.com/OCA/bank-statement-import', + 'category': 'Banking addons', + 'depends': [ + 'account_bank_statement_import_camt', + ], + 'data': [ + 'views/account_bank_statement_line.xml', + ], + 'qweb': [ + 'static/src/xml/camt_details_reconciliation_layout.xml', + ] +} diff --git a/account_bank_statement_import_camt_details/models/__init__.py b/account_bank_statement_import_camt_details/models/__init__.py new file mode 100644 index 0000000..d4115c8 --- /dev/null +++ b/account_bank_statement_import_camt_details/models/__init__.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- +# © 2017 Compassion CH +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +from . import account_bank_statement_line +from . import camt_parser diff --git a/account_bank_statement_import_camt_details/models/account_bank_statement_line.py b/account_bank_statement_import_camt_details/models/account_bank_statement_line.py new file mode 100644 index 0000000..4961ae7 --- /dev/null +++ b/account_bank_statement_import_camt_details/models/account_bank_statement_line.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +"""Add process_camt method to account.bank.statement.import.""" +# © 2017 Compassion CH +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +from openerp import models, fields + + +class AccountBankStatementLine(models.Model): + """Add process_camt method to account.bank.statement.import.""" + _inherit = 'account.bank.statement.line' + + partner_address = fields.Char() + partner_account = fields.Char() + partner_bic = fields.Char() + + def get_statement_line_for_reconciliation_widget(self): + """ Returns the data required by the bank statement + reconciliation widget to display a statement line + """ + data = super(AccountBankStatementLine, + self).get_statement_line_for_reconciliation_widget() + if self.partner_address: + data['partner_address'] = self.partner_address + if self.partner_account: + data['partner_account'] = self.partner_account + + return data diff --git a/account_bank_statement_import_camt_details/models/camt_parser.py b/account_bank_statement_import_camt_details/models/camt_parser.py new file mode 100644 index 0000000..e4f8c8a --- /dev/null +++ b/account_bank_statement_import_camt_details/models/camt_parser.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +# © 2017 Compassion CH +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +from openerp import models +from openerp.tools import OrderedDict + + +class CamtDetailsParser(models.AbstractModel): + """Parser for camt bank statement import files.""" + _inherit = 'account.bank.statement.import.camt.parser' + + def parse_transaction_details(self, ns, node, transaction): + """Parse transaction details (message, party, account...).""" + super(CamtDetailsParser, self).parse_transaction_details( + ns, node, transaction) + + # remote party values + party_type = 'Dbtr' + party_type_node = node.xpath( + '../../ns:CdtDbtInd', namespaces={'ns': ns}) + if party_type_node and party_type_node[0].text != 'CRDT': + party_type = 'Cdtr' + address_node = node.xpath( + './ns:RltdPties/ns:%s/ns:PstlAdr' % party_type, + namespaces={'ns': ns}) + if address_node and not transaction.get('partner_address'): + address_values = OrderedDict() + street_node = address_node[0].xpath( + './ns:StrtNm', namespaces={'ns': ns}) + if street_node: + address_values['street'] = street_node[0].text + building_node = address_node[0].xpath( + './ns:BldgNb', namespaces={'ns': ns}) + if building_node: + address_values['building'] = building_node[0].text + zip_node = address_node[0].xpath( + './ns:PstCd', namespaces={'ns': ns}) + if zip_node: + address_values['zip'] = zip_node[0].text + city_node = address_node[0].xpath( + './ns:TwnNm', namespaces={'ns': ns}) + if city_node: + address_values['city'] = city_node[0].text + transaction['partner_address'] = self._format_partner_address( + address_values) + + # Transfer account info in fields + transaction['partner_account'] = transaction.get('account_number') + transaction['partner_bic'] = transaction.get('account_bic') + + def _format_partner_address(self, address_values): + """ + Hook for formatting the partner address read in CAMT bank statement. + :param address_values: dict: all address values found in statement + Possible keys are ['street', 'building', 'zip', 'city'] + Not all keys may be present. + :return: str: formatted address + """ + return ', '.join(address_values.values()) diff --git a/account_bank_statement_import_camt_details/static/src/xml/camt_details_reconciliation_layout.xml b/account_bank_statement_import_camt_details/static/src/xml/camt_details_reconciliation_layout.xml new file mode 100644 index 0000000..d2a1c96 --- /dev/null +++ b/account_bank_statement_import_camt_details/static/src/xml/camt_details_reconciliation_layout.xml @@ -0,0 +1,12 @@ + + + + + + Address + + + Partner account + + + diff --git a/account_bank_statement_import_camt_details/tests/__init__.py b/account_bank_statement_import_camt_details/tests/__init__.py new file mode 100644 index 0000000..58e0fd3 --- /dev/null +++ b/account_bank_statement_import_camt_details/tests/__init__.py @@ -0,0 +1,5 @@ +# -*- encoding: utf-8 -*- +"""Test import of bank statement for camt.053.""" +# © 2017 Compassion CH +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +from . import test_import_bank_statement diff --git a/account_bank_statement_import_camt_details/tests/test_import_bank_statement.py b/account_bank_statement_import_camt_details/tests/test_import_bank_statement.py new file mode 100644 index 0000000..167c140 --- /dev/null +++ b/account_bank_statement_import_camt_details/tests/test_import_bank_statement.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +# © 2017 CompassionCH +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +import base64 +from openerp.tests.common import TransactionCase +from openerp.tools.misc import file_open + + +class TestImport(TransactionCase): + """Run test to import camt import.""" + + def setUp(self): + super(TestImport, self).setUp() + bank = self.env['res.partner.bank'].create({ + 'acc_number': 'NL77ABNA0574908765', + '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 camt)', + 'code': 'TBNKCAMT', + 'type': 'bank', + 'bank_account_id': bank.id, + }) + + def test_statement_import(self): + """Test that transaction details are correctly imported.""" + line_details = [ + { + 'partner_account': 'NL46ABNA0499998748', + 'partner_bic': 'ABNANL2A', + 'partner_name': 'INSURANCE COMPANY TESTX', + 'partner_address': 'TEST STREET 20, 1234 AB TESTCITY' + }, + { + 'partner_account': 'NL46ABNA0499998748', + 'partner_bic': 'ABNANL2A', + 'partner_name': 'Test Customer', + }, + { + 'partner_account': 'NL69ABNA0522123643', + 'partner_bic': 'ABNANL2A', + 'partner_name': '3rd party Media', + 'partner_address': 'SOMESTREET 570-A, 1276 ML HOUSCITY' + }, + ] + with file_open( + 'account_bank_statement_import_camt/test_files/test-camt053' + ) as testfile: + action = self.env['account.bank.statement.import'].create({ + 'data_file': base64.b64encode(testfile.read()), + }).import_file() + statement_lines = self.env['account.bank.statement'].browse( + action['context']['statement_ids']).mapped('line_ids') + for i in range(0, len(line_details)): + line = statement_lines[i] + rec_data = line.get_statement_line_for_reconciliation_widget() + for key, val in line_details[i].iteritems(): + # test data is in reconcile data view + if key in ('partner_account', 'partner_address'): + self.assertEqual(val, rec_data.get(key)) + # test field is set in model + self.assertEqual(getattr(line, key), val) diff --git a/account_bank_statement_import_camt_details/views/account_bank_statement_line.xml b/account_bank_statement_import_camt_details/views/account_bank_statement_line.xml new file mode 100644 index 0000000..79d27ae --- /dev/null +++ b/account_bank_statement_import_camt_details/views/account_bank_statement_line.xml @@ -0,0 +1,17 @@ + + + + bank.statement.line.details + account.bank.statement.line + form + + + + + + + + + + +