Emanuel Cino
8 years ago
10 changed files with 261 additions and 0 deletions
-
48account_bank_statement_import_camt_details/README.rst
-
4account_bank_statement_import_camt_details/__init__.py
-
20account_bank_statement_import_camt_details/__openerp__.py
-
5account_bank_statement_import_camt_details/models/__init__.py
-
27account_bank_statement_import_camt_details/models/account_bank_statement_line.py
-
59account_bank_statement_import_camt_details/models/camt_parser.py
-
12account_bank_statement_import_camt_details/static/src/xml/camt_details_reconciliation_layout.xml
-
5account_bank_statement_import_camt_details/tests/__init__.py
-
64account_bank_statement_import_camt_details/tests/test_import_bank_statement.py
-
17account_bank_statement_import_camt_details/views/account_bank_statement_line.xml
@ -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 <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**>`_. |
||||
|
|
||||
|
|
||||
|
Credits |
||||
|
======= |
||||
|
|
||||
|
Contributors |
||||
|
------------ |
||||
|
|
||||
|
* Emanuel Cino <ecino@compassion.ch> |
||||
|
|
||||
|
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. |
@ -0,0 +1,4 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# © 2017 Compassion CH <http://www.compassion.ch> |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
from . import models |
@ -0,0 +1,20 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# © 2017 Compassion CH <http://www.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', |
||||
|
] |
||||
|
} |
@ -0,0 +1,5 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# © 2017 Compassion CH <http://www.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 |
@ -0,0 +1,27 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
"""Add process_camt method to account.bank.statement.import.""" |
||||
|
# © 2017 Compassion CH <http://www.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 |
@ -0,0 +1,59 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# © 2017 Compassion CH <http://www.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()) |
@ -0,0 +1,12 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8" ?> |
||||
|
<templates id="template" xml:space="preserve"> |
||||
|
<t t-extend="bank_statement_reconciliation_statement_line_details"> |
||||
|
|
||||
|
<t t-jquery="table.details > tr:nth-child(2)" t-operation="after"> |
||||
|
<tr t-if="line.partner_address"><td>Address</td><td><t t-esc="line.partner_address"/></td></tr> |
||||
|
</t> |
||||
|
<t t-jquery="table.details > tr:nth-child(6)" t-operation="after"> |
||||
|
<tr t-if="line.partner_account"><td>Partner account</td><td><t t-esc="line.partner_account"/></td></tr> |
||||
|
</t> |
||||
|
</t> |
||||
|
</templates> |
@ -0,0 +1,5 @@ |
|||||
|
# -*- encoding: utf-8 -*- |
||||
|
"""Test import of bank statement for camt.053.""" |
||||
|
# © 2017 Compassion CH <http://www.compassion.ch> |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
from . import test_import_bank_statement |
@ -0,0 +1,64 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# © 2017 CompassionCH <http://therp.nl> |
||||
|
# 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) |
@ -0,0 +1,17 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<odoo> |
||||
|
<record id="statement_line_details" model="ir.ui.view"> |
||||
|
<field name="name">bank.statement.line.details</field> |
||||
|
<field name="model">account.bank.statement.line</field> |
||||
|
<field name="type">form</field> |
||||
|
<field name="inherit_id" ref="account.view_bank_statement_line_form" /> |
||||
|
<field name="arch" type="xml"> |
||||
|
<field name="partner_id" position="after"> |
||||
|
<field name="partner_name"/> |
||||
|
<field name="partner_account"/> |
||||
|
<field name="partner_address"/> |
||||
|
<field name="partner_bic"/> |
||||
|
</field> |
||||
|
</field> |
||||
|
</record> |
||||
|
</odoo> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue