Browse Source

[11.0][MIG] account_bank_statement_import_camt

pull/134/head
Andrea 7 years ago
parent
commit
83b5d6483c
  1. 28
      account_bank_statement_import_camt/README.rst
  2. 1
      account_bank_statement_import_camt/__init__.py
  3. 3
      account_bank_statement_import_camt/__manifest__.py
  4. 1
      account_bank_statement_import_camt/models/__init__.py
  5. 5
      account_bank_statement_import_camt/models/account_bank_statement_import.py
  6. 45
      account_bank_statement_import_camt/models/parser.py
  7. 1
      account_bank_statement_import_camt/tests/__init__.py
  8. 61
      account_bank_statement_import_camt/tests/test_import_bank_statement.py

28
account_bank_statement_import_camt/README.rst

@ -1,25 +1,28 @@
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
.. image:: https://img.shields.io/badge/license-AGPL--3-blue.png
:target: https://www.gnu.org/licenses/agpl
:alt: License: AGPL-3
=========================
Bank Statement Parse Camt
=========================
Module to import SEPA CAMT.053 Format bank statement files.
Module to import SEPA CAMT.053 and CAMT.054 Format bank statement files.
Based on the Banking addons framework.
Known issues / Roadmap
======================
* None
.. 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/11.0
Bug Tracker
===========
Bugs are tracked on `GitHub Issues <https://github.com/OCA/bank-statement-import/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 <https://github.com/OCA/bank-statement-import/issues/new?body=module:%20account_bank_statement_import%0Aversion:%208.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
Bugs are tracked on `GitHub Issues
<https://github.com/OCA/bank-statement-import/issues>`_. In case of trouble, please
check there if your issue has already been reported. If you spotted it first,
help us smash it by providing detailed and welcomed feedback.
Credits
@ -31,6 +34,9 @@ Contributors
* Holger Brunn <hbrunn@therp.nl>
* Stefan Rijnhart <srijnhart@therp.nl>
* Ronald Portier <rportier@therp.nl>
* Andrea Stirpe <a.stirpe@onestein.nl>
Do not contact contributors directly about support or help with technical issues.
Maintainer
----------
@ -45,6 +51,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.
This module should make it easy to migrate bank statement import
modules written for earlies versions of Odoo/OpenERP.
To contribute to this module, please visit https://odoo-community.org.

1
account_bank_statement_import_camt/__init__.py

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# © 2013-2016 Therp BV <http://therp.nl>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from . import models

3
account_bank_statement_import_camt/__manifest__.py

@ -1,9 +1,8 @@
# -*- coding: utf-8 -*-
# © 2013-2017 Therp BV <http://therp.nl>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
{
'name': 'CAMT Format Bank Statements Import',
'version': '10.0.1.1.0',
'version': '11.0.1.0.0',
'license': 'AGPL-3',
'author': 'Odoo Community Association (OCA), Therp BV',
'website': 'https://github.com/OCA/bank-statement-import',

1
account_bank_statement_import_camt/models/__init__.py

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# © 2013-2016 Therp BV <http://therp.nl>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from . import parser

5
account_bank_statement_import_camt/models/account_bank_statement_import.py

@ -1,9 +1,8 @@
# -*- coding: utf-8 -*-
"""Add process_camt method to account.bank.statement.import."""
# © 2013-2016 Therp BV <http://therp.nl>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
import logging
import StringIO
from io import BytesIO
import zipfile
from odoo import api, models
@ -23,7 +22,7 @@ class AccountBankStatementImport(models.TransientModel):
return parser.parse(data_file)
except ValueError:
try:
with zipfile.ZipFile(StringIO.StringIO(data_file)) as data:
with zipfile.ZipFile(BytesIO(data_file)) as data:
currency = None
account_number = None
transactions = []

45
account_bank_statement_import_camt/models/parser.py

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
"""Class to parse camt files."""
# © 2013-2016 Therp BV <http://therp.nl>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
@ -9,8 +8,8 @@ from odoo import models
class CamtParser(models.AbstractModel):
_name = 'account.bank.statement.import.camt.parser'
"""Parser for camt bank statement import files."""
_name = 'account.bank.statement.import.camt.parser'
def parse_amount(self, ns, node):
"""Parse element that contains Amount and CreditDebitIndicator."""
@ -78,10 +77,6 @@ class CamtParser(models.AbstractModel):
if party_node:
self.add_value_from_node(
ns, party_node[0], './ns:Nm', transaction, 'partner_name')
self.add_value_from_node(
ns, party_node[0], './ns:PstlAdr/ns:Ctry', transaction,
'partner_country'
)
address_node = party_node[0].xpath(
'./ns:PstlAdr/ns:AdrLine', namespaces={'ns': ns})
if address_node:
@ -96,12 +91,6 @@ class CamtParser(models.AbstractModel):
'./ns:IBAN', namespaces={'ns': ns})
if iban_node:
transaction['account_number'] = iban_node[0].text
bic_node = node.xpath(
'./ns:RltdAgts/ns:%sAgt/ns:FinInstnId/ns:BIC' % party_type,
namespaces={'ns': ns}
)
if bic_node:
transaction['account_bic'] = bic_node[0].text
else:
self.add_value_from_node(
ns, account_node[0], './ns:Othr/ns:Id', transaction,
@ -111,16 +100,12 @@ class CamtParser(models.AbstractModel):
def parse_transaction(self, ns, node):
"""Parse transaction (entry) node."""
transaction = {}
self.add_value_from_node(
ns, node, './ns:BkTxCd/ns:Prtry/ns:Cd', transaction,
'transfer_type'
)
self.add_value_from_node(
ns, node, './ns:BookgDt/ns:Dt', transaction, 'date')
if not transaction.get('date'):
self.add_value_from_node(
ns, node, './ns:BookgDt/ns:Dt', transaction, 'execution_date')
self.add_value_from_node(
ns, node, './ns:ValDt/ns:Dt', transaction, 'value_date')
ns, node, './ns:ValDt/ns:Dt', transaction, 'date')
transaction['amount'] = self.parse_amount(ns, node)
@ -140,7 +125,7 @@ class CamtParser(models.AbstractModel):
],
transaction, 'ref'
)
transaction['data'] = etree.tostring(node)
return transaction
def get_balance_amounts(self, ns, node):
@ -176,6 +161,19 @@ class CamtParser(models.AbstractModel):
self.parse_amount(ns, end_balance_node)
)
def get_statement_date(self, ns, node):
"""Return statement date.
The date might be in the balance node:
CLBD = ClosingBalance
"""
code_expr = \
'./ns:Bal/ns:Tp/ns:CdOrPrtry/ns:Cd[text()="CLBD"]' \
'/../../../ns:Dt/ns:Dt/text()'
date_node = node.xpath(code_expr, namespaces={'ns': ns})
date = date_node and date_node[0] or None
return date
def parse_statement(self, ns, node):
"""Parse a single Stmt node."""
result = {}
@ -193,6 +191,7 @@ 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))
result['date'] = self.get_statement_date(ns, node)
transaction_nodes = node.xpath('./ns:Ntry', namespaces={'ns': ns})
result['transactions'] = []
for entry_node in transaction_nodes:
@ -210,10 +209,12 @@ class CamtParser(models.AbstractModel):
)
if not re_camt.search(ns):
raise ValueError('no camt: ' + ns)
# Check wether version 052 or 053:
# Check wether version 052 ,053 or 054:
re_camt_version = re.compile(
r'(^urn:iso:std:iso:20022:tech:xsd:camt.053.'
r'(^urn:iso:std:iso:20022:tech:xsd:camt.054.'
r'|^urn:iso:std:iso:20022:tech:xsd:camt.053.'
r'|^urn:iso:std:iso:20022:tech:xsd:camt.052.'
r'|^ISO:camt.054.'
r'|^ISO:camt.053.'
r'|^ISO:camt.052.)'
)

1
account_bank_statement_import_camt/tests/__init__.py

@ -1,4 +1,3 @@
# -*- encoding: utf-8 -*-
"""Test import of bank statement for camt.053."""
# © 2013-2016 Therp BV <http://therp.nl>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

61
account_bank_statement_import_camt/tests/test_import_bank_statement.py

@ -1,22 +1,13 @@
# -*- coding: utf-8 -*-
"""Run test to import camt.053 import."""
# © 2013-2016 Therp BV <http://therp.nl>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
import base64
from odoo.tests.common import TransactionCase
from odoo.tools.misc import file_open
from odoo.modules.module import get_module_resource
class TestImport(TransactionCase):
"""Run test to import camt import."""
transactions = [
{
'account_number': 'NL46ABNA0499998748',
'amount': -754.25,
'date': '2014-01-05',
'ref': '435005714488-ABNO33052620',
},
]
def setUp(self):
super(TestImport, self).setUp()
@ -35,33 +26,47 @@ 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:
testfile = get_module_resource(
'account_bank_statement_import_camt',
'test_files',
'test-camt053',
)
datafile = open(testfile, 'rb').read()
action = self.env['account.bank.statement.import'].create({
'data_file': base64.b64encode(testfile.read()),
'data_file': base64.b64encode(datafile),
}).import_file()
for statement in self.env['account.bank.statement'].browse(
action['context']['statement_ids']
):
self.assertTrue(any(
all(
line[key] == self.transactions[0][key]
for key in ['amount', 'date', 'ref']
) and
line.bank_account_id.acc_number ==
self.transactions[0]['account_number']
for line in statement.line_ids
))
self.assertTrue(statement.name)
self.assertEqual(statement.date, '2014-01-05')
self.assertEqual(statement.difference, -504.16)
self.assertEqual(statement.journal_type, 'bank')
self.assertEqual(len(statement.line_ids), 3)
for line in statement.line_ids:
self.assertIn(line.amount, [1405.31, -594.05, -754.25])
self.assertEqual(line.date, '2014-01-05')
self.assertTrue(line.ref)
self.assertTrue(line.journal_id)
self.assertTrue(line.name)
self.assertTrue(line.note)
self.assertEqual(line.state, 'open')
self.assertIn(
line.bank_account_id.acc_number,
['NL69ABNA0522123643',
'NL46ABNA0499998748']
)
def test_zip_import(self):
"""Test import of multiple statements from zip file."""
with file_open(
'account_bank_statement_import_camt/test_files/test-camt053.zip'
) as testfile:
testfile = get_module_resource(
'account_bank_statement_import_camt',
'test_files',
'test-camt053.zip',
)
datafile = open(testfile, 'rb').read()
action = self.env['account.bank.statement.import'].create({
'data_file': base64.b64encode(testfile.read()),
'data_file': base64.b64encode(datafile),
}).import_file()
for statement in self.env['account.bank.statement'].browse(
action['context']['statement_ids']

Loading…
Cancel
Save