diff --git a/addons/payment_adyen_paybylink/controllers/main.py b/addons/payment_adyen_paybylink/controllers/main.py
index 63ea206d506ee..3ad41a46bcab8 100644
--- a/addons/payment_adyen_paybylink/controllers/main.py
+++ b/addons/payment_adyen_paybylink/controllers/main.py
@@ -37,24 +37,30 @@ def adyen_notification(self, **post):
)
try:
# Check the integrity of the notification
- tx_sudo = request.env['payment.transaction'].sudo().\
- _adyen_form_get_tx_from_data(post)
- self._verify_notification_signature(post, tx_sudo)
-
- # Check whether the event of the notification succeeded and
- # reshape the notification data for parsing
event_code = post['eventCode']
- if event_code in ('AUTHORISATION', 'REFUND') and post['success'] == 'true':
- post['authResult'] = 'AUTHORISED'
+ if event_code == 'REPORT_AVAILABLE' and post['success'] == 'true':
+ # 'merchantReference': ''
+ # 'psp_reference': 'settlement_detail_report_batch_554.xlsx'
+ journal = request.env['account.journal'].sudo()._adyen_get_journal_from_data(post)
+ journal.download_report(post)
+ else:
+ tx_sudo = request.env['payment.transaction'].sudo(). \
+ _adyen_form_get_tx_from_data(post)
+ self._verify_notification_signature(post, tx_sudo)
- # Handle the notification data
- request.env['payment.transaction'].sudo().form_feedback(
- post, 'adyen')
+ # Check whether the event of the notification succeeded and
+ # reshape the notification data for parsing
+ if event_code in ('AUTHORISATION', 'REFUND') and post['success'] == 'true':
+ post['authResult'] = 'AUTHORISED'
- # Handle fraud cases
- elif (event_code == 'NOTIFICATION_OF_CHARGEBACK' and
- post['success'] == 'true'):
- tx_sudo.process_fraud_case(post)
+ # Handle the notification data
+ request.env['payment.transaction'].sudo().form_feedback(
+ post, 'adyen')
+
+ # Handle fraud cases
+ elif (event_code == 'NOTIFICATION_OF_CHARGEBACK' and
+ post['success'] == 'true'):
+ tx_sudo.process_fraud_case(post)
# Acknowledge the notification to avoid getting spammed
except ValidationError:
@@ -107,6 +113,7 @@ def _compute_signature(payload, hmac_key):
:return: The computed signature
:rtype: str
"""
+
def _flatten_dict(_value, _path_base='', _separator='.'):
""" Recursively generate a flat representation of a dict.
diff --git a/addons/payment_adyen_paybylink/models/__init__.py b/addons/payment_adyen_paybylink/models/__init__.py
index 8e04237423ad2..94f5179eb28e8 100644
--- a/addons/payment_adyen_paybylink/models/__init__.py
+++ b/addons/payment_adyen_paybylink/models/__init__.py
@@ -1,4 +1,5 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
+from . import account_journal
from . import payment_acquirer
from . import payment_transaction
diff --git a/addons/payment_adyen_paybylink/models/account_journal.py b/addons/payment_adyen_paybylink/models/account_journal.py
new file mode 100644
index 0000000000000..7acb8bf9de896
--- /dev/null
+++ b/addons/payment_adyen_paybylink/models/account_journal.py
@@ -0,0 +1,67 @@
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+import logging
+import subprocess
+
+from odoo import _, api, fields, models
+from odoo.exceptions import ValidationError, UserError
+
+_logger = logging.getLogger(__name__)
+
+
+def runcmd(cmd, verbose=False, *args, **kwargs):
+ process = subprocess.Popen(
+ cmd,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ text=True,
+ shell=True
+ )
+ std_out, std_err = process.communicate()
+ if verbose:
+ _logger.info(std_out.strip(), std_err)
+ pass
+
+
+class AccountJournal(models.Model):
+ _inherit = 'account.journal'
+
+ @api.model
+ def _adyen_get_journal_from_data(self, data):
+ merchant_account = data.get('merchantAccountCode')
+ if not merchant_account:
+ error_msg = _('Missing merchantAccountCode in REPORT_AVAILABLE notification from Adyen.')
+ _logger.info(error_msg)
+ raise ValidationError(error_msg)
+ journal = self.env['account.journal'].search([("adyen_merchant_account", "=", merchant_account)])
+ if len(journal) != 1:
+ error_msg = _(f'Expected 1 journal for Adyen Merchant Account: {merchant_account}. Found {len(journal)}')
+ _logger.info(error_msg)
+ raise ValidationError(error_msg)
+ return journal
+
+ @api.model
+ def download_report(self, post):
+ """ Download bank statement report from Adyen to the server
+ """
+ adyen_user = self.acquirer_id.adyen_report_user
+ adyen_pass = self.acquirer_id.adyen_report_password
+ if not adyen_user or not adyen_pass:
+ raise UserError(
+ f'User or password missing for acquirer {self.name} '
+ f'related to journal {self.acquirer_id.name}'
+ )
+ path = '/tmp/adyen/'
+ cmd = "mkdir -p {path} && wget -P {path} --http-user='{user}@Company.VANMOOF' " \
+ "--http-password='{pwd}' --no-check-certificate {url}".format(
+ path=path, user=adyen_user, pwd=adyen_pass, url=post["reason"])
+ try:
+ _logger.debug('Downloading {url} to {path}{file}'.format(
+ file=post['pspReference'], url=post["reason"], path=path))
+ runcmd(cmd, verbose=True)
+ return path + post['pspReference']
+ except Exception as e:
+ message = f"Download Failed for Ayden Report notification {post} \n " \
+ f"with the exception: {e.args[0]}."
+ _logger.error(message)
+ raise UserError(message)
diff --git a/addons/payment_adyen_paybylink/models/payment_acquirer.py b/addons/payment_adyen_paybylink/models/payment_acquirer.py
index c2e7df960429a..62e702b8f86cd 100644
--- a/addons/payment_adyen_paybylink/models/payment_acquirer.py
+++ b/addons/payment_adyen_paybylink/models/payment_acquirer.py
@@ -3,15 +3,15 @@
import logging
import re
import requests
+import subprocess
from werkzeug import urls
from odoo import _, api, fields, models
-from odoo.exceptions import ValidationError
+from odoo.exceptions import ValidationError, UserError
from odoo.addons.payment_adyen_paybylink.const import API_ENDPOINT_VERSIONS
-
_logger = logging.getLogger(__name__)
@@ -40,6 +40,8 @@ class PaymentAcquirer(models.Model):
# the 'NOT NULL' constraint on those fields.
adyen_skin_code = fields.Char(default="Do not use this field")
adyen_skin_hmac_key = fields.Char(default="Do not use this field")
+ adyen_report_user = fields.Char(string="Report User")
+ adyen_report_password = fields.Char(string="Reporting Password")
@api.model_create_multi
def create(self, values_list):
diff --git a/addons/payment_adyen_paybylink/views/payment_views.xml b/addons/payment_adyen_paybylink/views/payment_views.xml
index c88f4b4afe717..a1572ef693f96 100644
--- a/addons/payment_adyen_paybylink/views/payment_views.xml
+++ b/addons/payment_adyen_paybylink/views/payment_views.xml
@@ -19,6 +19,16 @@
+
+
+
+
+
+
+
+
+