From c8a77e36114d15463d54150b754d95c0345b82cf Mon Sep 17 00:00:00 2001
From: Luc De Meyer
Date: Thu, 3 Dec 2020 22:36:30 +0100
Subject: [PATCH 1/4] [13.0]generic order type
---
account_ebics/__manifest__.py | 2 +-
account_ebics/models/ebics_file_format.py | 58 ++---------
account_ebics/wizards/ebics_xfer.py | 121 ++++++++++------------
account_ebics/wizards/ebics_xfer.xml | 1 +
4 files changed, 63 insertions(+), 119 deletions(-)
diff --git a/account_ebics/__manifest__.py b/account_ebics/__manifest__.py
index 004b2cb..2a428e6 100644
--- a/account_ebics/__manifest__.py
+++ b/account_ebics/__manifest__.py
@@ -3,7 +3,7 @@
{
'name': 'EBICS banking protocol',
- 'version': '13.0.1.2.1',
+ 'version': '13.0.1.3.0',
'license': 'LGPL-3',
'author': 'Noviat',
'website': 'www.noviat.com',
diff --git a/account_ebics/models/ebics_file_format.py b/account_ebics/models/ebics_file_format.py
index 55a9945..e11f9e3 100644
--- a/account_ebics/models/ebics_file_format.py
+++ b/account_ebics/models/ebics_file_format.py
@@ -1,7 +1,7 @@
# Copyright 2009-2020 Noviat.
# License LGPL-3 or later (http://www.gnu.org/licenses/lpgl).
-from odoo import api, fields, models
+from odoo import fields, models
class EbicsFileFormat(models.Model):
@@ -9,17 +9,19 @@ class EbicsFileFormat(models.Model):
_description = 'EBICS File Formats'
_order = 'type,name'
- name = fields.Selection(
- selection=lambda self: self._selection_name(),
- string='Request Type', required=True)
+ name = fields.Char(
+ string='Request Type',
+ required=True,
+ help="E.g. camt.053.001.02.stm, camt.xxx.cfonb120.stm, "
+ "pain.001.001.03.sct (check your EBICS contract).\n")
type = fields.Selection(
selection=[('down', 'Download'),
('up', 'Upload')],
required=True)
- order_type = fields.Selection(
- selection=lambda self: self._selection_order_type(),
+ order_type = fields.Char(
string='Order Type',
- help="For most banks is France you should use the "
+ help="E.g. C53 (check your EBICS contract).\n"
+ "For most banks in France you should use the "
"format neutral Order Types 'FUL' for upload "
"and 'FDL' for download.")
signature_class = fields.Selection(
@@ -36,45 +38,3 @@ class EbicsFileFormat(models.Model):
required=True,
help="Specify the filename suffix for this File Format."
"\nE.g. camt.053.xml")
-
- @api.model
- def _selection_order_type(self):
- up = self._supported_upload_order_types()
- down = self._supported_download_order_types()
- selection = [(x, x) for x in up + down]
- return selection
-
- def _supported_upload_order_types(self):
- return ['FUL', 'CCT', 'CDD', 'CDB', 'XE2', 'XE3']
-
- def _supported_download_order_types(self):
- return ['FDL', 'C52', 'C53', 'C54']
-
- @api.model
- def _selection_name(self):
- """
- List of supported EBICS Request Types.
- Extend this method via a custom module when testing
- a new Request Type and make a PR for the
- account_ebics module when this new Request Type
- is working correctly.
- This PR should include at least updates to
- - 'data/ebics_file_format.xml'
- - 'models/ebics_file_format.py'
- An overview of the EBICS Request Types can be found in
- the doc folder of this module (EBICS_Annex2).
- """
- request_types = [
- 'camt.052.001.02.stm',
- 'camt.053.001.02.stm',
- 'pain.001.001.03.sct',
- 'pain.008.001.02.sdd',
- 'pain.008.001.02.sbb',
- 'camt.xxx.cfonb120.stm',
- 'pain.001.001.02.sct',
- 'camt.053',
- 'pain.001',
- 'pain.008',
- ]
- selection = [(x, x) for x in request_types]
- return selection
diff --git a/account_ebics/wizards/ebics_xfer.py b/account_ebics/wizards/ebics_xfer.py
index 8166462..0f97f08 100644
--- a/account_ebics/wizards/ebics_xfer.py
+++ b/account_ebics/wizards/ebics_xfer.py
@@ -64,12 +64,10 @@ class EbicsXfer(models.TransientModel):
format_id = fields.Many2one(
comodel_name='ebics.file.format',
string='EBICS File Format',
- help="Select EBICS File Format to upload/download."
- "\nLeave blank to download all available files.")
- order_type = fields.Selection(
- selection=lambda self: self._selection_order_type(),
+ help="Select EBICS File Format to upload/download.")
+ order_type = fields.Char(
string='Order Type',
- help="For most banks is France you should use the "
+ help="For most banks in France you should use the "
"format neutral Order Types 'FUL' for upload "
"and 'FDL' for download.")
test_mode = fields.Boolean(
@@ -91,10 +89,6 @@ class EbicsXfer(models.TransientModel):
else:
return cfg_mod
- @api.model
- def _selection_order_type(self):
- return self.env['ebics.file.format']._selection_order_type()
-
@api.onchange('ebics_config_id')
def _onchange_ebics_config_id(self):
ebics_userids = self.ebics_config_id.ebics_userid_ids
@@ -166,63 +160,56 @@ class EbicsXfer(models.TransientModel):
self.note = ''
client = self._setup_client()
if client:
- download_formats = self.format_id \
- or self.ebics_config_id.ebics_file_format_ids.filtered(
- lambda r: r.type == 'down')
ebics_files = self.env['ebics.file']
- for df in download_formats:
- success = False
- order_type = df.order_type or 'FDL'
- params = {}
+ success = False
+ order_type = self.order_type or 'FDL'
+ date_from = self.date_from and self.date_from.isoformat() or None
+ date_to = self.date_to and self.date_to.isoformat() or None
+ try:
if order_type == 'FDL':
- params['filetype'] = df.name
- if order_type in ['FDL', 'C52', 'C53', 'C54']:
- params.update({
- 'start':
- self.date_from and self.date_from.isoformat()
- or None,
- 'end':
- self.date_to and self.date_to.isoformat()
- or None,
- })
- kwargs = {k: v for k, v in params.items() if v}
- try:
- method = getattr(client, order_type)
- data = method(**kwargs)
- ebics_files += self._handle_download_data(data, df)
- success = True
- except EbicsFunctionalError:
- e = exc_info()
- self.note += '\n'
- self.note += _("EBICS Functional Error:")
- self.note += '\n'
- self.note += '%s (code: %s)' % (e[1].message, e[1].code)
- except EbicsTechnicalError:
- e = exc_info()
- self.note += '\n'
- self.note += _("EBICS Technical Error:")
- self.note += '\n'
- self.note += '%s (code: %s)' % (e[1].message, e[1].code)
- except EbicsVerificationError:
- self.note += '\n'
- self.note += _("EBICS Verification Error:")
- self.note += '\n'
- self.note += _("The EBICS response could not be verified.")
- except UserError as e:
- self.note += '\n'
- self.note += _("Warning:")
- self.note += '\n'
- self.note += e.name
- except Exception:
- self.note += '\n'
- self.note += _("Unknown Error")
- tb = ''.join(format_exception(*exc_info()))
- self.note += '\n%s' % tb
+ data = client.FDL(self.format_id.name, date_from, date_to)
else:
- # mark received data so that it is not included in further
- # downloads
- trans_id = client.last_trans_id
- client.confirm_download(trans_id=trans_id, success=success)
+ params = None
+ if date_from and date_to:
+ params = {'DateRange': {
+ 'Start': date_from,
+ 'End': date_to,
+ }}
+ data = client.download(order_type, params=params)
+ ebics_files += self._handle_download_data(data, self.format_id)
+ success = True
+ except EbicsFunctionalError:
+ e = exc_info()
+ self.note += '\n'
+ self.note += _("EBICS Functional Error:")
+ self.note += '\n'
+ self.note += '%s (code: %s)' % (e[1].message, e[1].code)
+ except EbicsTechnicalError:
+ e = exc_info()
+ self.note += '\n'
+ self.note += _("EBICS Technical Error:")
+ self.note += '\n'
+ self.note += '%s (code: %s)' % (e[1].message, e[1].code)
+ except EbicsVerificationError:
+ self.note += '\n'
+ self.note += _("EBICS Verification Error:")
+ self.note += '\n'
+ self.note += _("The EBICS response could not be verified.")
+ except UserError as e:
+ self.note += '\n'
+ self.note += _("Warning:")
+ self.note += '\n'
+ self.note += e.name
+ except Exception:
+ self.note += '\n'
+ self.note += _("Unknown Error")
+ tb = ''.join(format_exception(*exc_info()))
+ self.note += '\n%s' % tb
+ else:
+ # mark received data so that it is not included in further
+ # downloads
+ trans_id = client.last_trans_id
+ client.confirm_download(trans_id=trans_id, success=success)
ctx['ebics_file_ids'] = ebics_files._ids
@@ -271,7 +258,7 @@ class EbicsXfer(models.TransientModel):
ef_format = self.format_id
OrderID = False
try:
- order_type = ef_format.order_type or 'FUL'
+ order_type = self.order_type or 'FUL'
method = hasattr(client, order_type) \
and getattr(client, order_type)
if order_type == 'FUL':
@@ -285,12 +272,8 @@ class EbicsXfer(models.TransientModel):
OrderID = method(ef_format.name, upload_data, **kwargs)
elif order_type in ['CCT', 'CDD', 'CDB']:
OrderID = method(upload_data)
- elif order_type in ['XE2', 'XE3']:
- OrderID = client.upload(order_type, upload_data)
else:
- # TODO: investigate if it makes sense to support
- # a generic upload for a non-predefined order_type
- pass
+ OrderID = client.upload(order_type, upload_data)
if OrderID:
self.note += '\n'
self.note += _(
diff --git a/account_ebics/wizards/ebics_xfer.xml b/account_ebics/wizards/ebics_xfer.xml
index 66b16f6..60b5369 100644
--- a/account_ebics/wizards/ebics_xfer.xml
+++ b/account_ebics/wizards/ebics_xfer.xml
@@ -17,6 +17,7 @@
+
-The licensed EBICS user ids. It must be a string or a list of user ids.
-You should NOT specify this parameter if your license is subsciption
+
The licensed EBICS user ids. It must be a string or a list of user ids.
+You should NOT specify this parameter if your license is subsciption
based (with monthly recurring billing).
@@ -446,6 +455,27 @@ fintech_register_users = USER1, USER2
Configuration
Go to Settings > Users
Add the users that are authorised to maintain the EBICS configuration to the 'EBICS Manager' Group.
+
+
Go to Accounting > Configuration > Miscellaneous > EBICS > EBICS File Formats
+
Check if the EBICS File formats that you want to process in Odoo are defined.
+
Most commonly used formats for which support is available in Odoo should be there already.
+
Please open an issue on https://github.com/Noviat/account_ebics to report missing EBICS File Formats.
+
For File Formats of type 'Downloads' you can also specifiy a 'Download Process Method'.
+
This is the method that will be executed when hitting the 'Process' button on the downloaded file.
+
The following methods are currently available:
+
+- cfonb120
+- camt.053
+- camt.052
+- camt.054
+
+
All these methods require complimentary modules to be installed (cf. Installation section supra).
+
You'll get an error message when the required module is not installed on your Odoo instance.
+
Go to Accounting > Configuration > Miscellaneous > EBICS > EBICS Configuration
Configure your EBICS configuration according to the contract with your bank.
From e7eaf68c5974d9338179d932211a329d348c2791 Mon Sep 17 00:00:00 2001
From: Luc De Meyer
Date: Sat, 5 Dec 2020 18:56:12 +0100
Subject: [PATCH 3/4] [13.0]account_ebics 1.3.0 - generic order type
---
account_ebics/data/ebics_file_format.xml | 201 +++++++++++-------
.../migrations/13.0.1.3/post-migration.py | 41 ++++
.../migrations/13.0.1.3/pre-migration.py | 70 ++++++
account_ebics/models/ebics_file.py | 27 ++-
account_ebics/models/ebics_file_format.py | 34 ++-
.../models/fintech_ebics_register.py | 4 +-
.../views/ebics_file_format_views.xml | 22 +-
account_ebics/wizards/ebics_xfer.py | 133 +++++++-----
8 files changed, 376 insertions(+), 156 deletions(-)
create mode 100644 account_ebics/migrations/13.0.1.3/post-migration.py
create mode 100644 account_ebics/migrations/13.0.1.3/pre-migration.py
diff --git a/account_ebics/data/ebics_file_format.xml b/account_ebics/data/ebics_file_format.xml
index a910b5f..7aa2601 100644
--- a/account_ebics/data/ebics_file_format.xml
+++ b/account_ebics/data/ebics_file_format.xml
@@ -2,104 +2,151 @@
-
-
- camt.053.001.02.stm
- down
- C53
- Bank Statement in Format camt.053
- c53.xml
-
+
-
-
- camt.052.001.02.stm
+
+ camt.052
down
C52
- Bank Statement in Format camt.052
+ camt.052
+ bank to customer account report in format camt.052
c52.xml
-
-
- pain.001.001.03.sct
- up
- CCT
- Payment Order in Format pain.001.001.03
- xml
+
+ camt.052
+ down
+ Z52
+ camt.052
+ bank to customer account report in format camt.052
+ c52.xml
+
+
+
+ camt.053
+ down
+ C53
+ camt.053
+ Bank to customer statement report in format camt.053
+ c53.xml
-
- pain.008.001.02.sdd
- up
- CDD
- Sepa Core Direct Debit Order in Format pain.008.001.02
- xml
+
+ camt.053
+ down
+ Z53
+ camt.053
+ Bank to customer statement report in format camt.053
+ c53.xml
+
+
+
+ camt.054
+ down
+ C54
+ camt.054
+ Bank to customer debit credit notification in format camt.054
+ c52.xml
-
- pain.008.001.02.sbb
- up
- CDB
- Sepa Direct Debit (B2B) Order in Format pain.008.001.02
- xml
+
+ camt.054
+ down
+ Z54
+ camt.054
+ Bank to customer debit credit notification in format camt.054
+ c52.xml
-
-
- pain.001
- up
- XE2
- Payment Order in Format pain.001.001.03
- xml
-
-
-
-
- pain.008
- up
- XE3
- Direct Debit Order in Format pain.008.001.02
- xml
-
-
-
-
+
camt.xxx.cfonb120.stm
down
FDL
- Bank Statement in Format cfonb120
+ cfonb120
+ Bank to customer statement report in format cfonb120
cfonb120.dat
-
-
+
+ pain.002
+ down
+ CDZ
+ Payment status report for direct debit in format pain.002
+ psr.xml
+
+
+
+ pain.002
+ down
+ Z01
+ Payment status report for direct debit in format pain.002
+ psr.xml
+
+
+
+
+
+ pain.001.001.03
+ up
+ CCT
+ Payment Order in format pain.001.001.03
+ cct.xml
+
+
+
+ pain.001.001.03
+ up
+ XE2
+ Payment Order in format pain.001.001.03
+ cct.xml
+
+
+
+ pain.008.001.02.sdd
+ up
+ CDD
+ Sepa Core Direct Debit Order in format pain.008.001.02
+ sdd.xml
+
+
+
+ pain.008.001.02.sdd
+ up
+ CDD
+ Sepa Core Direct Debit Order in format pain.008.001.02
+ sdd.xml
+
+
+
+ pain.008.001.02.sdd
+ up
+ XE3
+ Sepa Core Direct Debit Order in format pain.008.001.02
+ sdd.xml
+
+
+
+ pain.008.001.02.sbb
+ up
+ CDB
+ Sepa Direct Debit (B2B) Order in format pain.008.001.02
+ sbb.xml
+
+
+
+ pain.008.001.02.sbb
+ up
+ XE4
+ Sepa Direct Debit (B2B) Order in format pain.008.001.02
+ sbb.xml
+
+
+
pain.001.001.02.sct
up
FUL
- Payment Order in Format pain.001.001.02
- xml
+ Payment Order in format pain.001.001.02
+ cct.xml
diff --git a/account_ebics/migrations/13.0.1.3/post-migration.py b/account_ebics/migrations/13.0.1.3/post-migration.py
new file mode 100644
index 0000000..a082120
--- /dev/null
+++ b/account_ebics/migrations/13.0.1.3/post-migration.py
@@ -0,0 +1,41 @@
+# Copyright 2009-2020 Noviat.
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+_FILE_FORMATS = [
+ {'xml_id_name': 'ebics_ff_C52',
+ 'download_process_method': 'camt.052',
+ },
+ {'xml_id_name': 'ebics_ff_C53',
+ 'download_process_method': 'camt.053',
+ },
+ {'xml_id_name': 'ebics_ff_FDL_camt_xxx_cfonb120_stm',
+ 'download_process_method': 'cfonb120',
+ },
+
+]
+
+
+def migrate(cr, version):
+ for ff in _FILE_FORMATS:
+ _update_file_format(cr, ff)
+
+
+def _update_file_format(cr, ff):
+ cr.execute(
+ """
+ SELECT res_id FROM ir_model_data
+ WHERE module='account_ebics' AND name='{}'
+ """.format(ff['xml_id_name'])
+ )
+ res = cr.fetchone()
+ if res:
+ cr.execute(
+ """
+ UPDATE ebics_file_format
+ SET download_process_method='{download_process_method}'
+ WHERE id={ff_id};
+ """.format(
+ download_process_method=ff['download_process_method'],
+ ff_id=res[0]
+ )
+ )
diff --git a/account_ebics/migrations/13.0.1.3/pre-migration.py b/account_ebics/migrations/13.0.1.3/pre-migration.py
new file mode 100644
index 0000000..7799b26
--- /dev/null
+++ b/account_ebics/migrations/13.0.1.3/pre-migration.py
@@ -0,0 +1,70 @@
+# Copyright 2009-2020 Noviat.
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+_FILE_FORMATS = [
+ {'old_xml_id_name': 'ebics_ff_camt_052_001_02_stm',
+ 'new_xml_id_name': 'ebics_ff_C52',
+ 'new_name': 'camt.052',
+ },
+ {'old_xml_id_name': 'ebics_ff_camt_053_001_02_stm',
+ 'new_xml_id_name': 'ebics_ff_C53',
+ 'new_name': 'camt.053',
+ },
+ {'old_xml_id_name': 'ebics_ff_camt_xxx_cfonb120_stm',
+ 'new_xml_id_name': 'ebics_ff_FDL_camt_xxx_cfonb120_stm',
+ },
+ {'old_xml_id_name': 'ebics_ff_pain_001_001_03_sct',
+ 'new_xml_id_name': 'ebics_ff_CCT',
+ },
+ {'old_xml_id_name': 'ebics_ff_pain_001',
+ 'new_xml_id_name': 'ebics_ff_XE2',
+ 'new_name': 'pain.001.001.03',
+ },
+ {'old_xml_id_name': 'ebics_ff_pain_008_001_02_sdd',
+ 'new_xml_id_name': 'ebics_ff_CDD',
+ },
+ {'old_xml_id_name': 'ebics_ff_pain_008',
+ 'new_xml_id_name': 'ebics_ff_XE3',
+ },
+ {'old_xml_id_name': 'ebics_ff_pain_008_001_02_sbb',
+ 'new_xml_id_name': 'ebics_ff_CDB',
+ },
+ {'old_xml_id_name': 'ebics_ff_pain_001_001_02_sct',
+ 'new_xml_id_name': 'ebics_ff_FUL_pain_001_001_02_sct',
+ },
+]
+
+
+def migrate(cr, version):
+ if not version:
+ return
+
+ for ff in _FILE_FORMATS:
+ _update_file_format(cr, ff)
+
+
+def _update_file_format(cr, ff):
+ cr.execute(
+ """
+ SELECT id, res_id FROM ir_model_data
+ WHERE module='account_ebics' AND name='{}'
+ """.format(ff['old_xml_id_name'])
+ )
+ res = cr.fetchone()
+ if res:
+ query = """
+ UPDATE ir_model_data
+ SET name='{new_xml_id_name}'
+ WHERE id={xml_id};
+ """.format(
+ new_xml_id_name=ff["new_xml_id_name"], xml_id=res[0]
+ )
+ if ff.get('new_name'):
+ query += """
+ UPDATE ebics_file_format
+ SET name='{new_name}'
+ WHERE id={ff_id};
+ """.format(
+ new_name=ff["new_name"], ff_id=res[1]
+ )
+ cr.execute(query)
diff --git a/account_ebics/models/ebics_file.py b/account_ebics/models/ebics_file.py
index 90d7de6..36f2042 100644
--- a/account_ebics/models/ebics_file.py
+++ b/account_ebics/models/ebics_file.py
@@ -70,7 +70,7 @@ class EbicsFile(models.Model):
raise UserError(_(
"You can only remove EBICS files in state 'Draft'."))
# execute format specific actions
- ff = ebics_file.format_id.name
+ ff = ebics_file.format_id.download_process_method
if ff in ff_methods:
if ff_methods[ff].get('unlink'):
ff_methods[ff]['unlink'](ebics_file)
@@ -92,7 +92,7 @@ class EbicsFile(models.Model):
self = self.with_context(ctx)
self.note_process = ''
ff_methods = self._file_format_methods()
- ff = self.format_id.name
+ ff = self.format_id.download_process_method
if ff in ff_methods:
if ff_methods[ff].get('process'):
res = ff_methods[ff]['process'](self)
@@ -120,15 +120,18 @@ class EbicsFile(models.Model):
for extra file formats.
"""
res = {
- 'camt.xxx.cfonb120.stm':
+ 'cfonb120':
{'process': self._process_cfonb120,
'unlink': self._unlink_cfonb120},
- 'camt.052.001.02.stm':
+ 'camt.052':
{'process': self._process_camt052,
'unlink': self._unlink_camt052},
- 'camt.053.001.02.stm':
+ 'camt.053':
{'process': self._process_camt053,
'unlink': self._unlink_camt053},
+ 'camt.054':
+ {'process': self._process_camt054,
+ 'unlink': self._unlink_camt054},
}
return res
@@ -294,6 +297,20 @@ class EbicsFile(models.Model):
"""
pass
+ @staticmethod
+ def _process_camt054(self):
+ import_module = 'account_bank_statement_import_camt_oca'
+ self._check_import_module(import_module)
+ return self._process_camt053(self)
+
+ @staticmethod
+ def _unlink_camt054(self):
+ """
+ Placeholder for camt054 specific actions before removing the
+ EBICS data file and its related bank statements.
+ """
+ pass
+
@staticmethod
def _process_camt053(self):
import_module = 'account_bank_statement_import_camt%'
diff --git a/account_ebics/models/ebics_file_format.py b/account_ebics/models/ebics_file_format.py
index e11f9e3..5864644 100644
--- a/account_ebics/models/ebics_file_format.py
+++ b/account_ebics/models/ebics_file_format.py
@@ -1,29 +1,41 @@
# Copyright 2009-2020 Noviat.
# License LGPL-3 or later (http://www.gnu.org/licenses/lpgl).
-from odoo import fields, models
+from odoo import api, fields, models
class EbicsFileFormat(models.Model):
_name = 'ebics.file.format'
_description = 'EBICS File Formats'
- _order = 'type,name'
+ _order = 'type,name,order_type'
name = fields.Char(
string='Request Type',
required=True,
- help="E.g. camt.053.001.02.stm, camt.xxx.cfonb120.stm, "
- "pain.001.001.03.sct (check your EBICS contract).\n")
+ help="E.g. camt.xxx.cfonb120.stm, pain.001.001.03.sct.\n"
+ "Specify camt.052, camt.053, camt.054 for camt "
+ "Order Types such as C53, Z53, C54, Z54.\n"
+ "This name has to match the 'Request Type' in your "
+ "EBICS contract for Order Type 'FDL' or 'FUL'.\n")
type = fields.Selection(
selection=[('down', 'Download'),
('up', 'Upload')],
required=True)
order_type = fields.Char(
string='Order Type',
+ required=True,
help="E.g. C53 (check your EBICS contract).\n"
"For most banks in France you should use the "
"format neutral Order Types 'FUL' for upload "
"and 'FDL' for download.")
+ download_process_method = fields.Selection(
+ selection='_selection_download_process_method',
+ help="Enable processing within Odoo of the downloaded file "
+ "via the 'Process' button."
+ "E.g. specify camt.053 to import a camt.053 file and create "
+ "a bank statement.")
+ # TODO:
+ # move signature_class parameter so that it can be set per EBICS config
signature_class = fields.Selection(
selection=[('E', 'Single signature'),
('T', 'Transport signature')],
@@ -32,9 +44,19 @@ class EbicsFileFormat(models.Model):
"ERP system when using class 'E' to prevent unauthorised "
"users to make supplier payments."
"\nLeave this field empty to use the default "
- "defined for your bank connection.")
+ "defined for your EBICS UserID.")
description = fields.Char()
suffix = fields.Char(
required=True,
help="Specify the filename suffix for this File Format."
- "\nE.g. camt.053.xml")
+ "\nE.g. c53.xml")
+
+ @api.model
+ def _selection_download_process_method(self):
+ methods = self.env['ebics.file']._file_format_methods().keys()
+ return [(x, x) for x in methods]
+
+ @api.onchange('type')
+ def _onchange_type(self):
+ if self.type == 'up':
+ self.download_process_method = False
diff --git a/account_ebics/models/fintech_ebics_register.py b/account_ebics/models/fintech_ebics_register.py
index 5a97aaa..f908637 100644
--- a/account_ebics/models/fintech_ebics_register.py
+++ b/account_ebics/models/fintech_ebics_register.py
@@ -32,10 +32,10 @@ try:
keycode=fintech_register_keycode,
users=fintech_register_users)
except RuntimeError as e:
- if e.message == "'register' can be called only once":
+ if str(e) == "'register' can be called only once":
pass
else:
- _logger.error(e.message)
+ _logger.error(str(e))
fintech.register()
except Exception:
msg = "fintech.register error"
diff --git a/account_ebics/views/ebics_file_format_views.xml b/account_ebics/views/ebics_file_format_views.xml
index 7e901ac..79ed9e2 100644
--- a/account_ebics/views/ebics_file_format_views.xml
+++ b/account_ebics/views/ebics_file_format_views.xml
@@ -20,13 +20,21 @@
ebics.file.format
diff --git a/account_ebics/wizards/ebics_xfer.py b/account_ebics/wizards/ebics_xfer.py
index 0f97f08..f31df5f 100644
--- a/account_ebics/wizards/ebics_xfer.py
+++ b/account_ebics/wizards/ebics_xfer.py
@@ -64,8 +64,10 @@ class EbicsXfer(models.TransientModel):
format_id = fields.Many2one(
comodel_name='ebics.file.format',
string='EBICS File Format',
- help="Select EBICS File Format to upload/download.")
+ help="Select EBICS File Format to upload/download."
+ "\nLeave blank to download all available files.")
order_type = fields.Char(
+ related='format_id.order_type',
string='Order Type',
help="For most banks in France you should use the "
"format neutral Order Types 'FUL' for upload "
@@ -160,56 +162,73 @@ class EbicsXfer(models.TransientModel):
self.note = ''
client = self._setup_client()
if client:
+ download_formats = (
+ self.format_id
+ or self.ebics_config_id.ebics_file_format_ids.filtered(
+ lambda r: r.type == 'down'
+ )
+ )
ebics_files = self.env['ebics.file']
- success = False
- order_type = self.order_type or 'FDL'
date_from = self.date_from and self.date_from.isoformat() or None
date_to = self.date_to and self.date_to.isoformat() or None
- try:
- if order_type == 'FDL':
- data = client.FDL(self.format_id.name, date_from, date_to)
+ for df in download_formats:
+ try:
+ success = False
+ if df.order_type == 'FDL':
+ data = client.FDL(df.name, date_from, date_to)
+ else:
+ params = None
+ if date_from and date_to:
+ params = {'DateRange': {
+ 'Start': date_from,
+ 'End': date_to,
+ }}
+ data = client.download(df.order_type, params=params)
+ ebics_files += self._handle_download_data(data, df)
+ success = True
+ except EbicsFunctionalError:
+ e = exc_info()
+ self.note += '\n'
+ self.note += _(
+ "EBICS Functional Error during download of File Format %s (%s):"
+ ) % (df.name, df.order_type)
+ self.note += '\n'
+ self.note += '%s (code: %s)' % (e[1].message, e[1].code)
+ except EbicsTechnicalError:
+ e = exc_info()
+ self.note += '\n'
+ self.note += _(
+ "EBICS Technical Error during download of File Format %s (%s):"
+ ) % (df.name, df.order_type)
+ self.note += '\n'
+ self.note += '%s (code: %s)' % (e[1].message, e[1].code)
+ except EbicsVerificationError:
+ self.note += '\n'
+ self.note += _(
+ "EBICS Verification Error during download of "
+ "File Format %s (%s):"
+ ) % (df.name, df.order_type)
+ self.note += '\n'
+ self.note += _("The EBICS response could not be verified.")
+ except UserError as e:
+ self.note += '\n'
+ self.note += _(
+ "Warning during download of File Format %s (%s):"
+ ) % (df.name, df.order_type)
+ self.note += '\n'
+ self.note += e.name
+ except Exception:
+ self.note += '\n'
+ self.note += _(
+ "Unknown Error during download of File Format %s (%s):"
+ ) % (df.name, df.order_type)
+ tb = ''.join(format_exception(*exc_info()))
+ self.note += '\n%s' % tb
else:
- params = None
- if date_from and date_to:
- params = {'DateRange': {
- 'Start': date_from,
- 'End': date_to,
- }}
- data = client.download(order_type, params=params)
- ebics_files += self._handle_download_data(data, self.format_id)
- success = True
- except EbicsFunctionalError:
- e = exc_info()
- self.note += '\n'
- self.note += _("EBICS Functional Error:")
- self.note += '\n'
- self.note += '%s (code: %s)' % (e[1].message, e[1].code)
- except EbicsTechnicalError:
- e = exc_info()
- self.note += '\n'
- self.note += _("EBICS Technical Error:")
- self.note += '\n'
- self.note += '%s (code: %s)' % (e[1].message, e[1].code)
- except EbicsVerificationError:
- self.note += '\n'
- self.note += _("EBICS Verification Error:")
- self.note += '\n'
- self.note += _("The EBICS response could not be verified.")
- except UserError as e:
- self.note += '\n'
- self.note += _("Warning:")
- self.note += '\n'
- self.note += e.name
- except Exception:
- self.note += '\n'
- self.note += _("Unknown Error")
- tb = ''.join(format_exception(*exc_info()))
- self.note += '\n%s' % tb
- else:
- # mark received data so that it is not included in further
- # downloads
- trans_id = client.last_trans_id
- client.confirm_download(trans_id=trans_id, success=success)
+ # mark received data so that it is not included in further
+ # downloads
+ trans_id = client.last_trans_id
+ client.confirm_download(trans_id=trans_id, success=success)
ctx['ebics_file_ids'] = ebics_files._ids
@@ -258,9 +277,7 @@ class EbicsXfer(models.TransientModel):
ef_format = self.format_id
OrderID = False
try:
- order_type = self.order_type or 'FUL'
- method = hasattr(client, order_type) \
- and getattr(client, order_type)
+ order_type = self.order_type
if order_type == 'FUL':
kwargs = {}
bank = self.ebics_config_id.journal_ids[0].bank_id
@@ -269,9 +286,7 @@ class EbicsXfer(models.TransientModel):
kwargs['country'] = cc
if self.test_mode:
kwargs['TEST'] = 'TRUE'
- OrderID = method(ef_format.name, upload_data, **kwargs)
- elif order_type in ['CCT', 'CDD', 'CDB']:
- OrderID = method(upload_data)
+ OrderID = client.FUL(ef_format.name, upload_data, **kwargs)
else:
OrderID = client.upload(order_type, upload_data)
if OrderID:
@@ -509,17 +524,17 @@ class EbicsXfer(models.TransientModel):
else:
o_list[-i] = chr(ord(c) + 1)
break
- next = ''.join(o_list)
- if next == 'ZZZZ':
- next = 'A000'
- self.ebics_config_id.order_number = next
+ next_nr = ''.join(o_list)
+ if next_nr == 'ZZZZ':
+ next_nr = 'A000'
+ self.ebics_config_id.order_number = next_nr
def _insert_line_terminator(self, data_in, line_len):
data_in = data_in.replace(b'\n', b'').replace(b'\r', b'')
data_out = b''
- max = len(data_in)
+ max_len = len(data_in)
i = 0
- while i + line_len <= max:
+ while i + line_len <= max_len:
data_out += data_in[i:i + line_len] + b'\n'
i += line_len
return data_out
From 8df50b526c1a47bcba2af2e1b94d2f48ac8e12da Mon Sep 17 00:00:00 2001
From: Luc De Meyer
Date: Wed, 9 Dec 2020 21:48:58 +0100
Subject: [PATCH 4/4] add placeholder logic to add pain.002 processing logic
---
account_ebics/data/ebics_file_format.xml | 1 +
account_ebics/models/ebics_file.py | 20 ++++++++++++++++++++
2 files changed, 21 insertions(+)
diff --git a/account_ebics/data/ebics_file_format.xml b/account_ebics/data/ebics_file_format.xml
index 7aa2601..da1766f 100644
--- a/account_ebics/data/ebics_file_format.xml
+++ b/account_ebics/data/ebics_file_format.xml
@@ -79,6 +79,7 @@
pain.002
down
Z01
+ pain.002
Payment status report for direct debit in format pain.002
psr.xml
diff --git a/account_ebics/models/ebics_file.py b/account_ebics/models/ebics_file.py
index 36f2042..80dabf2 100644
--- a/account_ebics/models/ebics_file.py
+++ b/account_ebics/models/ebics_file.py
@@ -132,6 +132,9 @@ class EbicsFile(models.Model):
'camt.054':
{'process': self._process_camt054,
'unlink': self._unlink_camt054},
+ 'pain.002':
+ {'process': self._process_pain002,
+ 'unlink': self._unlink_pain002},
}
return res
@@ -341,6 +344,23 @@ class EbicsFile(models.Model):
"""
pass
+ @staticmethod
+ def _process_pain002(self):
+ """
+ Placeholder for processing pain.002 files.
+ TODO:
+ add import logic based upon OCA 'account_payment_return_import'
+ """
+ pass
+
+ @staticmethod
+ def _unlink_pain002(self):
+ """
+ Placeholder for pain.002 specific actions before removing the
+ EBICS data file.
+ """
+ raise NotImplementedError
+
def _process_undefined_format(self):
raise UserError(_(
"The current version of the 'account_ebics' module "