- Sponsor
-
Notifications
You must be signed in to change notification settings - Fork 162
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
14.0 l10n ch import payment return (#66)
* [ADD] l10n_ch_import_payment_return module to handle return from payment orders Add functionalities to handle the payment return from the switzerland pain generated from payment orders
1 parent
94e5278
commit 20ed733
Showing
14 changed files
with
290 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
============================= | ||
l10n_ch_import_payment_return | ||
============================= | ||
|
||
.. | ||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
!! This file is generated by oca-gen-addon-readme !! | ||
!! changes will be overwritten. !! | ||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
!! source digest: sha256:74050c117e767ff97c56412206efd3981573666cdf9205e8b4c1b71ae7b09a8f | ||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png | ||
:target: https://odoo-community.org/page/development-status | ||
:alt: Beta | ||
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png | ||
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html | ||
:alt: License: AGPL-3 | ||
.. |badge3| image:: https://img.shields.io/badge/github-CompassionCH%2Fl10n_switzerland-lightgray.png?logo=github | ||
:target: https://github.com/CompassionCH/l10n_switzerland/tree/14.0/l10n_ch_import_payment_return | ||
:alt: CompassionCH/l10n_switzerland | ||
|
||
|badge1| |badge2| |badge3| | ||
|
||
This module add the functionality of processing the return of the payment orders | ||
|
||
**Table of contents** | ||
|
||
.. contents:: | ||
:local: | ||
|
||
Usage | ||
===== | ||
|
||
To use this module, you need to: | ||
|
||
#. Go to EDI and configure a backend and an exchange type | ||
|
||
#. Create a payment order and choose an EDI exchange type | ||
|
||
#. When generating the file an edi exchange should be created | ||
|
||
#. When a return come back it should be processed by the parser | ||
|
||
Known issues / Roadmap | ||
====================== | ||
|
||
* Automate a generic treatment process of the files | ||
|
||
Changelog | ||
========= | ||
|
||
14.0.1.0.0 (2023-06-23) | ||
~~~~~~~~~~~~~~~~~~~~~~~ | ||
|
||
* [ADD] l10n_ch_import_payment_return | ||
|
||
Bug Tracker | ||
=========== | ||
|
||
Bugs are tracked on `GitHub Issues <https://github.com/CompassionCH/l10n_switzerland/issues>`_. | ||
In case of trouble, please check there if your issue has already been reported. | ||
If you spotted it first, help us to smash it by providing a detailed and welcomed | ||
`feedback <https://github.com/CompassionCH/l10n_switzerland/issues/new?body=module:%20l10n_ch_import_payment_return%0Aversion:%2014.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_. | ||
|
||
Do not contact contributors directly about support or help with technical issues. | ||
|
||
Credits | ||
======= | ||
|
||
Authors | ||
~~~~~~~ | ||
|
||
* Compassion CH | ||
|
||
Contributors | ||
~~~~~~~~~~~~ | ||
|
||
* Simon Gonzalez <simon.gonzalez@bluewin.ch> (https://compassion.ch) | ||
|
||
Maintainers | ||
~~~~~~~~~~~ | ||
|
||
This module is part of the `CompassionCH/l10n_switzerland <https://github.com/CompassionCH/l10n_switzerland/tree/14.0/l10n_ch_import_payment_return>`_ project on GitHub. | ||
|
||
You are welcome to contribute. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
from . import wizard | ||
from . import components |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
# Copyright 2023 Compassion CH (<https://www.compassion.ch>) | ||
# @author: Simon Gonzalez <simon.gonzalez@bluewin.ch> | ||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). | ||
|
||
{ | ||
"name": "l10n_ch_import_payment_return", | ||
"version": "14.0.1.0.0", | ||
"development_status": "Beta", | ||
"license": "AGPL-3", | ||
"author": "Compassion CH,Odoo Community Association (OCA)", | ||
"website": "https://github.com/OCA/l10n-switzerland", | ||
"category": "Banking addons", | ||
"depends": ["account_payment_export_sftp"], # OCA/bank-payment | ||
"data": ["data/edi_data.xml"], | ||
"installable": True, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from . import edi_import_payment_return |
31 changes: 31 additions & 0 deletions
31
l10n_ch_import_payment_return/components/edi_import_payment_return.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
# Copyright 2023 Compassion CH (https://www.compassion.ch) | ||
# @author: Simon Gonzalez <simon.gonzalez@bluewin.ch> | ||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). | ||
import base64 | ||
|
||
from odoo.addons.component.core import Component | ||
|
||
from ..wizard.pain_parser_ch import PainParserCH | ||
|
||
|
||
class EDIExchangeProcessPaymentReturn(Component): | ||
"""ACK for payment order pain002.01.03.CH""" | ||
|
||
_name = "edi.input.payment.ch.process" | ||
_inherit = "edi.component.input.mixin" | ||
_backend_type = "sftp_pay_ord_ack" | ||
_usage = "input.process" | ||
|
||
def process(self): | ||
origin_output = self.exchange_record.parent_id | ||
payment_order = self.env[origin_output.model].browse( | ||
self.exchange_record.parent_id.res_id | ||
) | ||
try: | ||
PainParserCH().validate_initial_return( | ||
base64.b64decode(self.exchange_record.exchange_file) | ||
) | ||
except Exception as e: | ||
payment_order.action_cancel() | ||
raise e | ||
payment_order.generated2uploaded() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
<?xml version="1.0" encoding="utf-8" ?> | ||
<odoo noupdate="1"> | ||
<record id="edi_ack_backend" model="edi.backend.type"> | ||
<field name="name">SFTP for payment orders with ack</field> | ||
<field name="code">sftp_pay_ord_ack</field> | ||
</record> | ||
</odoo> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
* Simon Gonzalez <simon.gonzalez@bluewin.ch> (https://compassion.ch) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
This module add the functionality of processing the return of the payment orders |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
14.0.1.0.0 (2023-06-23) | ||
~~~~~~~~~~~~~~~~~~~~~~~ | ||
|
||
* [ADD] l10n_ch_import_payment_return |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
* Automate a generic treatment process of the files |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
To use this module, you need to: | ||
|
||
#. Go to EDI and configure a backend and an exchange type | ||
|
||
#. Create a payment order and choose an EDI exchange type | ||
|
||
#. When generating the file an edi exchange should be created | ||
|
||
#. When a return come back it should be processed by the parser |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from . import payment_return_import |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
# Copyright 2023 Compassion CH - Simon Gonzalez | ||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). | ||
|
||
import logging | ||
import re | ||
|
||
from lxml import etree | ||
|
||
from odoo.addons.account_payment_return_import_iso20022.wizard.pain_parser import ( | ||
PainParser, | ||
) | ||
|
||
_logger = logging.getLogger(__name__) | ||
|
||
ACCEPTANCE_STATUS = ["ACCP", "ACWC", "ACTC"] | ||
|
||
|
||
class AcceptedEmptyByBankException(ValueError): | ||
pass | ||
|
||
|
||
class PainParserCH(PainParser): | ||
"""Parser for SEPA Direct Debit Unpaid Report import files.""" | ||
|
||
def _get_root_ns(self, data): | ||
try: | ||
root = etree.fromstring(data, parser=etree.XMLParser(recover=True)) | ||
except etree.XMLSyntaxError: | ||
# ABNAmro is known to mix up encodings | ||
root = etree.fromstring(data.decode("iso-8859-15").encode("utf-8")) | ||
if root is None: | ||
raise ValueError("Not a valid xml file, or not an xml file at all.") | ||
ns = root.tag[1 : root.tag.index("}")] | ||
self.check_version(ns, root) | ||
return root, ns | ||
|
||
def get_origin_msg(self, file): | ||
root, ns = self._get_root_ns(file) | ||
ORIGIN_MSG_XML_NODE = ( | ||
"./ns:CstmrPmtStsRpt/ns:OrgnlGrpInfAndSts/ns:OrgnlMsgId", | ||
) | ||
found_node = root.xpath(ORIGIN_MSG_XML_NODE, namespaces={"ns": ns}) | ||
return found_node[0].text | ||
|
||
def check_version(self, ns, root): | ||
"""Validate validity of SEPA Direct Debit Unpaid Report file.""" | ||
# Check wether it is SEPA Direct Debit Unpaid Report at all: | ||
re_pain = re.compile(r"^http://www.six-interbank-clearing.com/.*/pain") | ||
if not re_pain.search(ns): | ||
raise ValueError("no pain: " + ns) | ||
# Check wether version 002.001.03.ch: | ||
re_pain_version = re.compile(r"|pain.002.001.03.ch.02.xsd") | ||
if not re_pain_version.search(ns): | ||
raise ValueError("no PAIN.002.001.03: " + ns) | ||
# Check GrpHdr element: | ||
root_0_0 = root[0][0].tag[len(ns) + 2 :] # strip namespace | ||
if root_0_0 != "GrpHdr": | ||
raise ValueError("expected GrpHdr, got: " + root_0_0) | ||
|
||
def validate_grp_status(self, ns, root): | ||
"""Validate the status of the pain 002""" | ||
STATUS_XML_NODE = "./ns:CstmrPmtStsRpt/ns:OrgnlGrpInfAndSts/ns:GrpSts" | ||
found_node = root.xpath(STATUS_XML_NODE, namespaces={"ns": ns}) | ||
if found_node: | ||
return_status = found_node[0].text | ||
_logger.info(f"File has this status {return_status}") | ||
if return_status in ACCEPTANCE_STATUS: | ||
return True | ||
elif return_status == "PART": | ||
return True | ||
elif return_status == "RJCT": | ||
info_status = root.xpath( | ||
"./ns:CstmrPmtStsRpt/ns:OrgnlGrpInfAndSts/ns:StsRsnInf/ns:AddtlInf", | ||
namespaces={"ns": ns}, | ||
) | ||
raise ValueError(f"File rejected !\nReason: {info_status[0].text}") | ||
else: | ||
raise ValueError("Status not known by Pain Parser CH") | ||
else: | ||
raise ValueError("Status Node not found") | ||
|
||
def validate_initial_return(self, data): | ||
root, ns = self._get_root_ns(data) | ||
self.validate_grp_status(ns, root) | ||
return root, ns | ||
|
||
def parse(self, data): | ||
"""Parse a pain.002.001.03 file.""" | ||
root, ns = self.validate_initial_return(data) | ||
payment_returns = [] | ||
for node in root: | ||
payment_return = super().parse_payment_return(ns, node) | ||
if payment_return["transactions"]: | ||
if not payment_return.get("account_number"): | ||
payment_return["account_number"] = False | ||
payment_returns.append(payment_return) | ||
return payment_returns |
33 changes: 33 additions & 0 deletions
33
l10n_ch_import_payment_return/wizard/payment_return_import.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
# Copyright 2016 Tecnativa - Carlos Dauden | ||
# Copyright 2019 ACSONE SA/NV | ||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). | ||
|
||
import logging | ||
|
||
from odoo import api, models | ||
|
||
from .pain_parser_ch import PainParserCH | ||
|
||
_logger = logging.getLogger(__name__) | ||
|
||
|
||
class PaymentReturnImport(models.TransientModel): | ||
_inherit = "payment.return.import" | ||
|
||
@api.model | ||
def _parse_single_document(self, data_file): | ||
""" | ||
Try to parse the file as the following format or fall back on next | ||
parser: | ||
- pain.002.001.03.CH | ||
""" | ||
pain_parser = PainParserCH() | ||
try: | ||
_logger.debug("Try parsing as a PAIN Direct Debit Unpaid CH " "Report.") | ||
return pain_parser.parse(data_file) | ||
except ValueError: | ||
_logger.debug( | ||
"Payment return file is not a ISO20022 CH " "supported file.", | ||
exc_info=True, | ||
) | ||
return super()._parse_single_document(data_file) |