Fekete Mihai
9 years ago
9 changed files with 327 additions and 0 deletions
-
65account_bank_statement_import_mt940_ro_brd/README.rst
-
5account_bank_statement_import_mt940_ro_brd/__init__.py
-
20account_bank_statement_import_mt940_ro_brd/__openerp__.py
-
28account_bank_statement_import_mt940_ro_brd/account_bank_statement_import.py
-
26account_bank_statement_import_mt940_ro_brd/demo/demo_data.xml
-
143account_bank_statement_import_mt940_ro_brd/mt940.py
-
17account_bank_statement_import_mt940_ro_brd/test_files/test-brd.940
-
5account_bank_statement_import_mt940_ro_brd/tests/__init__.py
-
18account_bank_statement_import_mt940_ro_brd/tests/test_import_bank_statement.py
@ -0,0 +1,65 @@ |
|||
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg |
|||
:alt: License: AGPL-3 |
|||
|
|||
Import MT940 ROMANIAN BRD Bank Statements |
|||
========================================= |
|||
|
|||
This module allows you to import the MT940 files from the Romanian BRD bank |
|||
in Odoo as bank statements. |
|||
|
|||
Installation |
|||
============ |
|||
|
|||
To install this module, you need to: |
|||
|
|||
* clone the branch 8.0 of the repository https://github.com/OCA/bank-statement-import |
|||
* add the path to this repository in your configuration (addons-path) |
|||
* update the module list |
|||
* search for "MT940 BRD Format Bank Statements Import" in your addons |
|||
* install the module |
|||
|
|||
Known issues / Roadmap |
|||
====================== |
|||
|
|||
* None |
|||
|
|||
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/8.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_mt940_ro_brd%0Aversion:%208.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_. |
|||
|
|||
|
|||
Credits |
|||
======= |
|||
|
|||
Contributors |
|||
------------ |
|||
|
|||
* Fekete Mihai <feketemihai@gmail.com> |
|||
|
|||
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,5 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# © 2016 Forest and Biomass Services Romania |
|||
# See README.rst file on addons root folder for license details |
|||
|
|||
from . import account_bank_statement_import |
@ -0,0 +1,20 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# © 2016 Forest and Biomass Services Romania |
|||
# See README.rst file on addons root folder for license details |
|||
{ |
|||
'name': 'MT940 BRD Format Bank Statements Import', |
|||
'version': '8.0.0.1.0', |
|||
'license': 'AGPL-3', |
|||
'author': 'Forest and Biomass Services Romania, ' |
|||
'Odoo Community Association (OCA)', |
|||
'website': 'https://www.forbiom.eu', |
|||
'website': 'www.forbiom.eu', |
|||
'category': 'Banking addons', |
|||
'depends': [ |
|||
'account_bank_statement_import_mt940_base' |
|||
], |
|||
'demo': [ |
|||
'demo/demo_data.xml', |
|||
], |
|||
'installable': True, |
|||
} |
@ -0,0 +1,28 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# © 2016 Forest and Biomass Services Romania |
|||
# See README.rst file on addons root folder for license details |
|||
|
|||
import logging |
|||
from openerp import models, api |
|||
from .mt940 import MT940Parser as Parser |
|||
|
|||
_logger = logging.getLogger(__name__) |
|||
|
|||
|
|||
class AccountBankStatementImport(models.TransientModel): |
|||
"""Add parsing of mt940 files to bank statement import.""" |
|||
_inherit = 'account.bank.statement.import' |
|||
|
|||
|
|||
def _parse_file(self, cr, uid, data_file, context=None): |
|||
"""Parse a MT940 IBAN BRD file.""" |
|||
parser = Parser() |
|||
try: |
|||
_logger.debug("Try parsing with MT940 IBAN BRD.") |
|||
return parser.parse(data_file) |
|||
except ValueError: |
|||
# Returning super will call next candidate: |
|||
_logger.debug("Statement file was not a MT940 IBAN BRD file.", |
|||
exc_info=True) |
|||
return super(AccountBankStatementImport, self)._parse_file( |
|||
cr, uid, data_file, context=context) |
@ -0,0 +1,26 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<openerp> |
|||
<data> |
|||
|
|||
<record id="mt940_brd_bank_journal" model="account.journal"> |
|||
<field name="name">Bank Journal - (test mt940 BRD)</field> |
|||
<field name="code">TBNKMT940BRD</field> |
|||
<field name="type">bank</field> |
|||
<field name="sequence_id" ref="account.sequence_bank_journal"/> |
|||
<field name="default_debit_account_id" ref="account.bnk"/> |
|||
<field name="default_credit_account_id" ref="account.bnk"/> |
|||
<field name="user_id" ref="base.user_root"/> |
|||
</record> |
|||
|
|||
<record id="mt940_brd_company_bank" model="res.partner.bank"> |
|||
<field name="owner_name">Your Company</field> |
|||
<field name="acc_number">RO56BRDE360SV52474653600</field> |
|||
<field name="partner_id" ref="base.partner_root"></field> |
|||
<field name="company_id" ref="base.main_company"></field> |
|||
<field name="journal_id" ref="mt940_brd_bank_journal"></field> |
|||
<field name="state">bank</field> |
|||
<field name="bank" ref="base.res_bank_1"/> |
|||
</record> |
|||
</data> |
|||
|
|||
</openerp> |
@ -0,0 +1,143 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# © 2016 Forest and Biomass Services Romania |
|||
# See README.rst file on addons root folder for license details |
|||
|
|||
import re |
|||
from datetime import datetime |
|||
from openerp.addons.account_bank_statement_import_mt940_base.mt940 import ( |
|||
MT940, str2amount) |
|||
|
|||
def get_counterpart(transaction, subfield): |
|||
"""Get counterpart from transaction. |
|||
|
|||
Counterpart is often stored in subfield of tag 86. The subfield |
|||
can be 31, 32, 33""" |
|||
if not subfield: |
|||
return # subfield is empty |
|||
if len(subfield) >= 1 and subfield[0]: |
|||
transaction.remote_account = subfield[0] |
|||
if len(subfield) >= 2 and subfield[1]: |
|||
transaction.remote_owner = subfield[1] |
|||
if len(subfield) >= 3 and subfield[2]: |
|||
transaction.remote_owner_tin = subfield[2] |
|||
|
|||
def get_subfields(data, codewords): |
|||
"""Return dictionary with value array for each codeword in data. |
|||
|
|||
For instance: |
|||
data = |
|||
000+20TRANSACTIONTYPE+30BANKTRANSACTIONNUMBER+31PARTNERBANKACCOUNT |
|||
+32PARTNER+33CUI/CNPTIN |
|||
+23TRANSACTIONMESSAGE1+24TRANSACTIONMESSAGE2 |
|||
+25TRANSACTIONMESSAGE3+26TRANSACTIONMESSAGE4 |
|||
+27TRANSACTIONMESSAGE5 |
|||
+61PARTNERADDRESS1+62PARTNERADDRESS2 |
|||
codewords = ['20', '23', '24', '25', '26', '27', |
|||
'30', '31', '32', '33', '61', '62'] |
|||
!!! NOT ALL CODEWORDS ARE PRESENT !!! |
|||
Then return subfields = { |
|||
'20': [TRANSACTIONTYPE], |
|||
'30': [BANKTRANSACTIONNUMBER], |
|||
'31': [PARTNERBANKACCOUNT], |
|||
'32': [PARTNER], |
|||
'33': [TIN], |
|||
'23': [TRANSACTIONMESSAGE1], |
|||
'24': [TRANSACTIONMESSAGE2], |
|||
'25': [TRANSACTIONMESSAGE3], |
|||
'26': [TRANSACTIONMESSAGE4], |
|||
'27': [TRANSACTIONMESSAGE5], |
|||
'61': [PARTNERADDRESS1], |
|||
'62': [PARTNERADDRESS2], |
|||
} |
|||
""" |
|||
subfields = {} |
|||
current_codeword = None |
|||
for word in data.split('+'): |
|||
if not word and not current_codeword: |
|||
continue |
|||
if word[:2] in codewords: |
|||
current_codeword = word[:2] |
|||
subfields[current_codeword] = [word[2:]] |
|||
continue |
|||
if current_codeword in subfields: |
|||
subfields[current_codeword].append(word[2:]) |
|||
return subfields |
|||
|
|||
def handle_common_subfields(transaction, subfields): |
|||
"""Deal with common functionality for tag 86 subfields.""" |
|||
# Get counterpart from 31, 32 or 33 subfields: |
|||
counterpart_fields = [] |
|||
for counterpart_field in ['31', '32', '33']: |
|||
if counterpart_field in subfields: |
|||
new_value = subfields[counterpart_field][0].replace('CUI/CNP', '') |
|||
counterpart_fields.append(new_value) |
|||
else: |
|||
counterpart_fields.append('') |
|||
if counterpart_fields: |
|||
get_counterpart(transaction, counterpart_fields) |
|||
# REMI: Remitter information (text entered by other party on trans.): |
|||
transaction.message = '' |
|||
for counterpart_field in ['23', '24', '25', '26', '27']: |
|||
if counterpart_field in subfields: |
|||
transaction.message += ( |
|||
'/'.join(x for x in subfields[counterpart_field] if x)) |
|||
# Get transaction reference subfield (might vary): |
|||
if transaction.eref in subfields: |
|||
transaction.eref = ''.join( |
|||
subfields[transaction.eref]) |
|||
|
|||
class MT940Parser(MT940): |
|||
"""Parser for ing MT940 bank statement import files.""" |
|||
|
|||
tag_61_regex = re.compile( |
|||
r'^(?P<date>\d{6})(?P<line_date>\d{0,4})' |
|||
r'(?P<sign>[CD])(?P<amount>\d+,\d{2})N(?P<type>.{3})' |
|||
r'(?P<reference>\w{1,50})' |
|||
) |
|||
|
|||
def __init__(self): |
|||
"""Initialize parser - override at least header_regex.""" |
|||
super(MT940Parser, self).__init__() |
|||
self.mt940_type = 'BRD' |
|||
self.header_lines = 1 # Number of lines to skip |
|||
# Do not user $ for end of string below: line contains much |
|||
# more data than just the first line. |
|||
self.header_regex = '^:20:' # Start of relevant data |
|||
|
|||
def handle_tag_25(self, data): |
|||
"""Local bank account information.""" |
|||
data = data.replace('.', '').strip() |
|||
self.current_statement.local_account = data |
|||
|
|||
def handle_tag_28(self, data): |
|||
"""Number of BRD bank statement.""" |
|||
stmt = self.current_statement |
|||
stmt.statement_id = data.replace('.', '').strip() |
|||
|
|||
def handle_tag_61(self, data): |
|||
"""get transaction values""" |
|||
super(MT940Parser, self).handle_tag_61(data) |
|||
re_61 = self.tag_61_regex.match(data) |
|||
if not re_61: |
|||
raise ValueError("Cannot parse %s" % data) |
|||
parsed_data = re_61.groupdict() |
|||
self.current_transaction.transferred_amount = ( |
|||
str2amount(parsed_data['sign'], parsed_data['amount'])) |
|||
self.current_transaction.eref = parsed_data['reference'] |
|||
|
|||
def handle_tag_86(self, data): |
|||
"""Parse 86 tag containing reference data.""" |
|||
if not self.current_transaction: |
|||
return |
|||
codewords = ['20', '23', '24', '25', '26', '27', |
|||
'30', '31', '32', '33', '61', '62'] |
|||
subfields = get_subfields(data, codewords) |
|||
transaction = self.current_transaction |
|||
# If we have no subfields, set message to whole of data passed: |
|||
if not subfields: |
|||
transaction.message = data |
|||
else: |
|||
handle_common_subfields(transaction, subfields) |
|||
# Prevent handling tag 86 later for non transaction details: |
|||
self.current_transaction = None |
|||
|
@ -0,0 +1,17 @@ |
|||
:20:6450374100 |
|||
:25:RO56BRDE360SV52474653600 |
|||
:28:00138/1 |
|||
:60F:C160517EUR3885,24 |
|||
:61:1605170517D210,60NTRFOPH478 |
|||
PLATA FACT 4603309 |
|||
:86:000+20Plata +30302410000+31RO89RZBR0000060003480121 |
|||
+32RUSSMEDIA PRESS SRL+33/ |
|||
+23PLATA FACT 4603309 |
|||
:61:1605170517D2,76NCOMOPH478 |
|||
25-Comision MULTIX |
|||
:86:000+20Comision |
|||
+2325-Comision MULTIX |
|||
:62F:C160517EUR3671,88 |
|||
:64:C160517EUR3671,88 |
|||
:86:Credit neutilizat la 17/05/2016: 0,00 \ |
|||
Sume blocate la 17/05/2016: 0,00 |
@ -0,0 +1,5 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# © 2016 Forest and Biomass Services Romania |
|||
# See README.rst file on addons root folder for license details |
|||
|
|||
from . import test_import_bank_statement |
@ -0,0 +1,18 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# © 2016 Forest and Biomass Services Romania |
|||
# See README.rst file on addons root folder for license details |
|||
|
|||
from openerp.addons.account_bank_statement_import.tests import ( |
|||
TestStatementFile) |
|||
|
|||
|
|||
class TestImport(TestStatementFile): |
|||
"""Run test to import MT940 ING import.""" |
|||
|
|||
def test_statement_import(self): |
|||
"""Test correct creation of single statement.""" |
|||
self._test_statement_import( |
|||
'account_bank_statement_import_mt940_ro_brd', 'test-brd.940', |
|||
'00138/1', |
|||
start_balance=3885.24, end_balance=3671.88 |
|||
) |
Write
Preview
Loading…
Cancel
Save
Reference in new issue