From 5ab86ab755e042825fb6c870fc8051ba9dd12e21 Mon Sep 17 00:00:00 2001 From: Louis Bettens Date: Tue, 28 Mar 2017 14:01:27 +0200 Subject: [PATCH 1/4] more complete unit tests for camt parser This checks the whole output data of the parser against its expected output. --- .../test_files/golden-camt053.pydata | 44 +++++++++++++++++++ .../tests/test_import_bank_statement.py | 30 +++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 account_bank_statement_import_camt/test_files/golden-camt053.pydata diff --git a/account_bank_statement_import_camt/test_files/golden-camt053.pydata b/account_bank_statement_import_camt/test_files/golden-camt053.pydata new file mode 100644 index 0000000..053e4ff --- /dev/null +++ b/account_bank_statement_import_camt/test_files/golden-camt053.pydata @@ -0,0 +1,44 @@ +(None, + 'NL77ABNA0574908765', + [{'balance_end_real': 15121.12, + 'balance_start': 15568.27, + 'name': '1234Test/1', + 'transactions': [{'account_bic': 'ABNANL2A', + 'account_number': 'NL46ABNA0499998748', + 'amount': -754.25, + 'data': '\n 754.25\n DBIT\n BOOK\n \n
2014-01-05
\n
\n \n
2014-01-05
\n
\n \n \n PMNT\n \n RDDT\n ESDD\n \n \n \n EI\n \n \n \n \n \n INNDNL2U20141231000142300002844\n 435005714488-ABNO33052620\n 1880000341866\n \n \n \n 754.25\n \n \n \n \n INSURANCE COMPANY TESTX\n \n TEST STREET 20\n 1234 AB TESTCITY\n NL\n \n \n \n \n NL46ABNA0499998748\n \n \n \n \n \n \n ABNANL2A\n \n \n \n \n Insurance policy 857239PERIOD 01.01.2014 - 31.12.2014\n \n MKB Insurance 859239PERIOD 01.01.2014 - 31.12.2014\n \n \n
\n ', + 'date': '2014-01-05', + 'execution_date': '2014-01-05', + 'name': 'MKB Insurance 859239PERIOD 01.01.2014 - 31.12.2014', + 'note': 'Insurance policy 857239PERIOD 01.01.2014 - 31.12.2014', + 'partner_country': 'NL', + 'partner_name': 'INSURANCE COMPANY TESTX', + 'ref': '435005714488-ABNO33052620', + 'transfer_type': 'EI', + 'value_date': '2014-01-05'}, + {'account_bic': 'ABNANL2A', + 'account_number': 'NL46ABNA0499998748', + 'amount': -594.05, + 'data': '\n 594.05\n DBIT\n true\n BOOK\n \n
2014-01-05
\n
\n \n
2014-01-05
\n
\n \n \n PMNT\n \n IDDT\n UPDD\n \n \n \n EIST\n \n \n \n \n \n TESTBANK/NL/20141229/01206408\n TESTBANK/NL/20141229/01206408\n NL22ZZZ524885430000-C0125.1\n \n \n \n 564.05\n \n \n \n \n Test Customer\n \n NL\n \n \n \n \n NL46ABNA0499998748\n \n \n \n \n \n \n ABNANL2A\n \n \n \n \n Direct Debit S14 0410\n \n \n \n AC06\n \n \n Direct debit S14 0410 AC07 Rek.nummer blokkade TESTBANK/NL/20141229/01206408\n \n \n
\n ', + 'date': '2014-01-05', + 'execution_date': '2014-01-05', + 'name': 'Direct debit S14 0410 AC07 Rek.nummer blokkade TESTBANK/NL/20141229/01206408', + 'note': 'Direct Debit S14 0410', + 'partner_country': 'NL', + 'partner_name': 'Test Customer', + 'ref': 'TESTBANK/NL/20141229/01206408', + 'transfer_type': 'EIST', + 'value_date': '2014-01-05'}, + {'account_bic': 'ABNANL2A', + 'account_number': 'NL69ABNA0522123643', + 'amount': 1405.31, + 'data': '\n 1405.31\n CRDT\n BOOK\n \n
2014-01-05
\n
\n \n
2014-01-05
\n
\n \n \n PMNT\n \n RCDT\n ESCT\n \n \n \n ET\n \n \n \n \n \n INNDNL2U20140105000217200000708\n 115\n \n \n \n 1405.31\n \n \n \n \n 3rd party Media\n \n SOMESTREET 570-A\n 1276 ML HOUSCITY\n NL\n \n \n \n \n NL69ABNA0522123643\n \n \n \n \n \n \n ABNANL2A\n \n \n \n #RD PARTY MEDIA CUSNO 90782 4210773\n \n \n
\n ', + 'date': '2014-01-05', + 'execution_date': '2014-01-05', + 'name': '#RD PARTY MEDIA CUSNO 90782 4210773', + 'note': 'INNDNL2U20140105000217200000708', + 'partner_country': 'NL', + 'partner_name': '3rd party Media', + 'ref': '115', + 'transfer_type': 'ET', + 'value_date': '2014-01-05'}]}]) diff --git a/account_bank_statement_import_camt/tests/test_import_bank_statement.py b/account_bank_statement_import_camt/tests/test_import_bank_statement.py index b043e71..a3dabdb 100644 --- a/account_bank_statement_import_camt/tests/test_import_bank_statement.py +++ b/account_bank_statement_import_camt/tests/test_import_bank_statement.py @@ -1,12 +1,42 @@ # -*- coding: utf-8 -*- """Run test to import camt.053 import.""" # © 2013-2016 Therp BV +# Copyright 2017 Open Net Sàrl # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). import base64 +import difflib +import pprint +import tempfile from openerp.tests.common import TransactionCase from openerp.tools.misc import file_open +class TestParser(TransactionCase): + """Tests for the camt parser itself.""" + def setUp(self): + super(TestParser, self).setUp() + self.parser = self.env['account.bank.statement.import.camt.parser'] + + def test_parse(self): + with file_open( + 'account_bank_statement_import_camt/test_files/test-camt053' + ) as testfile: + data = testfile.read() + res = self.parser.parse(data) + with tempfile.NamedTemporaryFile(suffix='.pydata') as temp: + pprint.pprint(res, temp) + with file_open('account_bank_statement_import_camt/test_files/' + 'golden-camt053.pydata') as golden: + temp.seek(0) + diff = list( + difflib.unified_diff(golden.readlines(), temp.readlines(), + golden.name, temp.name)) + if len(diff) > 2: + self.fail( + "actual output doesn't match exptected output:\n%s" % + "".join(diff)) + + class TestImport(TransactionCase): """Run test to import camt import.""" transactions = [ From a68979260f33e2737351a5afdfc52a1da86ab469 Mon Sep 17 00:00:00 2001 From: Louis Bettens Date: Tue, 28 Mar 2017 11:00:41 +0200 Subject: [PATCH 2/4] correctly parse entries with multiple transactions Our bank does it. Care has been taken not to break cases where Ntry/NtryDtls/TxDtls isn't used: if any piece of information isn't found on these nodes, the matching information from the Ntry is used. Most often the entry has a sum or a summary and the transaction details are more precise and specific, so it makes sense to use their contents rather than its. --- .../models/parser.py | 61 ++++++++++--------- 1 file changed, 32 insertions(+), 29 deletions(-) diff --git a/account_bank_statement_import_camt/models/parser.py b/account_bank_statement_import_camt/models/parser.py index 8e685b2..7eb0920 100644 --- a/account_bank_statement_import_camt/models/parser.py +++ b/account_bank_statement_import_camt/models/parser.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- """Class to parse camt files.""" # © 2013-2016 Therp BV +# Copyright 2017 Open Net Sàrl # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). import re from lxml import etree @@ -46,7 +47,7 @@ class CamtParser(models.AbstractModel): break def parse_transaction_details(self, ns, node, transaction): - """Parse transaction details (message, party, account...).""" + """Parse TxDtls node.""" # message self.add_value_from_node( ns, node, [ @@ -67,6 +68,9 @@ class CamtParser(models.AbstractModel): ], transaction, 'ref' ) + amount = self.parse_amount(ns, node) + if amount != 0.0: + transaction['amount'] = amount # remote party values party_type = 'Dbtr' party_type_node = node.xpath( @@ -107,10 +111,11 @@ class CamtParser(models.AbstractModel): ns, account_node[0], './ns:Othr/ns:Id', transaction, 'account_number' ) + transaction['data'] = etree.tostring(node) - def parse_transaction(self, ns, node): - """Parse transaction (entry) node.""" - transaction = {} + def parse_entry(self, ns, node): + """Parse an Ntry node and yield transactions""" + transaction = {'name': '/', 'amount': 0} # fallback defaults self.add_value_from_node( ns, node, './ns:BkTxCd/ns:Prtry/ns:Cd', transaction, 'transfer_type' @@ -121,27 +126,26 @@ class CamtParser(models.AbstractModel): ns, node, './ns:BookgDt/ns:Dt', transaction, 'execution_date') self.add_value_from_node( ns, node, './ns:ValDt/ns:Dt', transaction, 'value_date') + amount = self.parse_amount(ns, node) + if amount != 0.0: + transaction['amount'] = amount + self.add_value_from_node( + ns, node, './ns:AddtlNtryInf', transaction, 'name') + self.add_value_from_node( + ns, node, [ + './ns:NtryDtls/ns:RmtInf/ns:Strd/ns:CdtrRefInf/ns:Ref', + './ns:NtryDtls/ns:Btch/ns:PmtInfId', + ], + transaction, 'ref' + ) - transaction['amount'] = self.parse_amount(ns, node) - - details_node = node.xpath( + details_nodes = node.xpath( './ns:NtryDtls/ns:TxDtls', namespaces={'ns': ns}) - if details_node: - self.parse_transaction_details(ns, details_node[0], transaction) - if not transaction.get('name'): - self.add_value_from_node( - ns, node, './ns:AddtlNtryInf', transaction, 'name') - if not transaction.get('name'): - transaction['name'] = '/' - if not transaction.get('ref'): - self.add_value_from_node( - ns, node, [ - './ns:NtryDtls/ns:Btch/ns:PmtInfId', - ], - transaction, 'ref' - ) - transaction['data'] = etree.tostring(node) - return transaction + transaction_base = transaction + for node in details_nodes: + transaction = transaction_base.copy() + self.parse_transaction_details(ns, node, transaction) + yield transaction def get_balance_amounts(self, ns, node): """Return opening and closing balance. @@ -193,12 +197,11 @@ class CamtParser(models.AbstractModel): ns, node, './ns:Acct/ns:Ccy', result, 'currency') result['balance_start'], result['balance_end_real'] = ( self.get_balance_amounts(ns, node)) - transaction_nodes = node.xpath('./ns:Ntry', namespaces={'ns': ns}) - result['transactions'] = [] - for entry_node in transaction_nodes: - transaction = self.parse_transaction(ns, entry_node) - if transaction: - result['transactions'].append(transaction) + entry_nodes = node.xpath('./ns:Ntry', namespaces={'ns': ns}) + transactions = [] + for entry_node in entry_nodes: + transactions.extend(self.parse_entry(ns, entry_node)) + result['transactions'] = transactions return result def check_version(self, ns, root): From 7bfdfa4ce71c9a4fe3484802012cf0afd2113fab Mon Sep 17 00:00:00 2001 From: Louis Bettens Date: Tue, 28 Mar 2017 16:23:34 +0200 Subject: [PATCH 3/4] add a test case that checks TxDtls decoding --- .../test_files/golden-camt053-txdtls.pydata | 25 ++ .../test_files/golden-camt053.pydata | 6 +- .../test_files/test-camt053-txdtls | 214 ++++++++++++++++++ .../tests/test_import_bank_statement.py | 26 ++- 4 files changed, 259 insertions(+), 12 deletions(-) create mode 100644 account_bank_statement_import_camt/test_files/golden-camt053-txdtls.pydata create mode 100644 account_bank_statement_import_camt/test_files/test-camt053-txdtls diff --git a/account_bank_statement_import_camt/test_files/golden-camt053-txdtls.pydata b/account_bank_statement_import_camt/test_files/golden-camt053-txdtls.pydata new file mode 100644 index 0000000..0a274e5 --- /dev/null +++ b/account_bank_statement_import_camt/test_files/golden-camt053-txdtls.pydata @@ -0,0 +1,25 @@ +(None, + 'CH1111000000123456789', + [{'balance_end_real': 79443.15, + 'balance_start': 75960.15, + 'name': '20170323123456789012345', + 'transactions': [{'account_number': 'CH2222000000123456789', + 'amount': 2187.0, + 'data': '\n \n 123456CHCAFEBABE\n \n 01\n 123456CHCAFEBABE\n \n \n 2187.00\n CRDT\n \n \n PMNT\n \n RCDT\n AUTT\n \n \n \n \n \n Banque Cantonale Vaudoise\n \n Place Saint-François\n 14\n 1003\n Lausanne\n CH1\n \n \n \n \n CH2222000000123456789\n \n \n \n \n \n \n POFICHBEXXX\n POSTFINANCE AG\n \n MINGERSTRASSE 20\n 3030 BERNE\n \n \n \n \n \n \n \n \n \n ISR Reference\n \n \n 302388292000011111111111111\n \n ?REJECT?0\n \n \n \n 2017-03-22T20:00:00\n \n \n ', + 'date': '2017-03-22', + 'execution_date': '2017-03-22', + 'name': u'CR\xc9DIT GROUP\xc9 BVR TRAITEMENT DU 22.03.2017 NUM\xc9RO CLIENT 01-70884-3 PAQUET ID: 123456CHCAFEBABE', + 'partner_country': 'CH1', + 'partner_name': 'Banque Cantonale Vaudoise', + 'ref': '302388292000011111111111111', + 'value_date': '2017-03-23'}, + {'account_number': 'CH3333000000123456789', + 'amount': 1296.0, + 'data': '\n \n 123456CHCAFEBABE\n \n 01\n 123456CHCAFEBABE\n \n \n 1296.00\n CRDT\n \n \n PMNT\n \n RCDT\n AUTT\n \n \n \n \n \n Banque Cantonale Vaudoise\n \n Place Saint-François\n 14\n 1003\n Lausanne\n CH2\n \n \n \n \n CH3333000000123456789\n \n \n \n \n \n \n POFICHBEYYY\n POSTFINANCE AG\n \n MINGERSTRASSE 20\n 3030 BERNE\n \n \n \n \n \n \n \n \n \n ISR Reference\n \n \n 302388292000022222222222222\n \n ?REJECT?0\n \n \n \n 2017-03-22T20:00:00\n \n \n ', + 'date': '2017-03-22', + 'execution_date': '2017-03-22', + 'name': u'CR\xc9DIT GROUP\xc9 BVR TRAITEMENT DU 22.03.2017 NUM\xc9RO CLIENT 01-70884-3 PAQUET ID: 123456CHCAFEBABE', + 'partner_country': 'CH2', + 'partner_name': 'Banque Cantonale Vaudoise', + 'ref': '302388292000022222222222222', + 'value_date': '2017-03-23'}]}]) diff --git a/account_bank_statement_import_camt/test_files/golden-camt053.pydata b/account_bank_statement_import_camt/test_files/golden-camt053.pydata index 053e4ff..dcc56be 100644 --- a/account_bank_statement_import_camt/test_files/golden-camt053.pydata +++ b/account_bank_statement_import_camt/test_files/golden-camt053.pydata @@ -6,7 +6,7 @@ 'transactions': [{'account_bic': 'ABNANL2A', 'account_number': 'NL46ABNA0499998748', 'amount': -754.25, - 'data': '\n 754.25\n DBIT\n BOOK\n \n
2014-01-05
\n
\n \n
2014-01-05
\n
\n \n \n PMNT\n \n RDDT\n ESDD\n \n \n \n EI\n \n \n \n \n \n INNDNL2U20141231000142300002844\n 435005714488-ABNO33052620\n 1880000341866\n \n \n \n 754.25\n \n \n \n \n INSURANCE COMPANY TESTX\n \n TEST STREET 20\n 1234 AB TESTCITY\n NL\n \n \n \n \n NL46ABNA0499998748\n \n \n \n \n \n \n ABNANL2A\n \n \n \n \n Insurance policy 857239PERIOD 01.01.2014 - 31.12.2014\n \n MKB Insurance 859239PERIOD 01.01.2014 - 31.12.2014\n \n \n
\n ', + 'data': '\n \n INNDNL2U20141231000142300002844\n 435005714488-ABNO33052620\n 1880000341866\n \n \n \n 754.25\n \n \n \n \n INSURANCE COMPANY TESTX\n \n TEST STREET 20\n 1234 AB TESTCITY\n NL\n \n \n \n \n NL46ABNA0499998748\n \n \n \n \n \n \n ABNANL2A\n \n \n \n \n Insurance policy 857239PERIOD 01.01.2014 - 31.12.2014\n \n MKB Insurance 859239PERIOD 01.01.2014 - 31.12.2014\n \n ', 'date': '2014-01-05', 'execution_date': '2014-01-05', 'name': 'MKB Insurance 859239PERIOD 01.01.2014 - 31.12.2014', @@ -19,7 +19,7 @@ {'account_bic': 'ABNANL2A', 'account_number': 'NL46ABNA0499998748', 'amount': -594.05, - 'data': '\n 594.05\n DBIT\n true\n BOOK\n \n
2014-01-05
\n
\n \n
2014-01-05
\n
\n \n \n PMNT\n \n IDDT\n UPDD\n \n \n \n EIST\n \n \n \n \n \n TESTBANK/NL/20141229/01206408\n TESTBANK/NL/20141229/01206408\n NL22ZZZ524885430000-C0125.1\n \n \n \n 564.05\n \n \n \n \n Test Customer\n \n NL\n \n \n \n \n NL46ABNA0499998748\n \n \n \n \n \n \n ABNANL2A\n \n \n \n \n Direct Debit S14 0410\n \n \n \n AC06\n \n \n Direct debit S14 0410 AC07 Rek.nummer blokkade TESTBANK/NL/20141229/01206408\n \n \n
\n ', + 'data': '\n \n TESTBANK/NL/20141229/01206408\n TESTBANK/NL/20141229/01206408\n NL22ZZZ524885430000-C0125.1\n \n \n \n 564.05\n \n \n \n \n Test Customer\n \n NL\n \n \n \n \n NL46ABNA0499998748\n \n \n \n \n \n \n ABNANL2A\n \n \n \n \n Direct Debit S14 0410\n \n \n \n AC06\n \n \n Direct debit S14 0410 AC07 Rek.nummer blokkade TESTBANK/NL/20141229/01206408\n \n ', 'date': '2014-01-05', 'execution_date': '2014-01-05', 'name': 'Direct debit S14 0410 AC07 Rek.nummer blokkade TESTBANK/NL/20141229/01206408', @@ -32,7 +32,7 @@ {'account_bic': 'ABNANL2A', 'account_number': 'NL69ABNA0522123643', 'amount': 1405.31, - 'data': '\n 1405.31\n CRDT\n BOOK\n \n
2014-01-05
\n
\n \n
2014-01-05
\n
\n \n \n PMNT\n \n RCDT\n ESCT\n \n \n \n ET\n \n \n \n \n \n INNDNL2U20140105000217200000708\n 115\n \n \n \n 1405.31\n \n \n \n \n 3rd party Media\n \n SOMESTREET 570-A\n 1276 ML HOUSCITY\n NL\n \n \n \n \n NL69ABNA0522123643\n \n \n \n \n \n \n ABNANL2A\n \n \n \n #RD PARTY MEDIA CUSNO 90782 4210773\n \n \n
\n ', + 'data': '\n \n INNDNL2U20140105000217200000708\n 115\n \n \n \n 1405.31\n \n \n \n \n 3rd party Media\n \n SOMESTREET 570-A\n 1276 ML HOUSCITY\n NL\n \n \n \n \n NL69ABNA0522123643\n \n \n \n \n \n \n ABNANL2A\n \n \n \n #RD PARTY MEDIA CUSNO 90782 4210773\n \n ', 'date': '2014-01-05', 'execution_date': '2014-01-05', 'name': '#RD PARTY MEDIA CUSNO 90782 4210773', diff --git a/account_bank_statement_import_camt/test_files/test-camt053-txdtls b/account_bank_statement_import_camt/test_files/test-camt053-txdtls new file mode 100644 index 0000000..cf7c38f --- /dev/null +++ b/account_bank_statement_import_camt/test_files/test-camt053-txdtls @@ -0,0 +1,214 @@ + + + + + 20170323312345678900000 + 2017-03-23T14:47:00 + + 1 + true + + Test + + + 20170323123456789012345 + 58 + 2017-03-23T14:47:00 + + 2017-03-23T00:00:00 + 2017-03-23T23:59:59 + + + + CH1111000000123456789 + + + Open Net S. à r.l. Prilly + + + + + + OPBD + + + 75960.15 + CRDT +
+
2017-03-22
+ +
+ + + + CLBD + + + 79443.15 + CRDT +
+
2017-03-23
+ +
+ + 012345678 + 3483.00 + CRDT + false + BOOK + +
2017-03-22
+
+ +
2017-03-23
+
+ 20170323001234567891234567891234 + + + PMNT + + RCDT + VCOM + + + + + + 2 + + + + 123456CHCAFEBABE + + 01 + 123456CHCAFEBABE + + + 2187.00 + CRDT + + + PMNT + + RCDT + AUTT + + + + + + Banque Cantonale Vaudoise + + Place Saint-François + 14 + 1003 + Lausanne + CH1 + + + + + CH2222000000123456789 + + + + + + + POFICHBEXXX + POSTFINANCE AG + + MINGERSTRASSE 20 + 3030 BERNE + + + + + + + + + + ISR Reference + + + 302388292000011111111111111 + + ?REJECT?0 + + + + 2017-03-22T20:00:00 + + + + + 123456CHCAFEBABE + + 01 + 123456CHCAFEBABE + + + 1296.00 + CRDT + + + PMNT + + RCDT + AUTT + + + + + + Banque Cantonale Vaudoise + + Place Saint-François + 14 + 1003 + Lausanne + CH2 + + + + + CH3333000000123456789 + + + + + + + POFICHBEYYY + POSTFINANCE AG + + MINGERSTRASSE 20 + 3030 BERNE + + + + + + + + + + ISR Reference + + + 302388292000022222222222222 + + ?REJECT?0 + + + + 2017-03-22T20:00:00 + + + + CRÉDIT GROUPÉ BVR TRAITEMENT DU 22.03.2017 NUMÉRO CLIENT 01-70884-3 PAQUET ID: 123456CHCAFEBABE +
+
+
+
diff --git a/account_bank_statement_import_camt/tests/test_import_bank_statement.py b/account_bank_statement_import_camt/tests/test_import_bank_statement.py index a3dabdb..e01cbc3 100644 --- a/account_bank_statement_import_camt/tests/test_import_bank_statement.py +++ b/account_bank_statement_import_camt/tests/test_import_bank_statement.py @@ -11,22 +11,22 @@ from openerp.tests.common import TransactionCase from openerp.tools.misc import file_open +DATA_DIR = 'account_bank_statement_import_camt/test_files/' + + class TestParser(TransactionCase): """Tests for the camt parser itself.""" def setUp(self): super(TestParser, self).setUp() self.parser = self.env['account.bank.statement.import.camt.parser'] - def test_parse(self): - with file_open( - 'account_bank_statement_import_camt/test_files/test-camt053' - ) as testfile: + def _do_parse_test(self, inputfile, goldenfile): + with file_open(inputfile) as testfile: data = testfile.read() res = self.parser.parse(data) with tempfile.NamedTemporaryFile(suffix='.pydata') as temp: pprint.pprint(res, temp) - with file_open('account_bank_statement_import_camt/test_files/' - 'golden-camt053.pydata') as golden: + with file_open(goldenfile) as golden: temp.seek(0) diff = list( difflib.unified_diff(golden.readlines(), temp.readlines(), @@ -36,6 +36,16 @@ class TestParser(TransactionCase): "actual output doesn't match exptected output:\n%s" % "".join(diff)) + def test_parse(self): + self._do_parse_test( + DATA_DIR + 'test-camt053', + DATA_DIR + 'golden-camt053.pydata') + + def test_parse_txdtls(self): + self._do_parse_test( + DATA_DIR + 'test-camt053-txdtls', + DATA_DIR + 'golden-camt053-txdtls.pydata') + class TestImport(TransactionCase): """Run test to import camt import.""" @@ -66,9 +76,7 @@ class TestImport(TransactionCase): def test_statement_import(self): """Test correct creation of single statement.""" action = {} - with file_open( - 'account_bank_statement_import_camt/test_files/test-camt053' - ) as testfile: + with file_open(DATA_DIR + 'test-camt053') as testfile: action = self.env['account.bank.statement.import'].create({ 'data_file': base64.b64encode(testfile.read()), }).import_file() From 7bc64b9bd03f24b5409f600d8e0e39121c0ab27a Mon Sep 17 00:00:00 2001 From: Louis Bettens Date: Thu, 4 May 2017 14:35:56 +0200 Subject: [PATCH 4/4] special case for Ntrys without TxDtls --- account_bank_statement_import_camt/models/parser.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/account_bank_statement_import_camt/models/parser.py b/account_bank_statement_import_camt/models/parser.py index 7eb0920..e485172 100644 --- a/account_bank_statement_import_camt/models/parser.py +++ b/account_bank_statement_import_camt/models/parser.py @@ -141,6 +141,9 @@ class CamtParser(models.AbstractModel): details_nodes = node.xpath( './ns:NtryDtls/ns:TxDtls', namespaces={'ns': ns}) + if len(details_nodes) == 0: + yield transaction + return transaction_base = transaction for node in details_nodes: transaction = transaction_base.copy()