diff --git a/.tx/config b/.tx/config index a0a2d819e63..b83a67de29c 100644 --- a/.tx/config +++ b/.tx/config @@ -67,11 +67,6 @@ file_filter = addons/account_tax_python/i18n/.po source_file = addons/account_tax_python/i18n/account_tax_python.pot source_lang = en -[odoo-master.adyen_platforms] -file_filter = addons/adyen_platforms/i18n/.po -source_file = addons/adyen_platforms/i18n/adyen_platforms.pot -source_lang = en - [odoo-master.analytic] file_filter = addons/analytic/i18n/.po source_file = addons/analytic/i18n/analytic.pot diff --git a/addons/adyen_platforms/__init__.py b/addons/adyen_platforms/__init__.py deleted file mode 100644 index 7d34c7c054a..00000000000 --- a/addons/adyen_platforms/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -# -*- coding: utf-8 -*- -# Part of Odoo. See LICENSE file for full copyright and licensing details. - -from . import controllers -from . import models diff --git a/addons/adyen_platforms/__manifest__.py b/addons/adyen_platforms/__manifest__.py deleted file mode 100644 index 056a00cb905..00000000000 --- a/addons/adyen_platforms/__manifest__.py +++ /dev/null @@ -1,32 +0,0 @@ -# -*- coding: utf-8 -*- -# Part of Odoo. See LICENSE file for full copyright and licensing details. - -{ - 'name': 'Adyen for Platforms', - 'version': '1.0', - 'category': '', - 'summary': 'Base Module for Adyen for Platforms', - 'description': 'Base Module for Adyen for Platforms, used in eCommerce and PoS', - 'depends': ['mail', 'web'], - 'data': [ - 'data/adyen_platforms_data.xml', - 'security/ir.model.access.csv', - 'security/ir_rule.xml', - 'views/adyen_account_templates.xml', - 'views/adyen_account_views.xml', - 'views/adyen_bank_account_views.xml', - 'views/adyen_shareholder_views.xml', - 'views/adyen_transaction_views.xml', - ], - 'installable': True, - 'assets': { - 'web.assets_backend': [ - 'adyen_platforms/static/src/scss/**/*', - 'adyen_platforms/static/src/js/**/*', - ], - 'web.assets_qweb': [ - 'adyen_platforms/static/src/xml/**/*', - ], - }, - 'license': 'LGPL-3', -} diff --git a/addons/adyen_platforms/controllers/__init__.py b/addons/adyen_platforms/controllers/__init__.py deleted file mode 100644 index 7ea350e3385..00000000000 --- a/addons/adyen_platforms/controllers/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -# -*- coding: utf-8 -*- -# Part of Odoo. See LICENSE file for full copyright and licensing details. - -from . import adyen_platforms diff --git a/addons/adyen_platforms/controllers/adyen_platforms.py b/addons/adyen_platforms/controllers/adyen_platforms.py deleted file mode 100644 index 0811f27d0c4..00000000000 --- a/addons/adyen_platforms/controllers/adyen_platforms.py +++ /dev/null @@ -1,45 +0,0 @@ -# Part of Odoo. See LICENSE file for full copyright and licensing details. - -import logging -from pprint import pformat - -from odoo import http -from odoo.http import request - -from odoo.addons.adyen_platforms.util import odoo_payments_proxy_control - -_logger = logging.getLogger(__name__) - - -class AdyenPlatformsController(http.Controller): - - @http.route('/adyen_platforms/create_account', type='http', auth='user', website=True) - def adyen_platforms_create_account(self, creation_token): - request.session['adyen_creation_token'] = creation_token - return request.redirect('/web?#action=adyen_platforms.adyen_account_action_create') - - @odoo_payments_proxy_control - @http.route('/adyen_platforms/account_notification', type='json', auth='public', csrf=False) - def adyen_platforms_notification(self): - data = request.jsonrequest - _logger.debug('Account notification received: %s', pformat(data)) - - account = request.env['adyen.account'].sudo().search([('adyen_uuid', '=', data['adyen_uuid'])]) - if not account: - _logger.error('Received notification for non-existing account: %s', data['adyen_uuid']) - return - - account.with_context(update_from_adyen=True)._handle_notification(data) - - @odoo_payments_proxy_control - @http.route('/adyen_platforms/transaction_notification', type='json', auth='public', csrf=False) - def adyen_transaction_notification(self): - data = request.jsonrequest - _logger.debug('Transaction notification received: %s', pformat(data)) - - account = request.env['adyen.account'].sudo().search([('adyen_uuid', '=', data['adyen_uuid'])]) - if not account: - _logger.error('Received notification for non-existing account: %s', data['adyen_uuid']) - return - - request.env['adyen.transaction'].sudo()._handle_notification(data) diff --git a/addons/adyen_platforms/data/adyen_platforms_data.xml b/addons/adyen_platforms/data/adyen_platforms_data.xml deleted file mode 100644 index 7914731e532..00000000000 --- a/addons/adyen_platforms/data/adyen_platforms_data.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - adyen_platforms.proxy_url - https://payment-adyen.odoo.com/payment_proxy_adyen/ - - - - adyen_platforms.onboarding_url - https://www.odoo.com/odoo_adyen/ - - - - Odoo Payments Sync - - code - model._sync_adyen_cron() - - 1 - days - -1 - - - - diff --git a/addons/adyen_platforms/i18n/adyen_platforms.pot b/addons/adyen_platforms/i18n/adyen_platforms.pot deleted file mode 100644 index a21bbb3f69d..00000000000 --- a/addons/adyen_platforms/i18n/adyen_platforms.pot +++ /dev/null @@ -1,1631 +0,0 @@ -# Translation of Odoo Server. -# This file contains the translation of the following modules: -# * adyen_platforms -# -msgid "" -msgstr "" -"Project-Id-Version: Odoo Server saas~14.4\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-07-12 07:50+0000\n" -"PO-Revision-Date: 2021-07-12 07:50+0000\n" -"Last-Translator: \n" -"Language-Team: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: \n" -"Plural-Forms: \n" - -#. module: adyen_platforms -#. openerp-web -#: code:addons/adyen_platforms/static/src/xml/adyen_transactions_templates.xml:0 -#, python-format -msgid "- Balance" -msgstr "" - -#. module: adyen_platforms -#. openerp-web -#: code:addons/adyen_platforms/static/src/xml/adyen_account_templates.xml:0 -#, python-format -msgid "" -". If we or our\n" -" Processor at any time discover that the information you provided about your\n" -" business is incorrect or has changed without informing us or if you violate any of\n" -" these conditions, the services may be suspended and/or terminated with\n" -" immediate effect and fines may be applied by the Credit Card Schemes and/or the\n" -" authorities for unregistered or inappropriate use of payment services which will in\n" -" such case be payable by you." -msgstr "" - -#. module: adyen_platforms -#: model_terms:ir.ui.view,arch_db:adyen_platforms.adyen_account_view_form -msgid " Transactions" -msgstr "" - -#. module: adyen_platforms -#: model_terms:ir.ui.view,arch_db:adyen_platforms.adyen_account_view_form -msgid "A bank account is required to perform payouts." -msgstr "" - -#. module: adyen_platforms -#: code:addons/adyen_platforms/models/adyen_account.py:0 -#, python-format -msgid "A timeout occurred while trying to reach the Adyen proxy." -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.constraint,message:adyen_platforms.constraint_adyen_transaction_reference_unique -msgid "A transaction with the same reference already exists." -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__account_code -msgid "Account Code" -msgstr "" - -#. module: adyen_platforms -#: model:ir.actions.server,name:adyen_platforms.adyen_account_action -msgid "Account Configuration" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__account_holder_code -msgid "Account Holder Code" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_bank_account__account_number -msgid "Account Number" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__state -msgid "Account State" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_bank_account__account_type -msgid "Account Type" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__message_needaction -msgid "Action Needed" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_account__account_status__active -msgid "Active" -msgstr "" - -#. module: adyen_platforms -#. openerp-web -#: code:addons/adyen_platforms/static/src/xml/adyen_account_templates.xml:0 -#: model_terms:ir.ui.view,arch_db:adyen_platforms.adyen_account_view_form -#: model_terms:ir.ui.view,arch_db:adyen_platforms.adyen_shareholder_view_form -#, python-format -msgid "Address" -msgstr "" - -#. module: adyen_platforms -#: code:addons/adyen_platforms/models/adyen_account.py:0 -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account_balance__adyen_account_id -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_bank_account__adyen_account_id -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_kyc__adyen_account_id -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_shareholder__adyen_account_id -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_transaction__adyen_account_id -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_transaction_payout__adyen_account_id -#: model:ir.model.fields,field_description:adyen_platforms.field_res_company__adyen_account_id -#: model_terms:ir.ui.view,arch_db:adyen_platforms.adyen_account_view_form -#, python-format -msgid "Adyen Account" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model,name:adyen_platforms.model_adyen_account_balance -msgid "Adyen Account Balance" -msgstr "" - -#. module: adyen_platforms -#: model_terms:ir.ui.view,arch_db:adyen_platforms.adyen_bank_account_view_form -msgid "Adyen Bank Account" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model,name:adyen_platforms.model_adyen_kyc -msgid "Adyen KYC checks" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_bank_account__adyen_kyc_ids -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_shareholder__adyen_kyc_ids -msgid "Adyen Kyc" -msgstr "" - -#. module: adyen_platforms -#. openerp-web -#: code:addons/adyen_platforms/static/src/xml/adyen_account_templates.xml:0 -#, python-format -msgid "Adyen MarketPay Terms and Conditions (click" -msgstr "" - -#. module: adyen_platforms -#. openerp-web -#: code:addons/adyen_platforms/static/src/xml/adyen_account_templates.xml:0 -#, python-format -msgid "Adyen Restricted and Prohibited Products and Services list (click" -msgstr "" - -#. module: adyen_platforms -#: model_terms:ir.ui.view,arch_db:adyen_platforms.adyen_shareholder_view_form -msgid "Adyen Shareholder" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_transaction_status__adyen_transaction_id -msgid "Adyen Transaction" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__adyen_uuid -msgid "Adyen UUID" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.constraint,message:adyen_platforms.constraint_adyen_account_adyen_uuid_uniq -msgid "Adyen UUID should be unique" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model,name:adyen_platforms.model_adyen_account -msgid "Adyen for Platforms Account" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model,name:adyen_platforms.model_adyen_address_mixin -msgid "Adyen for Platforms Address Mixin" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model,name:adyen_platforms.model_adyen_bank_account -msgid "Adyen for Platforms Bank Account" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model,name:adyen_platforms.model_adyen_id_mixin -msgid "Adyen for Platforms ID Mixin" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model,name:adyen_platforms.model_adyen_shareholder -msgid "Adyen for Platforms Shareholder" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model,name:adyen_platforms.model_adyen_transaction -msgid "Adyen for Platforms Transaction" -msgstr "" - -#. module: adyen_platforms -#: code:addons/adyen_platforms/models/adyen_bank_account.py:0 -#, python-format -msgid "" -"Allowed file formats for bank statements are jpeg, jpg, pdf or png. Received" -" %r instead." -msgstr "" - -#. module: adyen_platforms -#: code:addons/adyen_platforms/models/adyen_mixins.py:0 -#, python-format -msgid "Allowed file formats for photo IDs are jpeg, jpg, pdf or png" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,help:adyen_platforms.field_adyen_account__id_back -#: model:ir.model.fields,help:adyen_platforms.field_adyen_account__id_front -#: model:ir.model.fields,help:adyen_platforms.field_adyen_id_mixin__id_back -#: model:ir.model.fields,help:adyen_platforms.field_adyen_id_mixin__id_front -#: model:ir.model.fields,help:adyen_platforms.field_adyen_shareholder__id_back -#: model:ir.model.fields,help:adyen_platforms.field_adyen_shareholder__id_front -msgid "Allowed formats: jpg, pdf, png. Maximum allowed size: 4MB." -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_transaction_payout__amount -#: model_terms:ir.ui.view,arch_db:adyen_platforms.adyen_transaction_payout_view_list -msgid "Amount" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__message_attachment_count -msgid "Attachment Count" -msgstr "" - -#. module: adyen_platforms -#: model:ir.actions.act_window,name:adyen_platforms.adyen_balance_action -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account_balance__balance -msgid "Balance" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_kyc__bank_account_id -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_transaction_payout__bank_account_id -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_kyc__verification_type__bank_account -msgid "Bank Account" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__bank_account_ids -#: model_terms:ir.ui.view,arch_db:adyen_platforms.adyen_account_view_form -msgid "Bank Accounts" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_bank_account__bank_city -msgid "Bank City" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_bank_account__bank_code -msgid "Bank Code" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_bank_account__bank_name -msgid "Bank Name" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_bank_account__bank_statement -msgid "Bank Statement" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_bank_account__bank_statement_filename -msgid "Bank Statement Filename" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_account__payout_schedule__biweekly -msgid "Bi-weekly" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_bank_account__branch_code -msgid "Branch Code" -msgstr "" - -#. module: adyen_platforms -#. openerp-web -#: code:addons/adyen_platforms/static/src/xml/adyen_account_templates.xml:0 -#: model_terms:ir.ui.view,arch_db:adyen_platforms.adyen_account_view_form -#, python-format -msgid "Business" -msgstr "" - -#. module: adyen_platforms -#. openerp-web -#: code:addons/adyen_platforms/static/src/js/adyen_account_views.js:0 -#, python-format -msgid "Cancel" -msgstr "" - -#. module: adyen_platforms -#: code:addons/adyen_platforms/models/adyen_account.py:0 -#, python-format -msgid "Cannot update account balance, showing previous values: %s" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_transaction__capture_reference -msgid "Capture Reference" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_kyc__verification_type__card -msgid "Card" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_transaction__card_country_id -msgid "Card Country" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_transaction_status__status__chargeback -msgid "Chargeback" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_transaction_status__status__chargebackreceived -msgid "Chargeback Received" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_transaction_status__status__chargebackreversed -msgid "Chargeback Reversed" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_transaction_status__status__chargebackreversedreceived -msgid "Chargeback Reversed Received" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_bank_account__account_type__checking -msgid "Checking" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__city -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_address_mixin__city -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_shareholder__city -#: model_terms:ir.ui.view,arch_db:adyen_platforms.adyen_account_view_form -#: model_terms:ir.ui.view,arch_db:adyen_platforms.adyen_bank_account_view_form -#: model_terms:ir.ui.view,arch_db:adyen_platforms.adyen_shareholder_view_form -msgid "City" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_account__account_status__closed -msgid "Closed" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_transaction__commercial_card -msgid "Commercial Card" -msgstr "" - -#. module: adyen_platforms -#. openerp-web -#: code:addons/adyen_platforms/static/src/xml/adyen_account_templates.xml:0 -#, python-format -msgid "Commercial and non-EU cards: 2.8% + 0.20€" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model,name:adyen_platforms.model_res_company -msgid "Companies" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__company_id -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_kyc__verification_type__company -msgid "Company" -msgstr "" - -#. module: adyen_platforms -#. openerp-web -#: code:addons/adyen_platforms/static/src/js/adyen_account_views.js:0 -#, python-format -msgid "Confirm your Adyen Account Creation" -msgstr "" - -#. module: adyen_platforms -#. openerp-web -#: code:addons/adyen_platforms/static/src/xml/adyen_account_templates.xml:0 -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_bank_account__kyc_status__passed -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_kyc__status__passed -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_shareholder__kyc_status__passed -#, python-format -msgid "Confirmed" -msgstr "" - -#. module: adyen_platforms -#: model_terms:ir.ui.view,arch_db:adyen_platforms.adyen_account_view_form -msgid "Contact" -msgstr "" - -#. module: adyen_platforms -#. openerp-web -#: code:addons/adyen_platforms/static/src/xml/adyen_account_templates.xml:0 -#, python-format -msgid "Contractual Relationship" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_transaction_status__status__converted -msgid "Converted" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__country_id -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_address_mixin__country_id -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_bank_account__country_id -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_shareholder__country_id -#: model_terms:ir.ui.view,arch_db:adyen_platforms.adyen_account_view_form -#: model_terms:ir.ui.view,arch_db:adyen_platforms.adyen_bank_account_view_form -#: model_terms:ir.ui.view,arch_db:adyen_platforms.adyen_shareholder_view_form -msgid "Country" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__country_code -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_address_mixin__country_code -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_bank_account__country_code -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_shareholder__country_code -msgid "Country Code" -msgstr "" - -#. module: adyen_platforms -#. openerp-web -#: code:addons/adyen_platforms/static/src/js/adyen_account_views.js:0 -#, python-format -msgid "Create" -msgstr "" - -#. module: adyen_platforms -#: model:ir.actions.act_window,name:adyen_platforms.adyen_account_action_create -msgid "Create an Adyen Account" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__create_uid -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account_balance__create_uid -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_bank_account__create_uid -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_kyc__create_uid -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_shareholder__create_uid -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_transaction__create_uid -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_transaction_payout__create_uid -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_transaction_status__create_uid -msgid "Created by" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__create_date -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account_balance__create_date -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_bank_account__create_date -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_kyc__create_date -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_shareholder__create_date -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_transaction__create_date -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_transaction_payout__create_date -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_transaction_status__create_date -msgid "Created on" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_transaction_status__status__creditfailed -msgid "Credit Failed" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_transaction_status__status__credited -msgid "Credited" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account_balance__currency_id -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_bank_account__currency_id -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_transaction__currency_id -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_transaction_payout__currency_id -#: model_terms:ir.ui.view,arch_db:adyen_platforms.adyen_transaction_payout_view_search -#: model_terms:ir.ui.view,arch_db:adyen_platforms.adyen_transaction_view_search -msgid "Currency" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,help:adyen_platforms.field_adyen_bank_account__currency_name -msgid "Currency Code (ISO 4217)" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_bank_account__currency_name -msgid "Currency Name" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_transaction__total_amount -msgid "Customer Amount" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_account__payout_schedule__daily -msgid "Daily" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_bank_account__kyc_status__data_provided -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_kyc__status__data_provided -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_shareholder__kyc_status__data_provided -msgid "Data Provided" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_account__state__awaiting_data -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_bank_account__kyc_status__awaiting_data -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_kyc__status__awaiting_data -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_shareholder__kyc_status__awaiting_data -msgid "Data To Provide" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_account__state__validation -msgid "Data Validation" -msgstr "" - -#. module: adyen_platforms -#. openerp-web -#: code:addons/adyen_platforms/static/src/xml/adyen_account_templates.xml:0 -#, python-format -msgid "Data to provide" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_transaction__date -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_transaction_payout__date -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_transaction_status__date -#: model_terms:ir.ui.view,arch_db:adyen_platforms.adyen_transaction_payout_view_search -#: model_terms:ir.ui.view,arch_db:adyen_platforms.adyen_transaction_view_search -msgid "Date" -msgstr "" - -#. module: adyen_platforms -#. openerp-web -#: code:addons/adyen_platforms/static/src/xml/adyen_account_templates.xml:0 -#, python-format -msgid "Date of Birth" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__date_of_birth -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_shareholder__date_of_birth -msgid "Date of birth" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_transaction_status__status__debitfailed -msgid "Debit Failed" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_transaction_status__status__debitedreversed -msgid "Debit Reversed" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_transaction_status__status__debitreversedreceived -msgid "Debit Reversed Received" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_transaction_status__status__debited -msgid "Debited" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_transaction__description -msgid "Description" -msgstr "" - -#. module: adyen_platforms -#. openerp-web -#: code:addons/adyen_platforms/static/src/xml/adyen_account_templates.xml:0 -#, python-format -msgid "Disclaimers" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__display_name -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account_balance__display_name -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_bank_account__display_name -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_kyc__display_name -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_shareholder__display_name -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_transaction__display_name -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_transaction_payout__display_name -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_transaction_status__display_name -msgid "Display Name" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_transaction__dispute_reference -msgid "Dispute Reference" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_kyc__document -msgid "Document" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__document_type -msgid "Document Type" -msgstr "" - -#. module: adyen_platforms -#. openerp-web -#: code:addons/adyen_platforms/static/src/xml/adyen_account_templates.xml:0 -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__doing_business_as -#, python-format -msgid "Doing Business As" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_account__id_type__driving_license -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_id_mixin__id_type__driving_license -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_shareholder__id_type__driving_license -msgid "Driving License" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_account__document_type__drivinglicense -msgid "Driving license" -msgstr "" - -#. module: adyen_platforms -#. openerp-web -#: code:addons/adyen_platforms/static/src/xml/adyen_account_templates.xml:0 -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__email -#, python-format -msgid "Email" -msgstr "" - -#. module: adyen_platforms -#. openerp-web -#: code:addons/adyen_platforms/static/src/xml/adyen_account_templates.xml:0 -#, python-format -msgid "European consumer cards: 1.3% + 0.20€" -msgstr "" - -#. module: adyen_platforms -#. openerp-web -#: code:addons/adyen_platforms/static/src/xml/adyen_account_templates.xml:0 -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_bank_account__kyc_status__failed -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_kyc__status__failed -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_shareholder__kyc_status__failed -#, python-format -msgid "Failed" -msgstr "" - -#. module: adyen_platforms -#: code:addons/adyen_platforms/models/adyen_account.py:0 -#, python-format -msgid "Failed payout: %s" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_transaction__reason -msgid "Failure Reason" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_transaction__fees -msgid "Fees" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_transaction__fees_currency_id -msgid "Fees Currency" -msgstr "" - -#. module: adyen_platforms -#. openerp-web -#: code:addons/adyen_platforms/static/src/xml/adyen_account_templates.xml:0 -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__first_name -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_shareholder__first_name -#, python-format -msgid "First Name" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_transaction__fixed_fees -msgid "Fixed Fees" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__message_follower_ids -msgid "Followers" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__message_partner_ids -msgid "Followers (Partners)" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__full_name -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_shareholder__full_name -msgid "Full Name" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_transaction_status__status__fundtransfer -msgid "Fund Transfer" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__has_message -msgid "Has Message" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__house_number_or_name -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_address_mixin__house_number_or_name -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_shareholder__house_number_or_name -msgid "House Number Or Name" -msgstr "" - -#. module: adyen_platforms -#: model_terms:ir.ui.view,arch_db:adyen_platforms.adyen_account_view_form -#: model_terms:ir.ui.view,arch_db:adyen_platforms.adyen_bank_account_view_form -#: model_terms:ir.ui.view,arch_db:adyen_platforms.adyen_shareholder_view_form -msgid "House number or name" -msgstr "" - -#. module: adyen_platforms -#. openerp-web -#: code:addons/adyen_platforms/static/src/xml/adyen_account_templates.xml:0 -#, python-format -msgid "" -"I confirm I have taken notice of and accept the following terms and " -"restrictions:" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_bank_account__iban -msgid "IBAN" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__id -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account_balance__id -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_bank_account__id -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_kyc__id -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_shareholder__id -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_transaction__id -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_transaction_payout__id -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_transaction_status__id -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_account__document_type__id -msgid "ID" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_account__id_type__id_card -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_id_mixin__id_type__id_card -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_shareholder__id_type__id_card -msgid "ID Card" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__document_number -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_shareholder__document_number -msgid "ID Number" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__id_back_filename -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_id_mixin__id_back_filename -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_shareholder__id_back_filename -msgid "Id Back Filename" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__id_front_filename -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_id_mixin__id_front_filename -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_shareholder__id_front_filename -msgid "Id Front Filename" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_kyc__verification_type__identity -msgid "Identity" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,help:adyen_platforms.field_adyen_account__message_needaction -#: model:ir.model.fields,help:adyen_platforms.field_adyen_account__message_unread -msgid "If checked, new messages require your attention." -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,help:adyen_platforms.field_adyen_account__message_has_error -msgid "If checked, some messages have a delivery error." -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_account__account_status__inactive -msgid "Inactive" -msgstr "" - -#. module: adyen_platforms -#. openerp-web -#: code:addons/adyen_platforms/static/src/xml/adyen_account_templates.xml:0 -#: model_terms:ir.ui.view,arch_db:adyen_platforms.adyen_account_view_form -#, python-format -msgid "Individual" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__account_status -msgid "Internal Account Status" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__message_is_follower -msgid "Is Follower" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__is_business -msgid "Is a business" -msgstr "" - -#. module: adyen_platforms -#: model_terms:ir.ui.view,arch_db:adyen_platforms.adyen_account_view_form -msgid "KYC" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__adyen_kyc_ids -msgid "KYC Checks" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_kyc__verification_type -msgid "KYC Document" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_kyc__status -msgid "KYC Status" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__kyc_tier -msgid "KYC Tier" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_bank_account__kyc_status -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_shareholder__kyc_status -msgid "Kyc Status" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__kyc_status_message -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_bank_account__kyc_status_message -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_shareholder__kyc_status_message -msgid "Kyc Status Message" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account____last_update -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account_balance____last_update -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_bank_account____last_update -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_kyc____last_update -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_shareholder____last_update -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_transaction____last_update -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_transaction_payout____last_update -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_transaction_status____last_update -msgid "Last Modified on" -msgstr "" - -#. module: adyen_platforms -#. openerp-web -#: code:addons/adyen_platforms/static/src/xml/adyen_account_templates.xml:0 -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__last_name -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_shareholder__last_name -#, python-format -msgid "Last Name" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_transaction__last_status_id -msgid "Last Status" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_transaction__last_status_update -#: model_terms:ir.ui.view,arch_db:adyen_platforms.adyen_transaction_view_search -msgid "Last Status Update" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__last_sync_date -msgid "Last Sync Date" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_kyc__last_update -msgid "Last Update" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__write_uid -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account_balance__write_uid -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_bank_account__write_uid -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_kyc__write_uid -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_shareholder__write_uid -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_transaction__write_uid -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_transaction_payout__write_uid -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_transaction_status__write_uid -msgid "Last Updated by" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__write_date -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account_balance__write_date -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_bank_account__write_date -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_kyc__write_date -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_shareholder__write_date -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_transaction__write_date -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_transaction_payout__write_date -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_transaction_status__write_date -msgid "Last Updated on" -msgstr "" - -#. module: adyen_platforms -#. openerp-web -#: code:addons/adyen_platforms/static/src/xml/adyen_account_templates.xml:0 -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__legal_business_name -#, python-format -msgid "Legal Business Name" -msgstr "" - -#. module: adyen_platforms -#. openerp-web -#: code:addons/adyen_platforms/static/src/xml/adyen_account_templates.xml:0 -#: code:addons/adyen_platforms/static/src/xml/adyen_account_templates.xml:0 -#, python-format -msgid "Legal Entity" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__message_main_attachment_id -msgid "Main Attachment" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_transaction_status__status__manualcorrected -msgid "Manual Corrected" -msgstr "" - -#. module: adyen_platforms -#: code:addons/adyen_platforms/models/adyen_bank_account.py:0 -#, python-format -msgid "Maximum allowed size for bank statements: 4MB." -msgstr "" - -#. module: adyen_platforms -#: code:addons/adyen_platforms/models/adyen_mixins.py:0 -#, python-format -msgid "Maximum allowed size for photo ID: 4 MB." -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_transaction__merchant_amount -msgid "Merchant Amount" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__message_has_error -msgid "Message Delivery error" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__message_ids -msgid "Messages" -msgstr "" - -#. module: adyen_platforms -#: code:addons/adyen_platforms/models/adyen_bank_account.py:0 -#, python-format -msgid "" -"Minimum allowed size for bank statements: 1 KB for PDF, 100 KB for other " -"formats." -msgstr "" - -#. module: adyen_platforms -#: code:addons/adyen_platforms/models/adyen_mixins.py:0 -#, python-format -msgid "" -"Minimum allowed size for photo ID: 1 KB for PDF, 100 KB for other formats." -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_account__payout_schedule__monthly -msgid "Monthly" -msgstr "" - -#. module: adyen_platforms -#. openerp-web -#: code:addons/adyen_platforms/static/src/xml/adyen_transactions_templates.xml:0 -#, python-format -msgid "Next Payout Date:" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__next_scheduled_payout -msgid "Next Scheduled Payout" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_transaction__commercial_card__no -msgid "No" -msgstr "" - -#. module: adyen_platforms -#: model_terms:ir.actions.act_window,help:adyen_platforms.adyen_balance_action -msgid "No payouts yet." -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_kyc__verification_type__nonprofit -msgid "Nonprofit" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__message_needaction_counter -msgid "Number of Actions" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__message_has_error_counter -msgid "Number of errors" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,help:adyen_platforms.field_adyen_account__message_needaction_counter -msgid "Number of messages which requires an action" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,help:adyen_platforms.field_adyen_account__message_has_error_counter -msgid "Number of messages with delivery error" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,help:adyen_platforms.field_adyen_account__message_unread_counter -msgid "Number of unread messages" -msgstr "" - -#. module: adyen_platforms -#: model:ir.actions.server,name:adyen_platforms.adyen_sync_cron_ir_actions_server -#: model:ir.cron,cron_name:adyen_platforms.adyen_sync_cron -#: model:ir.cron,name:adyen_platforms.adyen_sync_cron -msgid "Odoo Payments Sync" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account_balance__on_hold -msgid "On Hold" -msgstr "" - -#. module: adyen_platforms -#: code:addons/adyen_platforms/models/adyen_account.py:0 -#, python-format -msgid "Other" -msgstr "" - -#. module: adyen_platforms -#: model_terms:ir.ui.view,arch_db:adyen_platforms.adyen_bank_account_view_form -msgid "Owner Address" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_bank_account__owner_city -msgid "Owner City" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_bank_account__owner_country_id -msgid "Owner Country" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_bank_account__owner_house_number_or_name -msgid "Owner House Number or Name" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_bank_account__owner_name -msgid "Owner Name" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_bank_account__owner_state_id -msgid "Owner State" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_bank_account__owner_street -msgid "Owner Street" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_bank_account__owner_zip -msgid "Owner ZIP" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_account__document_type__passport -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_account__id_type__passport -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_id_mixin__id_type__passport -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_kyc__verification_type__passport -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_shareholder__id_type__passport -msgid "Passport" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_transaction__payment_method -msgid "Payment Method" -msgstr "" - -#. module: adyen_platforms -#: model:ir.actions.act_window,name:adyen_platforms.adyen_transaction_action -msgid "Payment Transactions" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_transaction_payout__status__payout -msgid "Payout" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__payout_allowed -msgid "Payout Allowed" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_transaction_payout__status__payoutreversed -msgid "Payout Reversed" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__payout_schedule -msgid "Payout Schedule" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model,name:adyen_platforms.model_adyen_transaction_payout -msgid "Payout Transaction" -msgstr "" - -#. module: adyen_platforms -#: model_terms:ir.ui.view,arch_db:adyen_platforms.adyen_account_view_form -#: model_terms:ir.ui.view,arch_db:adyen_platforms.adyen_transaction_payout_view_search -msgid "Payouts" -msgstr "" - -#. module: adyen_platforms -#. openerp-web -#: code:addons/adyen_platforms/static/src/xml/adyen_account_templates.xml:0 -#, python-format -msgid "Payouts will be blocked until your application has been accepted." -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account_balance__pending -msgid "Pending" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_transaction_status__status__pendingcredit -msgid "Pending Credit" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_transaction_status__status__pendingdebit -msgid "Pending Debit" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_transaction_status__status__pendingfundtransfer -msgid "Pending Fund Transfer" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_account__state__pending -msgid "Pending Validation" -msgstr "" - -#. module: adyen_platforms -#. openerp-web -#: code:addons/adyen_platforms/static/src/xml/adyen_account_templates.xml:0 -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__phone_number -#, python-format -msgid "Phone Number" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__id_back -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_id_mixin__id_back -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_shareholder__id_back -msgid "Photo ID Back" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__id_front -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_id_mixin__id_front -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_shareholder__id_front -msgid "Photo ID Front" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__id_type -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_id_mixin__id_type -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_shareholder__id_type -msgid "Photo ID type" -msgstr "" - -#. module: adyen_platforms -#. openerp-web -#: code:addons/adyen_platforms/static/src/xml/adyen_account_templates.xml:0 -#, python-format -msgid "Pricing" -msgstr "" - -#. module: adyen_platforms -#. openerp-web -#: code:addons/adyen_platforms/static/src/xml/adyen_account_templates.xml:0 -#, python-format -msgid "Prohibited Products and Services List of our Processor" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__proxy_token -msgid "Proxy Token" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_bank_account__bank_account_reference -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_shareholder__shareholder_reference -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_transaction__reference -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_transaction_payout__reference -msgid "Reference" -msgstr "" - -#. module: adyen_platforms -#: model_terms:ir.ui.view,arch_db:adyen_platforms.adyen_transaction_view_form -msgid "Refund" -msgstr "" - -#. module: adyen_platforms -#. openerp-web -#: code:addons/adyen_platforms/static/src/xml/adyen_account_templates.xml:0 -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__registration_number -#, python-format -msgid "Registration Number" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_bank_account__account_type__savings -msgid "Savings" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_kyc__shareholder_id -msgid "Shareholder" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__shareholder_ids -#: model_terms:ir.ui.view,arch_db:adyen_platforms.adyen_account_view_form -msgid "Shareholders" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_transaction__shopper_country_id -msgid "Shopper Country" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_transaction__signature -msgid "Signature" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__state_id -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_address_mixin__state_id -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_shareholder__state_id -#: model_terms:ir.ui.view,arch_db:adyen_platforms.adyen_account_view_form -#: model_terms:ir.ui.view,arch_db:adyen_platforms.adyen_bank_account_view_form -#: model_terms:ir.ui.view,arch_db:adyen_platforms.adyen_shareholder_view_form -msgid "State" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__state_code -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_address_mixin__state_code -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_shareholder__state_code -msgid "State Code" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_transaction__status -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_transaction_status__status -msgid "Status" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_transaction__status_ids -msgid "Status History" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_kyc__status_message -msgid "Status Message" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__street -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_address_mixin__street -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_shareholder__street -#: model_terms:ir.ui.view,arch_db:adyen_platforms.adyen_account_view_form -#: model_terms:ir.ui.view,arch_db:adyen_platforms.adyen_bank_account_view_form -#: model_terms:ir.ui.view,arch_db:adyen_platforms.adyen_shareholder_view_form -msgid "Street" -msgstr "" - -#. module: adyen_platforms -#. openerp-web -#: code:addons/adyen_platforms/static/src/xml/adyen_account_templates.xml:0 -#, python-format -msgid "Submitted data" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_account__account_status__suspended -msgid "Suspended" -msgstr "" - -#. module: adyen_platforms -#: model_terms:ir.ui.view,arch_db:adyen_platforms.adyen_account_view_form -msgid "Sync Transactions" -msgstr "" - -#. module: adyen_platforms -#: code:addons/adyen_platforms/models/adyen_account.py:0 -#, python-format -msgid "The Adyen proxy is not reachable, please try again later." -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,help:adyen_platforms.field_adyen_account__country_code -#: model:ir.model.fields,help:adyen_platforms.field_adyen_address_mixin__country_code -#: model:ir.model.fields,help:adyen_platforms.field_adyen_bank_account__country_code -#: model:ir.model.fields,help:adyen_platforms.field_adyen_shareholder__country_code -msgid "" -"The ISO country code in two chars. \n" -"You can use this field for quick search." -msgstr "" - -#. module: adyen_platforms -#. openerp-web -#: code:addons/adyen_platforms/static/src/xml/adyen_account_templates.xml:0 -#, python-format -msgid "" -"The payment processing services ordered by you by placing this order will be\n" -" provided to you by Adyen N.V. (hereafter “Processor”), with which you are\n" -" entering into a direct agreement by confirming this order. Odoo S.A.\n" -" (hereafter “We /Us”) will assist and support you in your use of the services to be\n" -" provided by the Processor and we will provide you first line assistance with and\n" -" enable you to connect to the systems of Processor to be able to use its services.\n" -" For this purpose, you hereby instruct Processor to provide us access to your data\n" -" and setting in Processor’s systems which are used by Processor to provide the\n" -" services and authorise us to manage these on your behalf." -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,help:adyen_platforms.field_adyen_account__state_code -#: model:ir.model.fields,help:adyen_platforms.field_adyen_address_mixin__state_code -#: model:ir.model.fields,help:adyen_platforms.field_adyen_shareholder__state_code -msgid "The state code." -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,help:adyen_platforms.field_adyen_account__document_number -#: model:ir.model.fields,help:adyen_platforms.field_adyen_shareholder__document_number -msgid "" -"The type of ID Number required depends on the country:\n" -"US: Social Security Number (9 digits or last 4 digits)\n" -"Canada: Social Insurance Number\n" -"Italy: Codice fiscale\n" -"Australia: Document Number" -msgstr "" - -#. module: adyen_platforms -#: model_terms:ir.actions.act_window,help:adyen_platforms.adyen_transaction_action -msgid "There are no transactions yet." -msgstr "" - -#. module: adyen_platforms -#: code:addons/adyen_platforms/models/adyen_transaction.py:0 -#, python-format -msgid "Transaction %s has been CHARGEBACK'ed: %s" -msgstr "" - -#. module: adyen_platforms -#: model_terms:ir.ui.view,arch_db:adyen_platforms.adyen_transaction_payout_view_search -#: model_terms:ir.ui.view,arch_db:adyen_platforms.adyen_transaction_view_search -msgid "Transaction Date" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__transaction_payout_ids -msgid "Transaction Payout" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model,name:adyen_platforms.model_adyen_transaction_status -msgid "Transaction Status" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__transaction_ids -#: model_terms:ir.ui.view,arch_db:adyen_platforms.adyen_transaction_view_search -msgid "Transactions" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__transactions_count -msgid "Transactions Count" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_transaction_payout__status -msgid "Type" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_bank_account__bank_account_uuid -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_shareholder__shareholder_uuid -msgid "UUID" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_transaction__commercial_card__unknown -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_transaction_payout__status__unknown -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_transaction_status__status__unknown -msgid "Unknown" -msgstr "" - -#. module: adyen_platforms -#: code:addons/adyen_platforms/models/adyen_transaction.py:0 -#, python-format -msgid "Unknown eventCode received: %s" -msgstr "" - -#. module: adyen_platforms -#: code:addons/adyen_platforms/models/adyen_account.py:0 -#, python-format -msgid "Unknown eventType received: %s" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__message_unread -msgid "Unread Messages" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__message_unread_counter -msgid "Unread Messages Counter" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_account__state__validated -msgid "Validated" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_transaction__variable_fees -msgid "Variable Fees" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_account__document_type__visa -msgid "Visa" -msgstr "" - -#. module: adyen_platforms -#. openerp-web -#: code:addons/adyen_platforms/static/src/xml/adyen_account_templates.xml:0 -#, python-format -msgid "" -"WARNING: Please note that the right to use the payment services is only for\n" -" sales in your own name. You may not resell, hire or on any other basis allow third\n" -" parties to use the payment services to enable such third parties to be paid for their\n" -" services. You may not use the payment services for different types of product and\n" -" services than as registered with your application. In particular you confirm that you\n" -" will not use the payment services for any type of product or service appearing in the" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_bank_account__kyc_status__pending -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_kyc__status__pending -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_shareholder__kyc_status__pending -msgid "Waiting For Validation" -msgstr "" - -#. module: adyen_platforms -#. openerp-web -#: code:addons/adyen_platforms/static/src/xml/adyen_account_templates.xml:0 -#, python-format -msgid "Waiting for validation" -msgstr "" - -#. module: adyen_platforms -#: code:addons/adyen_platforms/models/adyen_account.py:0 -#, python-format -msgid "" -"We had troubles reaching Adyen, please retry later or contact the support if" -" the problem persists" -msgstr "" - -#. module: adyen_platforms -#. openerp-web -#: code:addons/adyen_platforms/static/src/xml/adyen_account_templates.xml:0 -#, python-format -msgid "" -"We will notify you when the status of the review changes, or if additional " -"data is required." -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_account__payout_schedule__weekly -msgid "Weekly" -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields.selection,name:adyen_platforms.selection__adyen_transaction__commercial_card__yes -msgid "Yes" -msgstr "" - -#. module: adyen_platforms -#. openerp-web -#: code:addons/adyen_platforms/static/src/xml/adyen_account_templates.xml:0 -#, python-format -msgid "You can start processing payments as soon as your application is sent." -msgstr "" - -#. module: adyen_platforms -#: code:addons/adyen_platforms/models/adyen_account.py:0 -#, python-format -msgid "You can't access account balance." -msgstr "" - -#. module: adyen_platforms -#: code:addons/adyen_platforms/models/adyen_transaction.py:0 -#, python-format -msgid "You cannot refund more than the original amount." -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,help:adyen_platforms.field_adyen_bank_account__bank_statement -msgid "" -"You need to provide a bank statement to allow payouts. The file must" -" be a bank statement, a screenshot of your online banking environment, a " -"letter from the bank or a cheque and must contain the logo of the " -"bank or it's name in a unique font, the bank account details, the name of " -"the account holder. Allowed formats: jpg, pdf, png. Maximum allowed " -"size: 10MB." -msgstr "" - -#. module: adyen_platforms -#: model_terms:ir.ui.view,arch_db:adyen_platforms.adyen_account_view_form -msgid "Your account is Closed." -msgstr "" - -#. module: adyen_platforms -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_account__zip -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_address_mixin__zip -#: model:ir.model.fields,field_description:adyen_platforms.field_adyen_shareholder__zip -#: model_terms:ir.ui.view,arch_db:adyen_platforms.adyen_account_view_form -#: model_terms:ir.ui.view,arch_db:adyen_platforms.adyen_bank_account_view_form -#: model_terms:ir.ui.view,arch_db:adyen_platforms.adyen_shareholder_view_form -msgid "ZIP" -msgstr "" - -#. module: adyen_platforms -#. openerp-web -#: code:addons/adyen_platforms/static/src/xml/adyen_account_templates.xml:0 -#: code:addons/adyen_platforms/static/src/xml/adyen_account_templates.xml:0 -#, python-format -msgid "here" -msgstr "" - -#. module: adyen_platforms -#. openerp-web -#: code:addons/adyen_platforms/static/src/xml/adyen_account_templates.xml:0 -#: code:addons/adyen_platforms/static/src/xml/adyen_account_templates.xml:0 -#, python-format -msgid "to download and review)" -msgstr "" diff --git a/addons/adyen_platforms/models/__init__.py b/addons/adyen_platforms/models/__init__.py deleted file mode 100644 index 8dcf258f929..00000000000 --- a/addons/adyen_platforms/models/__init__.py +++ /dev/null @@ -1,10 +0,0 @@ -# -*- coding: utf-8 -*- -# Part of Odoo. See LICENSE file for full copyright and licensing details. - -from . import adyen_mixins -from . import adyen_account -from . import adyen_bank_account -from . import adyen_kyc -from . import adyen_shareholder -from . import adyen_transaction -from . import res_company diff --git a/addons/adyen_platforms/models/adyen_account.py b/addons/adyen_platforms/models/adyen_account.py deleted file mode 100644 index 1a033ec9e7b..00000000000 --- a/addons/adyen_platforms/models/adyen_account.py +++ /dev/null @@ -1,647 +0,0 @@ -# Part of Odoo. See LICENSE file for full copyright and licensing details. - -import logging -import uuid -from datetime import timedelta - -import requests -from ast import literal_eval -from dateutil.parser import parse -from pytz import UTC -from werkzeug.urls import url_join - -from odoo import _, api, fields, models -from odoo.exceptions import AccessError, UserError, ValidationError -from odoo.http import request -from odoo.osv import expression -from odoo.tools import format_amount, format_datetime - -from odoo.addons.adyen_platforms.util import AdyenProxyAuth, to_major_currency - -_logger = logging.getLogger(__name__) - -TIMEOUT = 60 -ADYEN_STATUS_MAP = { - 'Active': 'active', - 'Inactive': 'inactive', - 'Suspended': 'suspended', - 'Closed': 'closed', -} -ADYEN_VALIDATION_MAP = { - 'FAILED': 'failed', - 'INVALID_DATA': 'awaiting_data', - 'RETRY_LIMIT_REACHED': 'awaiting_data', - 'AWAITING_DATA': 'awaiting_data', - 'DATA_PROVIDED': 'data_provided', - 'PENDING': 'pending', - 'PASSED': 'passed', -} -ADYEN_PAYOUT_FREQUENCIES = { - 'daily': 'DAILY', - 'weekly': 'WEEKLY', - 'biweekly': 'BIWEEKLY_ON_1ST_AND_15TH_AT_MIDNIGHT', - 'monthly': 'MONTHLY', -} - - -class AdyenAccount(models.Model): - _name = 'adyen.account' - _inherit = ['mail.thread', 'adyen.id.mixin', 'adyen.address.mixin'] - _description = 'Adyen for Platforms Account' - _rec_name = 'full_name' - - # Credentials - proxy_token = fields.Char('Proxy Token') - adyen_uuid = fields.Char('Adyen UUID') - account_holder_code = fields.Char('Account Holder Code', default=lambda self: uuid.uuid4().hex) - - company_id = fields.Many2one('res.company', default=lambda self: self.env.company) - shareholder_ids = fields.One2many('adyen.shareholder', 'adyen_account_id', string='Shareholders') - bank_account_ids = fields.One2many('adyen.bank.account', 'adyen_account_id', string='Bank Accounts') - transaction_ids = fields.One2many('adyen.transaction', 'adyen_account_id', string='Transactions') - transactions_count = fields.Integer(compute='_compute_transactions_count') - transaction_payout_ids = fields.One2many('adyen.transaction.payout', 'adyen_account_id') - - is_business = fields.Boolean('Is a business', required=True) - - # Payout - account_code = fields.Char('Account Code') - payout_schedule = fields.Selection([ - ('daily', 'Daily'), - ('weekly', 'Weekly'), - ('biweekly', 'Bi-weekly'), - ('monthly', 'Monthly'), - ], default='biweekly', required=True, string='Payout Schedule') - next_scheduled_payout = fields.Datetime('Next Scheduled Payout', readonly=True) - last_sync_date = fields.Datetime(default=fields.Datetime.now) - - # Contact Info - full_name = fields.Char(compute='_compute_full_name') - email = fields.Char('Email', required=True) - phone_number = fields.Char('Phone Number', required=True) - - # Individual - first_name = fields.Char('First Name') - last_name = fields.Char('Last Name') - date_of_birth = fields.Date('Date of birth') - document_number = fields.Char('ID Number', - help="The type of ID Number required depends on the country:\n" - "US: Social Security Number (9 digits or last 4 digits)\n" - "Canada: Social Insurance Number\nItaly: Codice fiscale\n" - "Australia: Document Number") - document_type = fields.Selection(string='Document Type', selection=[ - ('ID', 'ID'), - ('PASSPORT', 'Passport'), - ('VISA', 'Visa'), - ('DRIVINGLICENSE', 'Driving license'), - ], default='ID') - - # Business - legal_business_name = fields.Char('Legal Business Name') - doing_business_as = fields.Char('Doing Business As') - registration_number = fields.Char('Registration Number') - - # Adyen Account Status - internal use - account_status = fields.Selection(string='Internal Account Status', selection=[ - ('active', 'Active'), - ('inactive', 'Inactive'), - ('suspended', 'Suspended'), - ('closed', 'Closed'), - ], default='inactive', readonly=True) - payout_allowed = fields.Boolean(readonly=True) - - # Status for UX - state = fields.Selection([ - ('pending', 'Pending Validation'), # Odoo Validation - ('awaiting_data', 'Data To Provide'), - ('validation', 'Data Validation'), # KYC Validation from Adyen - ('validated', 'Validated'), - ], compute='_compute_state', string='Account State') - - # KYC - adyen_kyc_ids = fields.One2many('adyen.kyc', 'adyen_account_id', string='KYC Checks', readonly=True) - kyc_tier = fields.Integer(string='KYC Tier', default=0, readonly=True) - kyc_status_message = fields.Html(compute='_compute_kyc_status') - - _sql_constraints = [ - ('adyen_uuid_uniq', 'UNIQUE(adyen_uuid)', 'Adyen UUID should be unique'), - ] - - def default_get(self, fields): - res = super().default_get(fields) - company_fields = { - 'country_id': 'country_id', - 'state_id': 'state_id', - 'city': 'city', - 'zip': 'zip', - 'street': 'street', - 'email': 'email', - 'phone_number': 'phone', - } - - if self.env.company.partner_id.is_company: - company_fields.update({ - 'registration_number': 'vat', - 'legal_business_name': 'name', - 'doing_business_as': 'name', - }) - if 'is_business' in fields: - res['is_business'] = True - - field_keys = company_fields.keys() & set(fields) - for field_name in field_keys: - res[field_name] = self.env.company[company_fields[field_name]] - - if not self.env.company.partner_id.is_company and {'last_name', 'first_name'} & set(fields): - name = self.env.company.partner_id.name.split() - res['last_name'] = name[-1] - res['first_name'] = ' '.join(name[:-1]) - - return res - - @api.depends('transaction_ids') - def _compute_transactions_count(self): - for adyen_account_id in self: - adyen_account_id.transactions_count = len(adyen_account_id.transaction_ids) - - @api.depends('first_name', 'last_name', 'legal_business_name') - def _compute_full_name(self): - for adyen_account_id in self: - if adyen_account_id.is_business: - adyen_account_id.full_name = adyen_account_id.legal_business_name - else: - adyen_account_id.full_name = "%s %s" % (adyen_account_id.first_name, adyen_account_id.last_name) - - @api.depends('kyc_tier', 'adyen_kyc_ids', 'account_status') - def _compute_state(self): - for account in self: - if account.account_status in ['inactive', 'suspended'] and account.kyc_tier == 0: - account.state = 'pending' - else: - if any(k.status == 'awaiting_data' for k in account.adyen_kyc_ids): - account.state = 'awaiting_data' - elif any(k.status == 'pending' for k in account.adyen_kyc_ids): - account.state = 'validation' - else: - account.state = 'validated' - - @api.depends_context('lang') - @api.depends('adyen_kyc_ids') - def _compute_kyc_status(self): - self.kyc_status_message = False - doc_types = dict(self.env['adyen.kyc']._fields['verification_type']._description_selection(self.env)) - for account in self.filtered('adyen_kyc_ids.status_message'): - checks = {} - for kyc in account.adyen_kyc_ids.filtered('status_message'): - doc_type = doc_types.get(kyc.verification_type, _('Other')) - checks.setdefault(doc_type, []).append({ - 'document': kyc.document, - 'message': kyc.status_message, - }) - - account.kyc_status_message = self.env['ir.qweb']._render('adyen_platforms.kyc_status_message', { - 'checks': checks - }) - - @api.model - def create(self, values): - adyen_account_id = super().create(values) - - # Create account on odoo.com, proxy and Adyen - create_data = self._format_data(values) - create_data['payoutSchedule'] = ADYEN_PAYOUT_FREQUENCIES.get(values.get('payout_schedule', 'biweekly'), 'BIWEEKLY_ON_1ST_AND_15TH_AT_MIDNIGHT'), - response = self._adyen_rpc('v1/create_account_holder', create_data) - - adyen_account_id.with_context(update_from_adyen=True).write({ - 'account_code': response['adyen_response']['accountCode'], - 'adyen_uuid': response['adyen_uuid'], - 'proxy_token': response['proxy_token'], - }) - self.env.company.adyen_account_id = adyen_account_id.id - - return adyen_account_id - - def write(self, vals): - adyen_fields = { - 'country_id', 'state_id', 'city', 'zip', 'street', 'house_number_or_name', 'email', 'phone_number', - 'is_business', 'legal_business_name', 'doing_business_as', 'registration_number', 'first_name', - 'last_name', 'date_of_birth', 'document_number', 'document_type', - } - res = super().write(vals) - if vals.keys() & adyen_fields and not self.env.context.get('update_from_adyen'): - self._adyen_rpc('v1/update_account_holder', self._format_data(vals)) - - if 'payout_schedule' in vals: - self._update_payout_schedule(vals['payout_schedule']) - - return res - - def unlink(self): - self.check_access_rights('unlink') - - for adyen_account_id in self: - adyen_account_id._adyen_rpc('v1/close_account_holder', { - 'accountHolderCode': adyen_account_id.account_holder_code, - }) - return super().unlink() - - def _update_payout_schedule(self, payout_schedule): - self.ensure_one() - - self._adyen_rpc('v1/update_payout_schedule', { - 'accountCode': self.account_code, - 'metadata': { - 'adyen_uuid': self.adyen_uuid, - }, - 'payoutSchedule': { - 'action': 'UPDATE', - 'schedule': ADYEN_PAYOUT_FREQUENCIES.get(payout_schedule), - } - }) - - @api.model - def action_create_redirect(self): - ''' - Accessing the FormView to create an Adyen account needs to be done through this action. - The action will redirect the user to accounts.odoo.com to link an Odoo user_id to the Adyen - account. After logging in on odoo.com the user will be redirected to his DB with a token in - the URL. This token is then needed to create the Adyen account. - ''' - if self.env.company.adyen_account_id: - # An account already exists, show it - return { - 'name': _('Adyen Account'), - 'view_mode': 'form', - 'res_model': 'adyen.account', - 'res_id': self.env.company.adyen_account_id.id, - 'type': 'ir.actions.act_window', - } - return_url = url_join(self.env.company.get_base_url(), 'adyen_platforms/create_account') - onboarding_url = self.env['ir.config_parameter'].sudo().get_param('adyen_platforms.onboarding_url') - return { - 'type': 'ir.actions.act_url', - 'url': url_join(onboarding_url, 'get_creation_token?return_url=%s' % return_url), - } - - def action_show_transactions(self): - action = self.env['ir.actions.actions']._for_xml_id('adyen_platforms.adyen_transaction_action') - action['domain'] = expression.AND([[('adyen_account_id', '=', self.id)], literal_eval(action.get('domain', '[]'))]) - return action - - def _upload_photo_id(self, document_type, content, filename): - test_mode = self.env['ir.config_parameter'].sudo().get_param('adyen_platforms.test_mode') - self._adyen_rpc('v1/upload_document', { - 'documentDetail': { - 'accountHolderCode': self.account_holder_code, - 'documentType': document_type, - 'filename': filename, - 'description': 'PASSED' if test_mode else '', - }, - 'documentContent': content.decode(), - }) - - def _format_data(self, values): - fields = values.keys() - data = { - 'accountHolderCode': values.get('account_holder_code') or self.account_holder_code, - } - holder_details = {} - - # *ALL* the address fields are required if one of them changes - address_fields = {'country_id', 'state_id', 'city', 'zip', 'street', 'house_number_or_name'} - if address_fields & fields: - country_id = self.env['res.country'].browse(values.get('country_id')) if values.get('country_id') else self.country_id - state_id = self.env['res.country.state'].browse(values.get('state_id')) if values.get('state_id') else self.state_id - holder_details['address'] = { - 'country': country_id.code, - 'stateOrProvince': state_id.code or None, - 'city': values.get('city') or self.city, - 'postalCode': values.get('zip') or self.zip, - 'street': values.get('street') or self.street, - 'houseNumberOrName': values.get('house_number_or_name') or self.house_number_or_name, - } - - if 'email' in values: - holder_details['email'] = values['email'] - - if 'phone_number' in values: - holder_details['fullPhoneNumber'] = values['phone_number'] - - if 'is_business' in values: - data['legalEntity'] = 'Business' if values['is_business'] else 'Individual' - - if (values.get('is_business') or self.is_business) and {'legal_business_name', 'doing_business_as', 'registration_number'} & fields: - business_details = holder_details['business_details'] = {} - for source, dest in [ - ('legal_business_name', 'legalBusinessName'), - ('doing_business_as', 'doingBusinessAs'), - ('registration_number', 'registrationNumber'), - ]: - if source in values: - business_details[dest] = values[source] - - elif {'first_name', 'last_name', 'date_of_birth', 'document_number', 'document_type'} & fields: - holder_details['individualDetails'] = {} - - if {'first_name', 'last_name'} & fields: - holder_details['individualDetails']['name'] = { - 'firstName': values.get('first_name') or self.first_name, - 'lastName': values.get('last_name') or self.last_name - } - - if 'date_of_birth' in fields: - holder_details['individualDetails'].setdefault('personalData', {})['dateOfBirth'] = str(values['date_of_birth']) - - document_number = values.get('document_number') or self.document_number - if self.document_number and 'document_number' in fields: - holder_details['individualDetails'].setdefault('personalData', {})['documentData'] = [{ - 'number': document_number, - 'type': values.get('document_type') or self.document_type, - }] - - if holder_details: - data['accountHolderDetails'] = holder_details - - return data - - def _adyen_rpc(self, operation, adyen_data=None): - adyen_data = adyen_data or {} - if operation == 'v1/create_account_holder': - url = self.env['ir.config_parameter'].sudo().get_param('adyen_platforms.onboarding_url') - params = { - 'creation_token': request.session.get('adyen_creation_token'), - 'base_url': self.get_base_url(), - 'adyen_data': adyen_data, - } - auth = None - else: - url = self.env['ir.config_parameter'].sudo().get_param('adyen_platforms.proxy_url') - params = { - 'adyen_uuid': self.adyen_uuid, - 'adyen_data': adyen_data, - } - auth = AdyenProxyAuth(self) - - payload = { - 'jsonrpc': '2.0', - 'params': params, - } - try: - req = requests.post(url_join(url, operation), json=payload, auth=auth, timeout=TIMEOUT) - req.raise_for_status() - except requests.exceptions.Timeout: - raise UserError(_('A timeout occurred while trying to reach the Adyen proxy.')) - except Exception: - raise UserError(_('The Adyen proxy is not reachable, please try again later.')) - response = req.json() - - if 'error' in response: - name = response['error']['data'].get('name').rpartition('.')[-1] - if name == 'ValidationError': - raise ValidationError(response['error']['data'].get('arguments')[0]) - else: - _logger.warning('Proxy error: %s', response['error']) - raise UserError( - _("We had troubles reaching Adyen, please retry later or contact the support if the problem persists")) - return response.get('result') - - @api.model - def _sync_adyen_cron(self): - self.env['adyen.account'].search([]).sync_transactions() - - def _handle_notification(self, notification_data): - self.ensure_one() - - content = notification_data.get('content', {}) - event_type = notification_data.get('eventType') - - if event_type == 'ODOO_ACCOUNT_STATUS_CHANGE': - self._handle_odoo_account_status_change(content) - elif event_type == 'ACCOUNT_HOLDER_STATUS_CHANGE': - self._handle_account_holder_status_change_notification(content) - elif event_type == 'ACCOUNT_HOLDER_VERIFICATION': - self._handle_account_holder_verification_notification(content) - elif event_type == 'ACCOUNT_UPDATED': - self._handle_account_updated_notification(content) - elif event_type == 'ACCOUNT_HOLDER_PAYOUT': - self._handle_account_holder_payout(content) - else: - _logger.warning(_("Unknown eventType received: %s", event_type)) - - def _handle_odoo_account_status_change(self, content): - self.ensure_one() - - new_status = content.get('newStatus') - if new_status == 'active' and self.account_status in ['suspended', 'inactive']: - self._adyen_rpc('v1/unsuspend_account_holder', { - 'accountHolderCode': self.account_holder_code, - }) - elif new_status == 'rejected': - self._adyen_rpc('v1/close_account_holder', { - 'accountHolderCode': self.account_holder_code, - }) - - def _handle_account_holder_status_change_notification(self, content): - self.ensure_one() - - # Account Status - new_status = ADYEN_STATUS_MAP.get(content.get('newStatus', {}).get('status')) - if new_status and new_status != self.account_status: - self.account_status = new_status - - # Tier - tier = content.get('newStatus', {}).get('processingState', {}).get('tierNumber', None) - if isinstance(tier, int) and tier != self.kyc_tier: - self.kyc_tier = tier - - # Payout - payout_allowed = content.get('newStatus', {}).get('payoutState', {}).get('allowPayout', None) - if payout_allowed is not None: - self.payout_allowed = payout_allowed == 'true' - - # Events - events = content.get('newStatus', {}).get('events') - if events: - reasons = [] - for event in events: - account_event = event.get('AccountEvent', {}).get('reason') - if account_event: - reasons.append(account_event) - - status_message = self.env['ir.qweb']._render('adyen_platforms.status_message', { - 'message': content.get('reason'), - 'reasons': reasons, - }) - self.sudo().message_post(body=status_message, subtype_xmlid="mail.mt_comment") - - def _handle_account_holder_verification_notification(self, content): - self.ensure_one() - - status = ADYEN_VALIDATION_MAP.get(content.get('verificationStatus')) - document = '_'.join(content.get('verificationType', '').lower().split('_')[:-1]) # bank_account, identity, passport, etc. - status_message = content.get('statusSummary', {}).get('kycCheckDescription') - - bank_uuid = content.get('bankAccountUUID') - shareholder_uuid = content.get('shareholderCode') - - kyc = self.adyen_kyc_ids.filtered(lambda k: k.verification_type == document) - if bank_uuid: - kyc = kyc.filtered(lambda k: k.bank_account_id.bank_account_uuid == bank_uuid or not k.bank_account_id) - elif shareholder_uuid: - kyc = kyc.filtered(lambda k: k.shareholder_id.shareholder_uuid == shareholder_uuid or not k.shareholder_id) - else: - kyc = kyc.filtered(lambda k: not k.shareholder_id and not k.bank_account_id) - - if not kyc: - additional_data = {} - if document == 'bank_account' and bank_uuid: - bank_account_id = self.env['adyen.bank.account'].sudo().search([('bank_account_uuid', '=', bank_uuid)]) - additional_data['bank_account_id'] = bank_account_id.id - if shareholder_uuid: - shareholder_id = self.env['adyen.shareholder'].sudo().search([('shareholder_uuid', '=', shareholder_uuid)]) - additional_data['shareholder_id'] = shareholder_id.id - - self.env['adyen.kyc'].sudo().create({ - 'verification_type': document, - 'adyen_account_id': self.id, - 'status': status, - 'status_message': status_message, - 'last_update': fields.Datetime.now(), - **additional_data - }) - else: - if bank_uuid and not kyc.bank_account_id: - bank_account_id = self.env['adyen.bank.account'].sudo().search([('bank_account_uuid', '=', bank_uuid)]) - kyc.bank_account_id = bank_account_id.id - if shareholder_uuid and not kyc.shareholder_id: - shareholder_id = self.env['adyen.shareholder'].sudo().search([('shareholder_uuid', '=', shareholder_uuid)]) - kyc.shareholder_id = shareholder_id.id - - if status != kyc.status: - kyc.write({ - 'status': status, - 'status_message': status_message, - 'last_update': fields.Datetime.now(), - }) - - def _handle_account_updated_notification(self, content): - self.ensure_one() - scheduled_date = content.get('payoutSchedule', {}).get('nextScheduledPayout') - if scheduled_date: - self.next_scheduled_payout = parse(scheduled_date).astimezone(UTC).replace(tzinfo=None) - - def _handle_account_holder_payout(self, content): - self.ensure_one() - status = content.get('status', {}).get('statusCode') - - if status == 'Failed': - status_message = _('Failed payout: %s', content['status']['message']['text']) - self.sudo().message_post(body=status_message, subtype_xmlid="mail.mt_comment") - - def sync_transactions(self): - updated_transactions = self.env['adyen.transaction'] - for account in self: - page = 1 - next_page = True - max_create_date = False - - while next_page: - transactions, next_page = account._fetch_transactions(page) - page += 1 - - for transaction in transactions: - create_date = parse(transaction.get('creationDate')).astimezone(UTC).replace(tzinfo=None) - if not max_create_date: - max_create_date = create_date - if create_date <= account.last_sync_date: - next_page = False - break - - status = transaction.get('transactionStatus') - if status in ['Payout', 'PayoutReversed']: - reference = transaction.get('pspReference') or transaction.get('disputePspReference') - tx_sudo = account.transaction_payout_ids.sudo().filtered(lambda t: t.reference == reference) - if not tx_sudo: - self.env['adyen.transaction.payout'].sudo()._create_missing_payout(account.id, transaction) - else: - tx_sudo.status = status - else: - if status in ['Chargeback', 'ChargebackReceived']: - transaction['pspReference'] = transaction.get('disputePspReference') - tx_sudo, _reference, _capture_reference = account.transaction_ids.sudo()._get_tx_from_notification(transaction) - if not tx_sudo: - tx_sudo = self.env['adyen.transaction'].sudo()._create_missing_tx(account.id, transaction) - tx_sudo._update_status(status, create_date) - updated_transactions |= tx_sudo - account.last_sync_date = max_create_date - updated_transactions.sudo()._post_transaction_sync() - - def _fetch_transactions(self, page=1): - self.ensure_one() - response = self._adyen_rpc('v1/get_transactions', { - 'accountHolderCode': self.account_holder_code, - 'transactionListsPerAccount': [{ - 'accountCode': self.account_code, - 'page': page, - }] - }) - transaction_list = response['accountTransactionLists'][0] - return transaction_list['transactions'], transaction_list['hasNextPage'] - - -class AdyenAccountBalance(models.Model): - _name = 'adyen.account.balance' - _description = 'Adyen Account Balance' - - adyen_account_id = fields.Many2one('adyen.account', required=True, ondelete='cascade') - currency_id = fields.Many2one('res.currency') - balance = fields.Float(default=0.0) - on_hold = fields.Float(default=0.0) - pending = fields.Float(default=0.0) - - @api.model - def get_account_balance(self): - if not self.user_has_groups('base.group_erp_manager'): - raise AccessError(_("You can't access account balance.")) - - if not self.env.company.adyen_account_id: - return {} - - balance_fields = {'balance': 'balance', 'onHoldBalance': 'on_hold', 'pendingBalance': 'pending'} - balances = self.env['adyen.account.balance'].sudo().search([ - ('adyen_account_id', '=', self.env.company.adyen_account_id.id) - ]) - - delta = fields.Datetime.now() - timedelta(hours=1) - if not balances or any(b.write_date <= delta for b in balances): - response = {} - try: - response = self.env.company.adyen_account_id._adyen_rpc('v1/account_holder_balance', { - 'accountHolderCode': self.env.company.adyen_account_id.account_holder_code, - }) - except UserError as e: - _logger.warning(_('Cannot update account balance, showing previous values: %s', e)) - - balances.write({ - f: 0 for f in balance_fields.values() - }) - for total_balance, adyen_balances in response.get('totalBalance', {}).items(): - for balance in adyen_balances: - currency_id = self.env['res.currency'].search([('name', '=', balance.get('currency'))]) - bal = balances.filtered(lambda b: b.currency_id == currency_id) - if not bal: - bal = self.env['adyen.account.balance'].sudo().create({ - 'adyen_account_id': self.env.company.adyen_account_id.id, - 'currency_id': currency_id.id, - }) - balances |= bal - bal[balance_fields.get(total_balance)] = to_major_currency(balance.get('value', 0), currency_id.decimal_places) - - warning_delta = fields.Datetime.now() - timedelta(hours=2) - return [{ - 'currency': b.currency_id.name, - 'balance': format_amount(self.env, b.balance, b.currency_id), - 'payout_date': format_datetime(self.env, self.env.company.adyen_account_id.next_scheduled_payout, dt_format='short'), - 'last_update_warning': b.write_date <= warning_delta, - 'last_update': format_datetime(self.env, b.write_date), - } for b in balances] diff --git a/addons/adyen_platforms/models/adyen_bank_account.py b/addons/adyen_platforms/models/adyen_bank_account.py deleted file mode 100644 index 31a90c26274..00000000000 --- a/addons/adyen_platforms/models/adyen_bank_account.py +++ /dev/null @@ -1,159 +0,0 @@ -# Part of Odoo. See LICENSE file for full copyright and licensing details. - -import base64 -import uuid - -from odoo import _, api, fields, models -from odoo.exceptions import ValidationError -from odoo.tools.mimetypes import guess_mimetype - -from odoo.addons.adyen_platforms.models.adyen_kyc import ADYEN_KYC_STATUS -from odoo.addons.adyen_platforms.models.adyen_mixins import ADYEN_AVAILABLE_COUNTRIES - - -class AdyenBankAccount(models.Model): - _name = 'adyen.bank.account' - _description = 'Adyen for Platforms Bank Account' - - adyen_account_id = fields.Many2one('adyen.account', ondelete='cascade') - bank_account_reference = fields.Char('Reference', default=lambda self: uuid.uuid4().hex) - bank_account_uuid = fields.Char('UUID') # Given by Adyen - owner_name = fields.Char('Owner Name', required=True) - country_id = fields.Many2one('res.country', string='Country', domain=[('code', 'in', ADYEN_AVAILABLE_COUNTRIES)], required=True) - country_code = fields.Char(related='country_id.code') - currency_id = fields.Many2one('res.currency', string='Currency', required=True) - currency_name = fields.Char(related='currency_id.name', string='Currency Name') - iban = fields.Char('IBAN') - account_number = fields.Char('Account Number') - branch_code = fields.Char('Branch Code') - bank_city = fields.Char('Bank City') - bank_code = fields.Char('Bank Code') - bank_name = fields.Char('Bank Name') - account_type = fields.Selection(string='Account Type', selection=[ - ('checking', 'Checking'), - ('savings', 'Savings'), - ]) - owner_country_id = fields.Many2one('res.country', string='Owner Country') - owner_state_id = fields.Many2one('res.country.state', 'Owner State', domain="[('country_id', '=?', owner_country_id)]") - owner_street = fields.Char('Owner Street') - owner_city = fields.Char('Owner City') - owner_zip = fields.Char('Owner ZIP') - owner_house_number_or_name = fields.Char('Owner House Number or Name') - - bank_statement = fields.Binary('Bank Statement', help="You need to provide a bank statement to allow payouts. \ - The file must be a bank statement, a screenshot of your online banking environment, a letter from the bank or a cheque and must contain \ - the logo of the bank or it's name in a unique font, the bank account details, the name of the account holder.\ - Allowed formats: jpg, pdf, png. Maximum allowed size: 10MB.") - bank_statement_filename = fields.Char() - - # KYC - adyen_kyc_ids = fields.One2many('adyen.kyc', 'bank_account_id') - kyc_status = fields.Selection(ADYEN_KYC_STATUS, compute='_compute_kyc_status', readonly=True) - kyc_status_message = fields.Char(compute='_compute_kyc_status', readonly=True) - - @api.depends_context('lang') - @api.depends('adyen_kyc_ids') - def _compute_kyc_status(self): - self.kyc_status_message = False - self.kyc_status = False - for bank_account in self.filtered('adyen_kyc_ids'): - kyc = bank_account.adyen_kyc_ids._sort_by_status() - bank_account.kyc_status = kyc[0].status - - @api.model - def create(self, values): - adyen_bank_account_id = super().create(values) - adyen_account_id = self.env['adyen.account'].browse(values.get('adyen_account_id')) - response = adyen_account_id._adyen_rpc('v1/update_account_holder', self._format_data(values)) - bank_accounts = response['accountHolderDetails']['bankAccountDetails'] - - created_bank_account = next(bank_account for bank_account in bank_accounts if bank_account['bankAccountReference'] == adyen_bank_account_id.bank_account_reference) - adyen_bank_account_id.with_context(update_from_adyen=True).write({ - 'bank_account_uuid': created_bank_account['bankAccountUUID'], - }) - return adyen_bank_account_id - - def write(self, vals): - res = super().write(vals) - - if not self.env.context.get('update_from_adyen'): - self.adyen_account_id._adyen_rpc('v1/update_account_holder', self._format_data(vals)) - if 'bank_statement' in vals: - self._upload_bank_statement(vals['bank_statement'], vals['bank_statement_filename']) - return res - - def unlink(self): - self.check_access_rights('unlink') - - for bank_account_id in self: - bank_account_id.adyen_account_id._adyen_rpc('v1/delete_bank_accounts', { - 'accountHolderCode': bank_account_id.adyen_account_id.account_holder_code, - 'bankAccountUUIDs': [bank_account_id.bank_account_uuid], - }) - return super().unlink() - - def name_get(self): - res = [] - for bank_account in self: - name = f'{bank_account.owner_name} - f{bank_account.iban or bank_account.account_number}' - res.append((bank_account.id, name)) - return res - - def _format_data(self, values=None): - if values is None: - values = {} - adyen_account_id = self.env['adyen.account'].browse(values.get('adyen_account_id')) if values.get('adyen_account_id') else self.adyen_account_id - country_id = self.env['res.country'].browse(values.get('country_id')) if values.get('country_id') else self.country_id - currency_id = self.env['res.currency'].browse(values.get('currency_id')) if values.get('currency_id') else self.currency_id - owner_country_id = self.env['res.country'].browse(values.get('owner_country_id')) if values.get('owner_country_id') else self.owner_country_id - owner_state_id = self.env['res.country.state'].browse(values.get('owner_state_id')) if values.get('owner_state_id') else self.owner_state_id - return { - 'accountHolderCode': adyen_account_id.account_holder_code, - 'accountHolderDetails': { - 'bankAccountDetails': [{ - 'accountNumber': values.get('account_number') or self.account_number or None, - 'accountType': values.get('account_type') or self.account_type or None, - 'bankAccountReference': values.get('bank_account_reference') or self.bank_account_reference, - 'bankAccountUUID': values.get('bank_account_uuid') or self.bank_account_uuid or None, - 'bankCity': values.get('bank_city') or self.bank_city or None, - 'bankCode': values.get('bank_code') or self.bank_code or None, - 'bankName': values.get('bank_name') or self.bank_name or None, - 'branchCode': values.get('branch_code') or self.branch_code or None, - 'countryCode': country_id.code, - 'currencyCode': currency_id.name, - 'iban': values.get('iban') or self.iban or None, - 'ownerCity': values.get('owner_city') or self.owner_city or None, - 'ownerCountryCode': owner_country_id.code or None, - 'ownerHouseNumberOrName': values.get('owner_house_number_or_name') or self.owner_house_number_or_name or None, - 'ownerName': values.get('owner_name') or self.owner_name, - 'ownerPostalCode': values.get('owner_zip') or self.owner_zip or None, - 'ownerState': owner_state_id.code or None, - 'ownerStreet': values.get('owner_street') or self.owner_street or None, - }], - } - } - - def _upload_bank_statement(self, content, filename): - content_encoded = content.encode('utf8') - mimetype = guess_mimetype(base64.b64decode(content_encoded)) - file_size = len(content_encoded) - - # Document requirements: https://docs.adyen.com/platforms/verification-checks/bank-account-check#requirements - if mimetype not in ['image/jpeg', 'image/png', 'application/pdf']: - raise ValidationError(_('Allowed file formats for bank statements are jpeg, jpg, pdf or png. Received %r instead.', mimetype)) - if file_size < (100 * 1024) or (file_size < 1024 and mimetype == 'application/pdf'): - raise ValidationError(_('Minimum allowed size for bank statements: 1 KB for PDF, 100 KB for other formats.')) - if file_size > (4 * 1024 * 1024): - raise ValidationError(_('Maximum allowed size for bank statements: 4MB.')) - - test_mode = self.env['ir.config_parameter'].sudo().get_param('adyen_platforms.test_mode') - self.adyen_account_id._adyen_rpc('v1/upload_document', { - 'documentDetail': { - 'accountHolderCode': self.adyen_account_id.account_holder_code, - 'bankAccountUUID': self.bank_account_uuid, - 'documentType': 'BANK_STATEMENT', - 'filename': filename, - 'description': 'PASSED' if test_mode else '', - }, - 'documentContent': content, - }) diff --git a/addons/adyen_platforms/models/adyen_kyc.py b/addons/adyen_platforms/models/adyen_kyc.py deleted file mode 100644 index 4bcc4072d4f..00000000000 --- a/addons/adyen_platforms/models/adyen_kyc.py +++ /dev/null @@ -1,54 +0,0 @@ -# Part of Odoo. See LICENSE file for full copyright and licensing details. - -from odoo import api, fields, models - - -ADYEN_KYC_STATUS = [ - ('awaiting_data', 'Data To Provide'), - ('pending', 'Waiting For Validation'), - ('data_provided', 'Data Provided'), - ('passed', 'Confirmed'), - ('failed', 'Failed'), -] - -class AdyenKYC(models.Model): - _name = 'adyen.kyc' - _description = 'Adyen KYC checks' - - status_message = fields.Char() - status = fields.Selection(string='KYC Status', selection=[ - ('awaiting_data', 'Data To Provide'), - ('pending', 'Waiting For Validation'), - ('data_provided', 'Data Provided'), - ('passed', 'Confirmed'), - ('failed', 'Failed'), - ], required=True, default='pending') - - adyen_account_id = fields.Many2one('adyen.account', required=True, ondelete='cascade') - bank_account_id = fields.Many2one( - 'adyen.bank.account', domain="[('adyen_account_id', '=', adyen_account_id)]", ondelete='cascade') - shareholder_id = fields.Many2one( - 'adyen.shareholder', domain="[('adyen_account_id', '=', adyen_account_id)]", ondelete='cascade') - document = fields.Char(compute='_compute_document') - - verification_type = fields.Selection([ - ('company', 'Company'), - ('identity', 'Identity'), - ('passport', 'Passport'), - ('bank_account', 'Bank Account'), - ('nonprofit', 'Nonprofit'), - ('card', 'Card'), - ], string='KYC Document') - - last_update = fields.Datetime(string="Last Update") - - def _sort_by_status(self): - order = ['failed', 'awaiting_data', 'pending', 'data_provided', 'passed'] - kyc_sorted = sorted(self, key=lambda k: order.index(k.status)) - return kyc_sorted - - @api.depends('bank_account_id', 'shareholder_id') - def _compute_document(self): - self.document = False - for kyc in self.filtered(lambda k: k.bank_account_id or k.shareholder_id): - kyc.document = kyc.bank_account_id.display_name or kyc.shareholder_id.display_name diff --git a/addons/adyen_platforms/models/adyen_mixins.py b/addons/adyen_platforms/models/adyen_mixins.py deleted file mode 100644 index 71c3a0a8c44..00000000000 --- a/addons/adyen_platforms/models/adyen_mixins.py +++ /dev/null @@ -1,81 +0,0 @@ -# Part of Odoo. See LICENSE file for full copyright and licensing details. - -import base64 - -from odoo import _, api, fields, models -from odoo.exceptions import ValidationError -from odoo.tools.mimetypes import guess_mimetype - -ADYEN_AVAILABLE_COUNTRIES = [ - 'US', 'AT', 'AU', 'BE', 'CA', 'CH', 'CZ', 'DE', 'ES', 'FI', 'FR', 'GB', 'GR', 'HR', 'IE', 'IT', - 'LT', 'LU', 'NL', 'PL', 'PT' -] - - -class AdyenAddressMixin(models.AbstractModel): - _name = 'adyen.address.mixin' - _description = 'Adyen for Platforms Address Mixin' - - country_id = fields.Many2one('res.country', string='Country', domain=[('code', 'in', ADYEN_AVAILABLE_COUNTRIES)], required=True) - country_code = fields.Char(related='country_id.code') - state_id = fields.Many2one('res.country.state', string='State', domain="[('country_id', '=?', country_id)]") - state_code = fields.Char(related='state_id.code') - city = fields.Char('City', required=True) - zip = fields.Char('ZIP', required=True) - street = fields.Char('Street', required=True) - house_number_or_name = fields.Char('House Number Or Name', required=True) - - -class AdyenIDMixin(models.AbstractModel): - _name = 'adyen.id.mixin' - _description = 'Adyen for Platforms ID Mixin' - - id_type = fields.Selection(string='Photo ID type', selection=[ - ('PASSPORT', 'Passport'), - ('ID_CARD', 'ID Card'), - ('DRIVING_LICENSE', 'Driving License'), - ]) - id_front = fields.Binary('Photo ID Front', help="Allowed formats: jpg, pdf, png. Maximum allowed size: 4MB.") - id_front_filename = fields.Char() - id_back = fields.Binary('Photo ID Back', help="Allowed formats: jpg, pdf, png. Maximum allowed size: 4MB.") - id_back_filename = fields.Char() - - def write(self, vals): - res = super().write(vals) - - # Check file formats - if vals.get('id_front'): - self._check_file_requirements(vals.get('id_front')) - if vals.get('id_back'): - self._check_file_requirements(vals.get('id_back')) - - for adyen_account in self: - if vals.get('id_front'): - document_type = adyen_account.id_type - if adyen_account.id_type in ['ID_CARD', 'DRIVING_LICENSE']: - document_type += '_FRONT' - adyen_account._upload_photo_id(document_type, adyen_account.id_front, adyen_account.id_front_filename) - if vals.get('id_back') and adyen_account.id_type in ['ID_CARD', 'DRIVING_LICENSE']: - document_type = adyen_account.id_type + '_BACK' - adyen_account._upload_photo_id(document_type, adyen_account.id_back, adyen_account.id_back_filename) - return res - - @api.model - def _check_file_requirements(self, content): - content_encoded = content.encode('utf8') - mimetype = guess_mimetype(base64.b64decode(content_encoded)) - file_size = len(content_encoded) - - # Document requirements: https://docs.adyen.com/platforms/verification-checks/photo-id-check#requirements - if mimetype not in ['image/jpeg', 'image/png', 'application/pdf']: - raise ValidationError(_('Allowed file formats for photo IDs are jpeg, jpg, pdf or png')) - if file_size < (100 * 1024) or (file_size < 1024 and mimetype == 'application/pdf'): - raise ValidationError(_('Minimum allowed size for photo ID: 1 KB for PDF, 100 KB for other formats.')) - if file_size > (4 * 1024 * 1024): - raise ValidationError(_('Maximum allowed size for photo ID: 4 MB.')) - - def _upload_photo_id(self, document_type, content, filename): - # The request to be sent to Adyen will be different for Individuals, - # Shareholders, etc. This method should be implemented by the models - # inheriting this mixin - raise NotImplementedError() diff --git a/addons/adyen_platforms/models/adyen_shareholder.py b/addons/adyen_platforms/models/adyen_shareholder.py deleted file mode 100644 index 6649d3c5166..00000000000 --- a/addons/adyen_platforms/models/adyen_shareholder.py +++ /dev/null @@ -1,129 +0,0 @@ -# Part of Odoo. See LICENSE file for full copyright and licensing details. - -import uuid - -from odoo import api, fields, models - -from odoo.addons.adyen_platforms.models.adyen_kyc import ADYEN_KYC_STATUS - - -class AdyenShareholder(models.Model): - _name = 'adyen.shareholder' - _inherit = ['adyen.id.mixin', 'adyen.address.mixin'] - _description = 'Adyen for Platforms Shareholder' - _rec_name = 'full_name' - - adyen_account_id = fields.Many2one('adyen.account', ondelete='cascade') - shareholder_reference = fields.Char('Reference', default=lambda self: uuid.uuid4().hex) - shareholder_uuid = fields.Char('UUID') # Given by Adyen - first_name = fields.Char('First Name', required=True) - last_name = fields.Char('Last Name', required=True) - full_name = fields.Char(compute='_compute_full_name') - date_of_birth = fields.Date('Date of birth', required=True) - document_number = fields.Char('ID Number', - help="The type of ID Number required depends on the country:\n" - "US: Social Security Number (9 digits or last 4 digits)\n" - "Canada: Social Insurance Number\nItaly: Codice fiscale\n" - "Australia: Document Number") - - adyen_kyc_ids = fields.One2many('adyen.kyc', 'shareholder_id') - kyc_status = fields.Selection(ADYEN_KYC_STATUS, compute='_compute_kyc_status', readonly=True) - kyc_status_message = fields.Char(compute='_compute_kyc_status', readonly=True) - - @api.depends_context('lang') - @api.depends('adyen_kyc_ids') - def _compute_kyc_status(self): - self.kyc_status_message = False - self.kyc_status = False - for shareholder in self.filtered('adyen_kyc_ids'): - kyc = shareholder.adyen_kyc_ids._sort_by_status() - shareholder.kyc_status = kyc[0].status - - @api.depends('first_name', 'last_name') - def _compute_full_name(self): - for adyen_shareholder_id in self: - adyen_shareholder_id.full_name = f'{adyen_shareholder_id.first_name} {adyen_shareholder_id.last_name}' - - @api.model - def create(self, values): - adyen_shareholder_id = super().create(values) - adyen_account_id = self.env['adyen.account'].browse(values.get('adyen_account_id')) - response = adyen_account_id._adyen_rpc('v1/update_account_holder', self._format_data(values)) - - shareholders = response['accountHolderDetails']['businessDetails']['shareholders'] - created_shareholder = next(shareholder for shareholder in shareholders if shareholder['shareholderReference'] == adyen_shareholder_id.shareholder_reference) - adyen_shareholder_id.with_context(update_from_adyen=True).write({ - 'shareholder_uuid': created_shareholder['shareholderCode'], - }) - return adyen_shareholder_id - - def write(self, vals): - res = super().write(vals) - if not self.env.context.get('update_from_adyen'): - self.adyen_account_id._adyen_rpc('v1/update_account_holder', self._format_data(vals)) - return res - - def unlink(self): - self.check_access_rights('unlink') - - for shareholder_id in self: - shareholder_id.adyen_account_id._adyen_rpc('v1/delete_shareholders', { - 'accountHolderCode': shareholder_id.adyen_account_id.account_holder_code, - 'shareholderCodes': [shareholder_id.shareholder_uuid], - }) - return super().unlink() - - def _upload_photo_id(self, document_type, content, filename): - test_mode = self.env['ir.config_parameter'].sudo().get_param('adyen_platforms.test_mode') - self.adyen_account_id._adyen_rpc('v1/upload_document', { - 'documentDetail': { - 'accountHolderCode': self.adyen_account_id.account_holder_code, - 'shareholderCode': self.shareholder_uuid, - 'documentType': document_type, - 'filename': filename, - 'description': 'PASSED' if test_mode else '', - }, - 'documentContent': content.decode(), - }) - - def _format_data(self, values): - adyen_account_id = self.env['adyen.account'].browse(values.get('adyen_account_id')) if values.get('adyen_account_id') else self.adyen_account_id - country_id = self.env['res.country'].browse(values.get('country_id')) if values.get('country_id') else self.country_id - state_id = self.env['res.country.state'].browse(values.get('owner_state_id')) if values.get('state_id') else self.state_id - data = { - 'accountHolderCode': adyen_account_id.account_holder_code, - 'accountHolderDetails': { - 'businessDetails': { - 'shareholders': [{ - 'shareholderCode': values.get('shareholder_uuid') or self.shareholder_uuid or None, - 'shareholderReference': values.get('shareholder_reference') or self.shareholder_reference, - 'address': { - 'city': values.get('city') or self.city, - 'country': country_id.code, - 'houseNumberOrName': values.get('house_number_or_name') or self.house_number_or_name, - 'postalCode': values.get('zip') or self.zip, - 'stateOrProvince': state_id.code or None, - 'street': values.get('street') or self.street, - }, - 'name': { - 'firstName': values.get('first_name') or self.first_name, - 'lastName': values.get('last_name') or self.last_name, - 'gender': 'UNKNOWN' - }, - 'personalData': { - 'dateOfBirth': str(values.get('date_of_birth') or self.date_of_birth), - } - }] - } - } - } - - # documentData cannot be present in the data if not set - document_number = values.get('document_number') or self.document_number - if document_number: - data['accountHolderDetails']['businessDetails']['shareholders'][0]['personalData']['documentData'] = [{ - 'number': document_number, - 'type': 'ID', - }] - - return data diff --git a/addons/adyen_platforms/models/adyen_transaction.py b/addons/adyen_platforms/models/adyen_transaction.py deleted file mode 100644 index a65c1161b34..00000000000 --- a/addons/adyen_platforms/models/adyen_transaction.py +++ /dev/null @@ -1,315 +0,0 @@ -# Part of Odoo. See LICENSE file for full copyright and licensing details. - -import logging - -from dateutil.parser import parse -from dateutil.relativedelta import relativedelta -from pytz import UTC - -from odoo import _, api, fields, models -from odoo.exceptions import ValidationError -from odoo.osv import expression -from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT - -from odoo.addons.adyen_platforms.util import to_major_currency, to_minor_currency - -_logger = logging.getLogger(__name__) - - -class AdyenTransaction(models.Model): - _name = 'adyen.transaction' - _description = 'Adyen for Platforms Transaction' - _order = 'date desc' - _rec_name = 'reference' - - adyen_account_id = fields.Many2one('adyen.account') - reference = fields.Char('Reference', index=True, required=True) - capture_reference = fields.Char('Capture Reference') - total_amount = fields.Float('Customer Amount') - currency_id = fields.Many2one('res.currency', string='Currency') - merchant_amount = fields.Float('Merchant Amount') - fees = fields.Float('Fees') - fixed_fees = fields.Float('Fixed Fees') - variable_fees = fields.Float('Variable Fees') - fees_currency_id = fields.Many2one('res.currency', default=lambda self: self.env.ref('base.EUR')) - date = fields.Datetime('Date') - description = fields.Char('Description') - signature = fields.Char('Signature') - reason = fields.Char('Failure Reason') - - status = fields.Selection(related='last_status_id.status') - last_status_id = fields.Many2one('adyen.transaction.status', 'Last Status', compute='_compute_last_status_id', store=True, readonly=True) - last_status_update = fields.Datetime(related='last_status_id.date', string='Last Status Update') - status_ids = fields.One2many('adyen.transaction.status', 'adyen_transaction_id', 'Status History') - payment_method = fields.Char('Payment Method') - shopper_country_id = fields.Many2one('res.country') - card_country_id = fields.Many2one('res.country') - commercial_card = fields.Selection([ - ('yes', 'Yes'), - ('no', 'No'), - ('unknown', 'Unknown'), - ], default='unknown') - dispute_reference = fields.Char('Dispute Reference') - - _sql_constraints = [ - ('reference_unique', 'unique(reference, capture_reference)', 'A transaction with the same reference already exists.'), - ] - - @api.depends('status_ids') - def _compute_last_status_id(self): - self.last_status_id = False - for transaction in self.filtered('status_ids'): - transaction.last_status_id = transaction.status_ids.sorted('date')[-1] - - def _get_tx_from_notification(self, notification): - if notification.get('eventCode') in ['CAPTURE', 'REFUND']: - reference = notification.get('originalReference') - capture_reference = notification.get('pspReference') - else: - reference = notification.get('pspReference') - capture_reference = notification.get('capturePspReference') - - domain = [('reference', '=', reference)] - if capture_reference: - domain = expression.AND([domain, [('capture_reference', '=', capture_reference)]]) - - if self: - return self.filtered_domain(domain), reference, capture_reference - return self.env['adyen.transaction'].search(domain), reference, capture_reference - - @api.model - def _handle_notification(self, data): - adyen_uuid = data.get("additionalData", {}).get("metadata.adyen_uuid") or data.get('adyen_uuid') - account = self.env['adyen.account'].sudo().search([('adyen_uuid', '=', adyen_uuid)]) - if not account: - _logger.warning("Received payment notification for non-existing account") - return - - tx_sudo, reference, capture_reference = self.env['adyen.transaction']._get_tx_from_notification(data) - if not tx_sudo: - tx_sudo = self.env['adyen.transaction'].sudo().create({ - 'adyen_account_id': account.id, - 'reference': reference, - 'capture_reference': capture_reference, - 'description': data.get('merchantReference'), - }) - - event_code = data.get('eventCode') - if event_code == "AUTHORISATION": - tx_sudo._handle_authorisation_notification(data) - elif event_code == "FEES_UPDATED": - tx_sudo._handle_fees_updated_notification(data) - elif event_code == "REFUND": - tx_sudo._handle_refund_notification(data) - elif event_code in ["CHARGEBACK", "NOTIFICATION_OF_CHARGEBACK"]: - tx_sudo._handle_chargeback_notification(data) - else: - _logger.warning(_("Unknown eventCode received: %s", event_code)) - - return tx_sudo - - def _handle_authorisation_notification(self, notification_data): - self.ensure_one() - additional_data = notification_data.get('additionalData', {}) - - currency_id = self.env['res.currency'].search([('name', '=', notification_data.get('amount', {}).get('currency'))]) - shopper_country_id = self.env['res.country'].search([('code', '=', additional_data.get('shopperCountry'))]) - commercial_card = additional_data.get('isCardCommercial', 'unknown') - card_country_id = self.env['res.country'].search([('code', '=', additional_data.get('cardIssuingCountry', additional_data.get('issuerCountry')))]) - - self.write({ - 'reference': notification_data.get('pspReference'), - 'total_amount': to_major_currency(notification_data['amount']['value'], currency_id.decimal_places), - 'currency_id': currency_id.id, - 'date': parse(notification_data.get('eventDate')).astimezone(UTC).strftime(DEFAULT_SERVER_DATETIME_FORMAT), - 'description': notification_data.get('merchantReference'), - 'payment_method': notification_data.get('paymentMethod'), - 'shopper_country_id': shopper_country_id.id, - 'card_country_id': card_country_id.id, - 'commercial_card': commercial_card if commercial_card in ('yes', 'no', 'unknown') else 'unknown', - }) - self._trigger_sync() - - def _handle_fees_updated_notification(self, notification_data): - self.ensure_one() - - currency_amount = self.env['res.currency'].search([('name', '=', notification_data.get('totalAmount', {}).get('currency'))]) - currency_fees = self.env['res.currency'].search([('name', '=', notification_data.get('totalFees', {}).get('currency'))]) - self.capture_reference = notification_data.get('captureReference') - self.fees = to_major_currency(notification_data['totalFees']['value'], currency_fees.decimal_places) - self.fixed_fees = to_major_currency(notification_data['fixedFees']['value'], currency_fees.decimal_places) - self.variable_fees = to_major_currency(notification_data['variableFees']['value'], currency_fees.decimal_places) - self.merchant_amount = to_major_currency(notification_data['merchantAmount']['value'], currency_amount.decimal_places) - self.total_amount = to_major_currency(notification_data['totalAmount']['value'], currency_amount.decimal_places) - self.signature = notification_data.get('signature') - - def _handle_refund_notification(self, notification_data): - self.ensure_one() - - currency_id = self.env['res.currency'].search([('name', '=', notification_data.get('amount', {}).get('currency'))]) - self.currency_id = currency_id.id - self.date = parse(notification_data.get('eventDate')).astimezone(UTC).strftime(DEFAULT_SERVER_DATETIME_FORMAT) - reason = notification_data.get('reason') - if reason: - self.reason = reason - - def _handle_chargeback_notification(self, notification_data): - self.ensure_one() - self.dispute_reference = notification_data.get('pspReference') - - self.adyen_account_id.message_post( - body=_('Transaction %s has been CHARGEBACK\'ed: %s', self.description or self.reference, notification_data.get('reason')), - subtype_xmlid="mail.mt_comment" - ) - - def _create_missing_tx(self, account_id, transaction, **kwargs): - currency_id = self.env['res.currency'].search([('name', '=', transaction.get('amount', {}).get('currency'))]) - amount = to_major_currency(transaction['amount']['value'], currency_id.decimal_places) - tx = self.create({ - 'adyen_account_id': account_id, - 'reference': transaction.get('pspReference'), - 'capture_reference': transaction.get('capturePspReference'), - 'merchant_amount': amount, - 'total_amount': amount, - 'currency_id': currency_id.id, - 'date': parse(transaction.get('creationDate')).astimezone(UTC).strftime(DEFAULT_SERVER_DATETIME_FORMAT), - 'description': transaction.get('description'), - **kwargs, - }) - return tx - - def _trigger_sync(self): - sync_cron = self.env.ref('adyen_platforms.adyen_sync_cron', raise_if_not_found=False) - if sync_cron: - sync_cron._trigger(at=fields.Datetime.now() + relativedelta(minutes=5)) - - def _update_status(self, new_status, date): - self.ensure_one() - - if not self.status_ids or self.status_ids[0].date != date: - self.status_ids = [(0, 0, { - 'adyen_transaction_id': self.id, - 'status': new_status, - 'date': date, - })] - - def _post_transaction_sync(self): - """ Hook defined to perform actions on transactions after they were sync'ed """ - return - - def _refund_request(self, amount=None): - self.ensure_one() - - if amount is None: - amount = self.total_amount - - if amount > self.total_amount: - raise ValidationError(_('You cannot refund more than the original amount.')) - - converted_amount = to_minor_currency(amount, self.currency_id.decimal_places) - initial_amount = to_minor_currency(self.total_amount, self.currency_id.decimal_places) - fees_amount = to_minor_currency(self.fees, self.fees_currency_id.decimal_places) - - refund_data = { - 'originalReference': self.reference, - 'modificationAmount': { - 'currency': self.currency_id.name, - 'value': converted_amount, - }, - 'initialAmount': { - 'currency': self.currency_id.name, - 'value': initial_amount, - }, - 'feesAmount': { - 'currency': self.fees_currency_id.name, - 'value': fees_amount, - }, - 'date': str(self.date), - 'reference': 'Refund of %s' % self.description, # TODO generate unique reference - 'payout': self.adyen_account_id.account_code, - 'adyen_uuid': self.adyen_account_id.adyen_uuid, - 'signature': self.signature, - } - res = self.adyen_account_id._adyen_rpc('v1/refund', refund_data) - - refund_tx = self.env['adyen.transaction'].sudo().create({ - 'adyen_account_id': self.adyen_account_id.id, - 'reference': self.reference, - 'capture_reference': res['pspReference'], - 'description': refund_data.get('reference'), - 'currency_id': self.currency_id.id, - 'total_amount': to_major_currency(res['totalAmount']['value'], self.currency_id.decimal_places), - 'fees': to_major_currency(res['totalFees']['value'], self.currency_id.decimal_places), - 'variable_fees': to_major_currency(res['totalFees']['value'], self.currency_id.decimal_places), - 'merchant_amount': to_major_currency(res['merchantAmount']['value'], self.currency_id.decimal_places), - 'date': fields.Datetime.now(), - }) - self._trigger_sync() - - return refund_tx - - def action_refund(self): - for tx in self: - tx._refund_request() - - -class AdyenTransactionStatus(models.Model): - _name = 'adyen.transaction.status' - _description = 'Transaction Status' - _order = 'date desc' - _rec_name = 'status' - - adyen_transaction_id = fields.Many2one('adyen.transaction', required=True, ondelete='cascade') - status = fields.Selection(string='Status', selection=[ - ('unknown', 'Unknown'), - ('PendingCredit', 'Pending Credit'), - ('CreditFailed', 'Credit Failed'), - ('Credited', 'Credited'), - ('Converted', 'Converted'), - ('PendingDebit', 'Pending Debit'), - ('DebitFailed', 'Debit Failed'), - ('Debited', 'Debited'), - ('DebitReversedReceived', 'Debit Reversed Received'), - ('DebitedReversed', 'Debit Reversed'), - ('ChargebackReceived', 'Chargeback Received'), - ('Chargeback', 'Chargeback'), - ('ChargebackReversedReceived', 'Chargeback Reversed Received'), - ('ChargebackReversed', 'Chargeback Reversed'), - ('FundTransfer', 'Fund Transfer'), - ('PendingFundTransfer', 'Pending Fund Transfer'), - ('ManualCorrected', 'Manual Corrected'), - ]) - date = fields.Datetime() - - -class AdyenTransactionPayout(models.Model): - _name = 'adyen.transaction.payout' - _description = 'Payout Transaction' - _order = 'date desc' - - adyen_account_id = fields.Many2one('adyen.account') - date = fields.Datetime() - amount = fields.Float('Amount', required=True) - currency_id = fields.Many2one('res.currency', required=True) - reference = fields.Char('Reference', index=True, required=True) - bank_account_id = fields.Many2one('adyen.bank.account') - status = fields.Selection(string='Type', selection=[ - ('unknown', 'Unknown'), - ('Payout', 'Payout'), - ('PayoutReversed', 'Payout Reversed'), - ], default='unknown') - - def _create_missing_payout(self, account_id, transaction, **kwargs): - currency_id = self.env['res.currency'].search([('name', '=', transaction['amount']['currency'])]) - bank_account_id = self.env['adyen.bank.account'].search([('bank_account_uuid', '=', transaction.get('bankAccountDetail', {}).get('bankAccountUUID'))]) - tx = self.create({ - 'adyen_account_id': account_id, - 'date': parse(transaction.get('creationDate')).astimezone(UTC).strftime(DEFAULT_SERVER_DATETIME_FORMAT), - 'amount': to_major_currency(transaction.get('amount', {}).get('value'), currency_id.decimal_places), - 'currency_id': currency_id.id, - 'reference': transaction.get('pspReference'), - 'bank_account_id': bank_account_id.id, - 'status': transaction.get('transactionStatus'), - **kwargs, - }) - return tx diff --git a/addons/adyen_platforms/models/res_company.py b/addons/adyen_platforms/models/res_company.py deleted file mode 100644 index df1c6fed203..00000000000 --- a/addons/adyen_platforms/models/res_company.py +++ /dev/null @@ -1,9 +0,0 @@ -# Part of Odoo. See LICENSE file for full copyright and licensing details. - -from odoo import fields, models - - -class ResCompany(models.Model): - _inherit = "res.company" - - adyen_account_id = fields.Many2one('adyen.account', string='Adyen Account', readonly=True) diff --git a/addons/adyen_platforms/security/ir.model.access.csv b/addons/adyen_platforms/security/ir.model.access.csv deleted file mode 100644 index cd5955a4712..00000000000 --- a/addons/adyen_platforms/security/ir.model.access.csv +++ /dev/null @@ -1,9 +0,0 @@ -id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink -access_adyen_account_group_erp_manager,adyen.account,model_adyen_account,base.group_erp_manager,1,1,1,1 -access_adyen_shareholder_group_erp_manager,adyen.shareholder,model_adyen_shareholder,base.group_erp_manager,1,1,1,1 -access_adyen_bank_account_group_erp_manager,adyen.bank.account,model_adyen_bank_account,base.group_erp_manager,1,1,1,1 -access_adyen_transaction_group_erp_manager,adyen.transaction,model_adyen_transaction,base.group_erp_manager,1,0,0,0 -access_adyen_kyc_group_erp_manager,adyen.kyc,model_adyen_kyc,base.group_erp_manager,1,0,0,0 -access_adyen_account_balance_group_erp_manager,adyen.account.balance,model_adyen_account_balance,base.group_erp_manager,1,0,0,0 -access_adyen_transaction_status_group_erp_manager,adyen.transaction.status,model_adyen_transaction_status,base.group_erp_manager,1,0,0,0 -access_adyen_transaction_payout_group_erp_manager,adyen.transaction.payout,model_adyen_transaction_payout,base.group_erp_manager,1,0,0,0 diff --git a/addons/adyen_platforms/security/ir_rule.xml b/addons/adyen_platforms/security/ir_rule.xml deleted file mode 100644 index 7b5b8adaf38..00000000000 --- a/addons/adyen_platforms/security/ir_rule.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - Readonly: Closed Accounts - [('account_status', '!=', 'closed')] - - - - - - diff --git a/addons/adyen_platforms/static/src/js/adyen_account_views.js b/addons/adyen_platforms/static/src/js/adyen_account_views.js deleted file mode 100644 index 8921a993590..00000000000 --- a/addons/adyen_platforms/static/src/js/adyen_account_views.js +++ /dev/null @@ -1,63 +0,0 @@ -odoo.define('adyen_platforms.account_views', function (require) { -"use strict"; - -var core = require('web.core'); -var Dialog = require('web.Dialog'); -var FormController = require('web.FormController'); -var FormView = require('web.FormView'); -var viewRegistry = require('web.view_registry'); - -var _t = core._t; -var QWeb = core.qweb; - -var AdyenAccountFormController = FormController.extend({ - _saveRecord: function (recordID, options) { - if(this.model.isNew(this.handle) && this.canBeSaved()) { - var _super = this._super.bind(this, recordID, options); - var buttons = [ - { - text: _t("Create"), - classes: 'btn-primary o_adyen_confirm', - close: true, - disabled: true, - click: function () { - this.close(); - _super(); - }, - }, - { - text: _t("Cancel"), - close: true, - } - ]; - - var dialog = new Dialog(this, { - size: 'extra-large', - buttons: buttons, - title: _t("Confirm your Adyen Account Creation"), - $content: QWeb.render('AdyenAccountCreationConfirmation', { - data: this.model.get(this.handle).data, - }), - }); - - dialog.open().opened(function () { - dialog.$el.on('change', '.opt_in_checkbox', function (ev) { - ev.preventDefault(); - dialog.$footer.find('.o_adyen_confirm')[0].disabled = !ev.currentTarget.checked; - }); - }); - } else if (!this.model.isNew(this.handle)) { - return this._super.apply(this, arguments); - } - }, -}); - -var AdyenAccountFormView = FormView.extend({ - config: _.extend({}, FormView.prototype.config, { - Controller: AdyenAccountFormController, - }), -}); - -viewRegistry.add('adyen_account_form', AdyenAccountFormView); - -}); diff --git a/addons/adyen_platforms/static/src/js/adyen_transactions_dashboard.js b/addons/adyen_platforms/static/src/js/adyen_transactions_dashboard.js deleted file mode 100644 index 4c952801a25..00000000000 --- a/addons/adyen_platforms/static/src/js/adyen_transactions_dashboard.js +++ /dev/null @@ -1,39 +0,0 @@ -odoo.define('adyen_platforms.transactions.dashboard', function (require) { - "use strict"; - - var ListRenderer = require('web.ListRenderer'); - var ListView = require('web.ListView'); - - var viewRegistry = require('web.view_registry'); - - var core = require('web.core'); - var QWeb = core.qweb; - - var AdyenTransactionsListRenderer = ListRenderer.extend({ - _render: function () { - const el = this.$el.parent(); - return this._super.apply(this, arguments).then(() => { - this._rpc({ - model: 'adyen.account.balance', - method: 'get_account_balance', - content: this.context - }).then((result) => { - el.parent().find('.o_adyen_transactions_dashboard').remove(); - - const dash = QWeb.render('AdyenTransactions.dashboard', { - balances: result, - }); - el.before(dash); - }); - }); - } - }); - - var AdyenTransactionsListView = ListView.extend({ - config: _.extend({}, ListView.prototype.config, { - Renderer: AdyenTransactionsListRenderer - }), - }); - - viewRegistry.add('adyen_transactions_list', AdyenTransactionsListView); -}); diff --git a/addons/adyen_platforms/static/src/scss/adyen_platforms.scss b/addons/adyen_platforms/static/src/scss/adyen_platforms.scss deleted file mode 100644 index f7014742590..00000000000 --- a/addons/adyen_platforms/static/src/scss/adyen_platforms.scss +++ /dev/null @@ -1,35 +0,0 @@ -.o_adyen_transactions_dashboard { - .o_adyen_account_balance_card { - margin: 4px; - flex: 1; - text-align: center; - padding: 4px; - - h4 { - color: $o-enterprise-color; - font-weight: bold; - } - - ul { - list-style-type: none; - padding: 0; - margin: 0; - } - - &:not(:last-child) { - border-bottom: 2px solid $o-enterprise-color; - } - - @include media-breakpoint-up(sm) { - &:not(:last-child) { - border-right: 2px solid $o-enterprise-color; - border-bottom: 0 !important; - } - } - - .o_primary_amount { - color: $o-enterprise-primary-color; - font-size: 2rem; - } - } -} diff --git a/addons/adyen_platforms/static/src/xml/adyen_account_templates.xml b/addons/adyen_platforms/static/src/xml/adyen_account_templates.xml deleted file mode 100644 index d338d426117..00000000000 --- a/addons/adyen_platforms/static/src/xml/adyen_account_templates.xml +++ /dev/null @@ -1,125 +0,0 @@ - - - -
-
- You can start processing payments as soon as your application is sent.
- Payouts will be blocked until your application has been accepted.
- We will notify you when the status of the review changes, or if additional data is required.
-
- -

Submitted data

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Legal EntityBusiness
Legal Business Name -
Doing Business As -
Registration Number -
Legal EntityIndividual
First Name -
Last Name -
Date of Birth -
Email -
Phone Number -
Address - , - , - -
- -

Disclaimers

-

WARNING: Please note that the right to use the payment services is only for - sales in your own name. You may not resell, hire or on any other basis allow third - parties to use the payment services to enable such third parties to be paid for their - services. You may not use the payment services for different types of product and - services than as registered with your application. In particular you confirm that you - will not use the payment services for any type of product or service appearing in the - - Prohibited Products and Services List of our Processor. If we or our - Processor at any time discover that the information you provided about your - business is incorrect or has changed without informing us or if you violate any of - these conditions, the services may be suspended and/or terminated with - immediate effect and fines may be applied by the Credit Card Schemes and/or the - authorities for unregistered or inappropriate use of payment services which will in - such case be payable by you.

- -

Contractual Relationship

-

The payment processing services ordered by you by placing this order will be - provided to you by Adyen N.V. (hereafter “Processor”), with which you are - entering into a direct agreement by confirming this order. Odoo S.A. - (hereafter “We /Us”) will assist and support you in your use of the services to be - provided by the Processor and we will provide you first line assistance with and - enable you to connect to the systems of Processor to be able to use its services. - For this purpose, you hereby instruct Processor to provide us access to your data - and setting in Processor’s systems which are used by Processor to provide the - services and authorise us to manage these on your behalf.

- -

Pricing

-
    -
  • European consumer cards: 1.3% + 0.20€
  • -
  • Commercial and non-EU cards: 2.8% + 0.20€
  • -
- - - -
    -
  • Adyen MarketPay Terms and Conditions (click here to download and review)
  • -
  • Adyen Restricted and Prohibited Products and Services list (click here to download and review)
  • -
-
-
- - - - Data to provide - - - Waiting for validation - - - Confirmed - - - Failed - - -
diff --git a/addons/adyen_platforms/static/src/xml/adyen_transactions_templates.xml b/addons/adyen_platforms/static/src/xml/adyen_transactions_templates.xml deleted file mode 100644 index 1616d0f6e42..00000000000 --- a/addons/adyen_platforms/static/src/xml/adyen_transactions_templates.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - -
-
- - - -
-
-
-
diff --git a/addons/adyen_platforms/util.py b/addons/adyen_platforms/util.py deleted file mode 100644 index 8e70c35216b..00000000000 --- a/addons/adyen_platforms/util.py +++ /dev/null @@ -1,94 +0,0 @@ -# -*- coding: utf-8 -*- -# Part of Odoo. See LICENSE file for full copyright and licensing details. - -import base64 -import decorator -import hashlib -import hmac -import json -import logging -import requests -import time - -from werkzeug.urls import url_decode, url_parse -from werkzeug.exceptions import Forbidden - -from odoo.http import request -from odoo.tools import float_round - -_logger = logging.getLogger(__name__) -TIMEOUT = 60 - -def to_major_currency(amount, decimal=2): - return float_round(amount, 0) / (10**decimal) - -def to_minor_currency(amount, decimal=2): - return int(float_round(amount, decimal) * (10**decimal)) - -class AdyenProxyAuth(requests.auth.AuthBase): - def __init__(self, adyen_account_id): - super().__init__() - self.adyen_account_id = adyen_account_id - - def __call__(self, request): - h = hmac.new(self.adyen_account_id.proxy_token.encode('utf-8'), digestmod=hashlib.sha256) - - # Craft the message (timestamp|url path|query params|body content) - msg_timestamp = int(time.time()) - parsed_url = url_parse(request.path_url) - body = request.body - if isinstance(body, bytes): - body = body.decode('utf-8') - body = json.loads(body) - - message = '%s|%s|%s|%s' % ( - msg_timestamp, # timestamp - parsed_url.path, # url path - json.dumps(url_decode(parsed_url.query), sort_keys=True), # url query params sorted by key - json.dumps(body, sort_keys=True)) # request body - - h.update(message.encode('utf-8')) # digest the message - - request.headers.update({ - 'oe-adyen-uuid': self.adyen_account_id.adyen_uuid, - 'oe-signature': base64.b64encode(h.digest()), - 'oe-timestamp': msg_timestamp, - }) - - return request - -@decorator.decorator -def odoo_payments_proxy_control(func, *args, **kwargs): - _logger.debug('Check notification from Odoo Payments') - - adyen_uuid = request.httprequest.headers.get('oe-adyen-uuid') - account_id = request.env['adyen.account'].sudo().search([('adyen_uuid', '=', adyen_uuid)]) - if not account_id: - raise Forbidden() - - secret = account_id.proxy_token.encode('utf8') - msg_signature = request.httprequest.headers.get('oe-signature') # base64 encoded hmac sha256 digest - msg_timestamp = request.httprequest.headers.get('oe-timestamp') - - if not (secret and msg_signature and msg_timestamp): - raise Forbidden() - - if int(msg_timestamp) + TIMEOUT < int(time.time()): - _logger.debug('HTTP request validation failed due to invalid timestamp for route %r', request.httprequest.path) - raise Forbidden() - - h = hmac.new(secret, digestmod=hashlib.sha256) - body = json.dumps(request.jsonrequest, sort_keys=True) - - message = '%s|%s|%s|%s' % ( - msg_timestamp, # timestamp - request.httprequest.path, # url path - json.dumps(url_decode(request.httprequest.query_string), sort_keys=True), # url query params sorted by key - body, # http request body - ) - - h.update(message.encode('utf-8')) - - if not hmac.compare_digest(h.digest(), base64.b64decode(msg_signature)): - raise Forbidden() - return func(*args, **kwargs) diff --git a/addons/adyen_platforms/views/adyen_account_templates.xml b/addons/adyen_platforms/views/adyen_account_templates.xml deleted file mode 100644 index 03e97e0e397..00000000000 --- a/addons/adyen_platforms/views/adyen_account_templates.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - diff --git a/addons/adyen_platforms/views/adyen_account_views.xml b/addons/adyen_platforms/views/adyen_account_views.xml deleted file mode 100644 index a574cd400a8..00000000000 --- a/addons/adyen_platforms/views/adyen_account_views.xml +++ /dev/null @@ -1,174 +0,0 @@ - - - - adyen.account.view.form - adyen.account - -
- - - - - - -
-
- -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - -
- -
-
- - - Create an Adyen Account - adyen.account - form - - - - Account Configuration - - ir.actions.server - code - - action = model.action_create_redirect() - - -
diff --git a/addons/adyen_platforms/views/adyen_bank_account_views.xml b/addons/adyen_platforms/views/adyen_bank_account_views.xml deleted file mode 100644 index af72c78457f..00000000000 --- a/addons/adyen_platforms/views/adyen_bank_account_views.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - - adyen.bank.account.view.form - adyen.bank.account - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
diff --git a/addons/adyen_platforms/views/adyen_shareholder_views.xml b/addons/adyen_platforms/views/adyen_shareholder_views.xml deleted file mode 100644 index 5ced2f9bf37..00000000000 --- a/addons/adyen_platforms/views/adyen_shareholder_views.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - adyen.shareholder.view.form - adyen.shareholder - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
-
diff --git a/addons/adyen_platforms/views/adyen_transaction_views.xml b/addons/adyen_platforms/views/adyen_transaction_views.xml deleted file mode 100644 index cdae7ac8f77..00000000000 --- a/addons/adyen_platforms/views/adyen_transaction_views.xml +++ /dev/null @@ -1,150 +0,0 @@ - - - - adyen.transaction.view.form - adyen.transaction - -
- - - -
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - adyen.transaction.view.list - adyen.transaction - - - - - - - - - - - - - - - - - - - - - - - - - adyen.transaction - - - - - - - - - - - - - - - - - adyen.transaction.payout.view.list - adyen.transaction.payout - 10 - - - - - - - - - - - - - - adyen.transaction.payout - - - - - - - - - - - - - - - Payment Transactions - adyen.transaction - tree,form - [] - {} - -

- There are no transactions yet. -

-
-
- - - Balance - adyen.transaction.payout - tree - [] - {} - -

- No payouts yet. -

-
-
- diff --git a/addons/payment/data/payment_acquirer_data.xml b/addons/payment/data/payment_acquirer_data.xml index 2c622064d4e..c3fb27e8858 100644 --- a/addons/payment/data/payment_acquirer_data.xml +++ b/addons/payment/data/payment_acquirer_data.xml @@ -148,38 +148,6 @@ - - Odoo Payments - 10 - Credit Card (powered by Odoo Payments) - - - -

- A payment gateway to accept online payments via credit cards, debit cards and bank - transfers. -

-
    -
  • Online Payment
  • -
  • Subscriptions
  • -
  • Save Cards
  • -
  • Payment Status Tracking
  • -
-
- - -
- Ogone Credit Card (powered by Ogone) diff --git a/addons/payment_odoo/__init__.py b/addons/payment_odoo/__init__.py deleted file mode 100644 index 816928efc22..00000000000 --- a/addons/payment_odoo/__init__.py +++ /dev/null @@ -1,10 +0,0 @@ -# Part of Odoo. See LICENSE file for full copyright and licensing details. - -from . import controllers -from . import models - -from odoo.addons.payment import reset_payment_acquirer - - -def uninstall_hook(cr, registry): - reset_payment_acquirer(cr, registry, 'odoo') diff --git a/addons/payment_odoo/__manifest__.py b/addons/payment_odoo/__manifest__.py deleted file mode 100644 index 92d4bffbce4..00000000000 --- a/addons/payment_odoo/__manifest__.py +++ /dev/null @@ -1,20 +0,0 @@ -# Part of Odoo. See LICENSE file for full copyright and licensing details. - -{ - 'name': 'Odoo Payments Payment Acquirer', - 'version': '2.0', - 'category': 'Accounting/Payment Acquirers', - 'sequence': 330, - 'summary': 'Payment Acquirer: Odoo Payments', - 'description': """Odoo Payments""", - 'depends': ['payment', 'adyen_platforms'], - 'data': [ - 'views/adyen_transaction_views.xml', - 'views/payment_views.xml', - 'views/payment_odoo_templates.xml', - 'data/payment_acquirer_data.xml', - ], - 'application': True, - 'uninstall_hook': 'uninstall_hook', - 'license': 'LGPL-3', -} diff --git a/addons/payment_odoo/const.py b/addons/payment_odoo/const.py deleted file mode 100644 index 73db0f01799..00000000000 --- a/addons/payment_odoo/const.py +++ /dev/null @@ -1,22 +0,0 @@ -# Part of Odoo. See LICENSE file for full copyright and licensing details. - -# Adyen-specific mapping of currency codes in ISO 4217 format to the number of decimals. -# Only currencies for which Adyen does not follow the ISO 4217 norm are listed here. -# See https://docs.adyen.com/development-resources/currency-codes -CURRENCY_DECIMALS = { - 'CLP': 2, - 'CVE': 0, - 'IDR': 0, - 'ISK': 2, -} - -# Mapping of transaction states to Adyen result codes. -# See https://docs.adyen.com/checkout/payment-result-codes for the exhaustive list of result codes. -RESULT_CODES_MAPPING = { - 'pending': ( - 'ChallengeShopper', 'IdentifyShopper', 'Pending', 'PresentToShopper', 'Received', - 'RedirectShopper' - ), - 'done': ('Authorised',), - 'cancel': ('Cancelled',), -} diff --git a/addons/payment_odoo/controllers/__init__.py b/addons/payment_odoo/controllers/__init__.py deleted file mode 100644 index 80ee4da1c5e..00000000000 --- a/addons/payment_odoo/controllers/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# Part of Odoo. See LICENSE file for full copyright and licensing details. - -from . import main diff --git a/addons/payment_odoo/controllers/main.py b/addons/payment_odoo/controllers/main.py deleted file mode 100644 index cd4d5ed6147..00000000000 --- a/addons/payment_odoo/controllers/main.py +++ /dev/null @@ -1,93 +0,0 @@ -# Part of Odoo. See LICENSE file for full copyright and licensing details. - -import json -import logging -import pprint - -from odoo import http -from odoo.http import request - -from odoo.addons.payment import utils as payment_utils -from odoo.addons.payment_odoo.const import CURRENCY_DECIMALS - -_logger = logging.getLogger(__name__) - - -class OdooController(http.Controller): - _notification_url = '/payment/odoo/notification' - - @http.route(_notification_url, type='json', auth='public') - def odoo_notification(self): - """ Process the data sent by Adyen to the webhook based on the event code. - - See https://docs.adyen.com/development-resources/webhooks/understand-notifications for the - exhaustive list of event codes. - - :return: None - """ - # Payload data represent a single notification's data. Because two notifications of a same - # batch can be related to different sub-merchants, the proxy splits the batches and send - # individual notifications one by one to this endpoint. - notification_data = json.loads(request.httprequest.data) - - # Check the source and integrity of the notification - received_signature = notification_data.get('additionalData', {}).get( - 'metadata.merchant_signature' - ) - tx_sudo = request.env['payment.transaction'].sudo()._get_tx_from_feedback_data( - 'odoo', notification_data - ) - - # Ignore signature for REFUND, the signature will be the one of the original transaction - event_code = notification_data['eventCode'] - if event_code != 'REFUND' and not self._verify_notification_signature( - received_signature, tx_sudo - ): - return - - _logger.info("notification received:\n%s", pprint.pformat(notification_data)) - if notification_data['success'] != 'true' and event_code != 'REFUND': - return # Don't handle failed events - - request.env['adyen.transaction'].sudo()._handle_payment_notification( - notification_data, tx_sudo - ) - - # Reshape the notification data for parsing - if event_code == 'AUTHORISATION': - notification_data['resultCode'] = 'Authorised' - elif event_code == 'CANCELLATION': - notification_data['resultCode'] = 'Cancelled' - elif event_code in ['NOTIFICATION_OF_CHARGEBACK', 'CHARGEBACK']: - notification_data['resultCode'] = 'Chargeback' - elif event_code == 'REFUND': - notification_data['resultCode'] = 'Refund' - else: - return # Don't handle unsupported event codes - - # Handle the notification data as a regular feedback - request.env['payment.transaction'].sudo()._handle_feedback_data('odoo', notification_data) - - def _verify_notification_signature(self, received_signature, tx): - """ Check that the signature computed from the transaction values matches the received one. - - :param str received_signature: The signature sent with the notification - :param recordset tx: The transaction of the notification, as a `payment.transaction` record - :return: Whether the signatures match - :rtype: str - """ - - if not received_signature: - _logger.warning("ignored notification with missing signature") - return False - - converted_amount = payment_utils.to_minor_currency_units( - tx.amount, tx.currency_id, CURRENCY_DECIMALS.get(tx.currency_id.name) - ) - if not payment_utils.check_access_token( - received_signature, converted_amount, tx.currency_id.name, tx.reference - ): - _logger.warning("ignored notification with invalid signature") - return False - - return True diff --git a/addons/payment_odoo/data/payment_acquirer_data.xml b/addons/payment_odoo/data/payment_acquirer_data.xml deleted file mode 100644 index ef740073485..00000000000 --- a/addons/payment_odoo/data/payment_acquirer_data.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - odoo - - False - False - - True - True - - - - Odoo - odoo - inbound - - - diff --git a/addons/payment_odoo/i18n/payment_odoo.pot b/addons/payment_odoo/i18n/payment_odoo.pot deleted file mode 100644 index b8b996daa49..00000000000 --- a/addons/payment_odoo/i18n/payment_odoo.pot +++ /dev/null @@ -1,215 +0,0 @@ -# Translation of Odoo Server. -# This file contains the translation of the following modules: -# * payment_odoo -# -msgid "" -msgstr "" -"Project-Id-Version: Odoo Server saas~14.4\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-07-12 07:49+0000\n" -"PO-Revision-Date: 2021-07-12 07:49+0000\n" -"Last-Translator: \n" -"Language-Team: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: \n" -"Plural-Forms: \n" - -#. module: payment_odoo -#: model:ir.ui.menu,name:payment_odoo.menu_adyen_account -msgid "Account Configuration" -msgstr "" - -#. module: payment_odoo -#: model:ir.model.fields,field_description:payment_odoo.field_adyen_transaction__partner_address -#: model_terms:ir.ui.view,arch_db:payment_odoo.adyen_transaction_view_form -msgid "Address" -msgstr "" - -#. module: payment_odoo -#: model:ir.model.fields,field_description:payment_odoo.field_payment_acquirer__odoo_adyen_account_id -msgid "Adyen Account" -msgstr "" - -#. module: payment_odoo -#: model:ir.model.fields,field_description:payment_odoo.field_account_bank_statement_line__adyen_transaction_ids -#: model:ir.model.fields,field_description:payment_odoo.field_account_move__adyen_transaction_ids -#: model:ir.model.fields,field_description:payment_odoo.field_account_payment__adyen_transaction_ids -#: model:ir.model.fields,field_description:payment_odoo.field_payment_transaction__adyen_transaction_ids -msgid "Adyen Transaction" -msgstr "" - -#. module: payment_odoo -#: model:ir.model,name:payment_odoo.model_adyen_account -msgid "Adyen for Platforms Account" -msgstr "" - -#. module: payment_odoo -#: model:ir.model,name:payment_odoo.model_adyen_transaction -msgid "Adyen for Platforms Transaction" -msgstr "" - -#. module: payment_odoo -#: model:ir.ui.menu,name:payment_odoo.menu_adyen_balance -msgid "Balance" -msgstr "" - -#. module: payment_odoo -#: model:ir.model.fields,field_description:payment_odoo.field_adyen_transaction__partner_city -#: model_terms:ir.ui.view,arch_db:payment_odoo.adyen_transaction_view_form -msgid "City" -msgstr "" - -#. module: payment_odoo -#: model:ir.model.fields,field_description:payment_odoo.field_adyen_transaction__partner_country_id -#: model_terms:ir.ui.view,arch_db:payment_odoo.adyen_transaction_view_form -msgid "Country" -msgstr "" - -#. module: payment_odoo -#: model_terms:ir.ui.view,arch_db:payment_odoo.payment_acquirer_form -msgid "Create an account in 1 minute" -msgstr "" - -#. module: payment_odoo -#: model:ir.model.fields,field_description:payment_odoo.field_adyen_transaction__partner_id -msgid "Customer" -msgstr "" - -#. module: payment_odoo -#: model:ir.model.fields,field_description:payment_odoo.field_adyen_transaction__partner_email -msgid "Email" -msgstr "" - -#. module: payment_odoo -#: model_terms:ir.ui.view,arch_db:payment_odoo.adyen_transaction_view_form -msgid "Invoice(s)" -msgstr "" - -#. module: payment_odoo -#: model:ir.model.fields,field_description:payment_odoo.field_adyen_transaction__invoice_ids -msgid "Invoices" -msgstr "" - -#. module: payment_odoo -#: model:ir.model.fields,field_description:payment_odoo.field_adyen_transaction__invoices_count -msgid "Invoices Count" -msgstr "" - -#. module: payment_odoo -#: model:ir.model,name:payment_odoo.model_account_move -msgid "Journal Entry" -msgstr "" - -#. module: payment_odoo -#: model:ir.model.fields,field_description:payment_odoo.field_adyen_transaction__partner_lang -msgid "Language" -msgstr "" - -#. module: payment_odoo -#: code:addons/payment_odoo/models/payment_transaction.py:0 -#, python-format -msgid "No transaction found matching reference %s." -msgstr "" - -#. module: payment_odoo -#: model:account.payment.method,name:payment_odoo.payment_method_odoo -msgid "Odoo" -msgstr "" - -#. module: payment_odoo -#: model:ir.model.fields.selection,name:payment_odoo.selection__payment_acquirer__provider__odoo -#: model:ir.ui.menu,name:payment_odoo.root_adyen_menu -msgid "Odoo Payments" -msgstr "" - -#. module: payment_odoo -#: model:ir.model.fields,field_description:payment_odoo.field_adyen_transaction__partner_name -msgid "Partner Name" -msgstr "" - -#. module: payment_odoo -#: model:ir.model,name:payment_odoo.model_payment_acquirer -msgid "Payment Acquirer" -msgstr "" - -#. module: payment_odoo -#: model:ir.model.fields,field_description:payment_odoo.field_payment_token__odoo_payment_method_type -msgid "Payment Method Type" -msgstr "" - -#. module: payment_odoo -#: model:ir.model,name:payment_odoo.model_account_payment_method -msgid "Payment Methods" -msgstr "" - -#. module: payment_odoo -#: model:ir.model,name:payment_odoo.model_payment_token -msgid "Payment Token" -msgstr "" - -#. module: payment_odoo -#: model:ir.model,name:payment_odoo.model_payment_transaction -#: model:ir.model.fields,field_description:payment_odoo.field_adyen_transaction__payment_transaction_id -msgid "Payment Transaction" -msgstr "" - -#. module: payment_odoo -#: model:ir.ui.menu,name:payment_odoo.menu_adyen_transaction -msgid "Payment Transactions" -msgstr "" - -#. module: payment_odoo -#: model:ir.model.fields,field_description:payment_odoo.field_adyen_transaction__partner_phone -msgid "Phone" -msgstr "" - -#. module: payment_odoo -#: model:ir.model.fields,field_description:payment_odoo.field_payment_acquirer__provider -msgid "Provider" -msgstr "" - -#. module: payment_odoo -#: code:addons/payment_odoo/models/payment_transaction.py:0 -#, python-format -msgid "Received data with invalid payment state: %s" -msgstr "" - -#. module: payment_odoo -#: code:addons/payment_odoo/models/payment_transaction.py:0 -#, python-format -msgid "Received data with missing merchant reference" -msgstr "" - -#. module: payment_odoo -#: code:addons/payment_odoo/models/payment_transaction.py:0 -#, python-format -msgid "Received data with missing payment state." -msgstr "" - -#. module: payment_odoo -#: model:ir.model.fields,field_description:payment_odoo.field_adyen_transaction__partner_state_id -#: model_terms:ir.ui.view,arch_db:payment_odoo.adyen_transaction_view_form -msgid "State" -msgstr "" - -#. module: payment_odoo -#: model:ir.model.fields,help:payment_odoo.field_payment_acquirer__provider -msgid "The Payment Service Provider to use with this acquirer" -msgstr "" - -#. module: payment_odoo -#: code:addons/payment_odoo/models/payment_transaction.py:0 -#, python-format -msgid "The transaction is not linked to a token." -msgstr "" - -#. module: payment_odoo -#: model_terms:ir.ui.view,arch_db:payment_odoo.adyen_transaction_view_form -msgid "ZIP" -msgstr "" - -#. module: payment_odoo -#: model:ir.model.fields,field_description:payment_odoo.field_adyen_transaction__partner_zip -msgid "Zip" -msgstr "" diff --git a/addons/payment_odoo/i18n/payment_odoo_by_adyen.pot b/addons/payment_odoo/i18n/payment_odoo_by_adyen.pot deleted file mode 100644 index 8737df49df9..00000000000 --- a/addons/payment_odoo/i18n/payment_odoo_by_adyen.pot +++ /dev/null @@ -1,124 +0,0 @@ -# Translation of Odoo Server. -# This file contains the translation of the following modules: -# * payment_odoo_by_adyen -# -msgid "" -msgstr "" -"Project-Id-Version: Odoo Server 14.0\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-11-27 14:12+0000\n" -"PO-Revision-Date: 2020-11-27 14:12+0000\n" -"Last-Translator: \n" -"Language-Team: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: \n" -"Plural-Forms: \n" - -#. module: payment_odoo_by_adyen -#: code:addons/payment_odoo_by_adyen/models/payment.py:0 -#, python-format -msgid "; multiple order found" -msgstr "" - -#. module: payment_odoo_by_adyen -#: code:addons/payment_odoo_by_adyen/models/payment.py:0 -#, python-format -msgid "; no order found" -msgstr "" - -#. module: payment_odoo_by_adyen -#: model:ir.model.fields,field_description:payment_odoo_by_adyen.field_payment_acquirer__odoo_adyen_account_id -msgid "Adyen Account" -msgstr "" - -#. module: payment_odoo_by_adyen -#: model:ir.model.fields,field_description:payment_odoo_by_adyen.field_payment_acquirer__odoo_adyen_payout_id -msgid "Adyen Payout" -msgstr "" - -#. module: payment_odoo_by_adyen -#: code:addons/payment_odoo_by_adyen/models/payment.py:0 -#, python-format -msgid "Card No XXXXXXXXXXXX%s" -msgstr "" - -#. module: payment_odoo_by_adyen -#: model_terms:ir.ui.view,arch_db:payment_odoo_by_adyen.acquirer_form_odoo_by_adyen -msgid "Create an account in 1 minute" -msgstr "" - -#. module: payment_odoo_by_adyen -#: model:ir.model.fields,field_description:payment_odoo_by_adyen.field_payment_acquirer__display_name -#: model:ir.model.fields,field_description:payment_odoo_by_adyen.field_payment_token__display_name -#: model:ir.model.fields,field_description:payment_odoo_by_adyen.field_payment_transaction__display_name -msgid "Display Name" -msgstr "" - -#. module: payment_odoo_by_adyen -#: model:ir.model.fields,field_description:payment_odoo_by_adyen.field_payment_acquirer__id -#: model:ir.model.fields,field_description:payment_odoo_by_adyen.field_payment_token__id -#: model:ir.model.fields,field_description:payment_odoo_by_adyen.field_payment_transaction__id -msgid "ID" -msgstr "" - -#. module: payment_odoo_by_adyen -#: model:ir.model.fields,field_description:payment_odoo_by_adyen.field_payment_acquirer____last_update -#: model:ir.model.fields,field_description:payment_odoo_by_adyen.field_payment_token____last_update -#: model:ir.model.fields,field_description:payment_odoo_by_adyen.field_payment_transaction____last_update -msgid "Last Modified on" -msgstr "" - -#. module: payment_odoo_by_adyen -#: code:addons/payment_odoo_by_adyen/models/payment.py:0 -#, python-format -msgid "Odoo Payment by Adyen: feedback error" -msgstr "" - -#. module: payment_odoo_by_adyen -#: model:ir.model.fields.selection,name:payment_odoo_by_adyen.selection__payment_acquirer__provider__odoo_adyen -msgid "Odoo Payments by Adyen" -msgstr "" - -#. module: payment_odoo_by_adyen -#: code:addons/payment_odoo_by_adyen/models/payment.py:0 -#, python-format -msgid "Odoo Payments by Adyen is not available in test mode." -msgstr "" - -#. module: payment_odoo_by_adyen -#: code:addons/payment_odoo_by_adyen/models/payment.py:0 -#, python-format -msgid "Odoo Payments by Adyen: received data for reference %s" -msgstr "" - -#. module: payment_odoo_by_adyen -#: code:addons/payment_odoo_by_adyen/models/payment.py:0 -#, python-format -msgid "Odoo Payments by Adyen: received data with missing reference (%s)" -msgstr "" - -#. module: payment_odoo_by_adyen -#: model:ir.model,name:payment_odoo_by_adyen.model_payment_acquirer -msgid "Payment Acquirer" -msgstr "" - -#. module: payment_odoo_by_adyen -#: model:ir.model,name:payment_odoo_by_adyen.model_payment_token -msgid "Payment Token" -msgstr "" - -#. module: payment_odoo_by_adyen -#: model:ir.model,name:payment_odoo_by_adyen.model_payment_transaction -msgid "Payment Transaction" -msgstr "" - -#. module: payment_odoo_by_adyen -#: model:ir.model.fields,field_description:payment_odoo_by_adyen.field_payment_token__odoo_adyen_payment_method_type -msgid "PaymentMethod Type" -msgstr "" - -#. module: payment_odoo_by_adyen -#: model:ir.model.fields,field_description:payment_odoo_by_adyen.field_payment_acquirer__provider -msgid "Provider" -msgstr "" diff --git a/addons/payment_odoo/models/__init__.py b/addons/payment_odoo/models/__init__.py deleted file mode 100644 index 447999fe187..00000000000 --- a/addons/payment_odoo/models/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -# Part of Odoo. See LICENSE file for full copyright and licensing details. - -from . import account_move -from . import adyen_account -from . import adyen_transaction -from . import account_payment_method -from . import payment_acquirer -from . import payment_token -from . import payment_transaction diff --git a/addons/payment_odoo/models/account_move.py b/addons/payment_odoo/models/account_move.py deleted file mode 100644 index 34c751b3d15..00000000000 --- a/addons/payment_odoo/models/account_move.py +++ /dev/null @@ -1,23 +0,0 @@ -# Part of Odoo. See LICENSE file for full copyright and licensing details. - -from odoo import fields, models - - -class AccountMove(models.Model): - _inherit = 'account.move' - - adyen_transaction_ids = fields.One2many(related='transaction_ids.adyen_transaction_ids') - - def action_view_payment_transactions(self): - if any(provider != 'odoo' for provider in self.transaction_ids.mapped('provider')): - return super().action_view_payment_transactions() - - action = self.env['ir.actions.act_window']._for_xml_id('adyen_platforms.adyen_transaction_action') - if len(self.adyen_transaction_ids) == 1: - action['view_mode'] = 'form' - action['res_id'] = self.adyen_transaction_ids.id - action['views'] = [] - else: - action['domain'] = [('id', 'in', self.adyen_transaction_ids.ids)] - - return action diff --git a/addons/payment_odoo/models/account_payment_method.py b/addons/payment_odoo/models/account_payment_method.py deleted file mode 100644 index 586d4da6ca3..00000000000 --- a/addons/payment_odoo/models/account_payment_method.py +++ /dev/null @@ -1,14 +0,0 @@ -# -*- coding: utf-8 -*- -# Part of Odoo. See LICENSE file for full copyright and licensing details. - -from odoo import api, models - - -class AccountPaymentMethod(models.Model): - _inherit = 'account.payment.method' - - @api.model - def _get_payment_method_information(self): - res = super()._get_payment_method_information() - res['odoo'] = {'mode': 'unique', 'domain': [('type', '=', 'bank')]} - return res diff --git a/addons/payment_odoo/models/adyen_account.py b/addons/payment_odoo/models/adyen_account.py deleted file mode 100644 index f61cda16c16..00000000000 --- a/addons/payment_odoo/models/adyen_account.py +++ /dev/null @@ -1,12 +0,0 @@ -# Part of Odoo. See LICENSE file for full copyright and licensing details. - -from odoo import models - - -class AdyenAccount(models.Model): - _inherit = 'adyen.account' - - def unlink(self): - acquirer = self.env['payment.acquirer'].search([('provider', '=', 'odoo'), ('odoo_adyen_account_id', 'in', self.ids)]) - acquirer.state = 'disabled' - return super().unlink() diff --git a/addons/payment_odoo/models/adyen_transaction.py b/addons/payment_odoo/models/adyen_transaction.py deleted file mode 100644 index b2882a57535..00000000000 --- a/addons/payment_odoo/models/adyen_transaction.py +++ /dev/null @@ -1,57 +0,0 @@ -# Part of Odoo. See LICENSE file for full copyright and licensing details. - -from odoo import api, fields, models -from odoo.tools.float_utils import float_is_zero - - -class AdyenTransaction(models.Model): - _inherit = 'adyen.transaction' - - payment_transaction_id = fields.Many2one(comodel_name='payment.transaction') - - # payment.transaction fields - invoice_ids = fields.Many2many(related='payment_transaction_id.invoice_ids') - invoices_count = fields.Integer(related='payment_transaction_id.invoices_count') - - partner_id = fields.Many2one(related='payment_transaction_id.partner_id') - partner_name = fields.Char(related='payment_transaction_id.partner_name') - partner_lang = fields.Selection(related='payment_transaction_id.partner_lang') - partner_email = fields.Char(related='payment_transaction_id.partner_email') - partner_address = fields.Char(related='payment_transaction_id.partner_address') - partner_zip = fields.Char(related='payment_transaction_id.partner_zip') - partner_city = fields.Char(related='payment_transaction_id.partner_city') - partner_state_id = fields.Many2one(related='payment_transaction_id.partner_state_id') - partner_country_id = fields.Many2one(related='payment_transaction_id.partner_country_id') - partner_phone = fields.Char(related='payment_transaction_id.partner_phone') - - @api.model - def _handle_payment_notification(self, notification_data, payment_tx): - tx_sudo = self._handle_notification(notification_data) - - if not tx_sudo.payment_transaction_id: - tx_sudo.payment_transaction_id = payment_tx.id - - # Update fees on payment.transaction - if float_is_zero(payment_tx.fees, precision_digits=payment_tx.currency_id.decimal_places) and not float_is_zero(tx_sudo.fees, precision_digits=tx_sudo.fees_currency_id.decimal_places): - amount = tx_sudo.fees_currency_id._convert(tx_sudo.fees, payment_tx.currency_id, self.env.company, tx_sudo.date or fields.Date.today()) - payment_tx.fees = amount - - def _create_missing_tx(self, account_id, transaction, **kwargs): - tx = super()._create_missing_tx(account_id, transaction, **kwargs) - if tx.description and not tx.payment_transaction_id: - payment_tx = self.env['payment.transaction'].search([('reference', '=', tx.description), ('provider', '=', 'odoo')]) - if payment_tx: - tx.payment_transaction_id = payment_tx.id - - if not transaction.get('disputePspReference') and tx.merchant_amount > 0: - tx.total_amount = payment_tx.amount - tx.currency_id = payment_tx.currency_id - - fees_amount = tx.total_amount - tx.merchant_amount - tx.fees = payment_tx.currency_id._convert(fees_amount, tx.fees_currency_id, self.env.company, tx.date or fields.Date.today()) - tx.variable_fees = tx.fees - return tx - - def action_view_invoices(self): - self.ensure_one() - return self.payment_transaction_id.action_view_invoices() diff --git a/addons/payment_odoo/models/payment_acquirer.py b/addons/payment_odoo/models/payment_acquirer.py deleted file mode 100644 index 347eeb1fff9..00000000000 --- a/addons/payment_odoo/models/payment_acquirer.py +++ /dev/null @@ -1,40 +0,0 @@ -# Part of Odoo. See LICENSE file for full copyright and licensing details. - -from werkzeug import urls - -from odoo import fields, models - - -class PaymentAcquirer(models.Model): - _inherit = 'payment.acquirer' - - provider = fields.Selection( - selection_add=[('odoo', "Odoo Payments")], ondelete={'odoo': 'set default'}) - odoo_adyen_account_id = fields.Many2one( - related='company_id.adyen_account_id', required_if_provider='odoo') - - def odoo_create_adyen_account(self): - return self.env['adyen.account'].action_create_redirect() - - def _odoo_get_api_url(self): - self.ensure_one() - proxy_url = self.env['ir.config_parameter'].sudo().get_param('adyen_platforms.proxy_url') - url = 'v1/pay_by_link' if self.state == 'enabled' else 'v1/test_pay_by_link' - return urls.url_join(proxy_url, url) - - def _odoo_compute_shopper_reference(self, partner_id): - """ Compute a unique reference of the partner for Adyen. - - This is used for the `shopperReference` field in communications with Adyen. - - :param recordset partner_id: The partner making the transaction, as a `res.partner` id - :return: The unique reference for the partner - :rtype: str - """ - return f'{self.odoo_adyen_account_id.adyen_uuid}_{partner_id}' - - def _get_default_payment_method_id(self): - self.ensure_one() - if self.provider != 'odoo': - return super()._get_default_payment_method_id() - return self.env.ref('payment_odoo.payment_method_odoo').id diff --git a/addons/payment_odoo/models/payment_token.py b/addons/payment_odoo/models/payment_token.py deleted file mode 100644 index d8c5a13b558..00000000000 --- a/addons/payment_odoo/models/payment_token.py +++ /dev/null @@ -1,9 +0,0 @@ -# Part of Odoo. See LICENSE file for full copyright and licensing details. - -from odoo import fields, models - - -class PaymentToken(models.Model): - _inherit = 'payment.token' - - odoo_payment_method_type = fields.Char(string="Payment Method Type") diff --git a/addons/payment_odoo/models/payment_transaction.py b/addons/payment_odoo/models/payment_transaction.py deleted file mode 100644 index d273acd37ee..00000000000 --- a/addons/payment_odoo/models/payment_transaction.py +++ /dev/null @@ -1,236 +0,0 @@ -# Part of Odoo. See LICENSE file for full copyright and licensing details. - -import json -import logging -import pprint - -from werkzeug import urls - -from odoo import _, api, fields, models -from odoo.exceptions import UserError, ValidationError - -from odoo.addons.payment import utils as payment_utils -from odoo.addons.payment_odoo.const import CURRENCY_DECIMALS, RESULT_CODES_MAPPING -from odoo.addons.payment_odoo.controllers.main import OdooController - -_logger = logging.getLogger(__name__) - - -class PaymentTransaction(models.Model): - _inherit = 'payment.transaction' - - adyen_transaction_ids = fields.One2many('adyen.transaction', 'payment_transaction_id') - - def _get_specific_rendering_values(self, processing_values): - """ Override of payment to return Odoo-specific rendering values. - - Note: self.ensure_one() from `_get_processing_values` - - :param dict processing_values: The generic and specific processing values of the transaction - :return: The dict of acquirer-specific processing values - :rtype: dict - """ - res = super()._get_specific_rendering_values(processing_values) - if self.provider != 'odoo': - return res - - converted_amount = payment_utils.to_minor_currency_units( - self.amount, self.currency_id, CURRENCY_DECIMALS.get(self.currency_id.name) - ) - # The lang is taken from the context rather than from the partner because it is not required - # to be logged to make a payment and because the lang is not always set on the partner. - # Adyen only supports a reduced set of languages but, instead of looking for the closest - # match in https://docs.adyen.com/checkout/components-web/localization-components, we simply - # provide the lang string as is (after adapting the format) and let Adyen find the best fit. - lang_code = (self._context.get('lang') or 'en-US').replace('_', '-') - base_url = self.acquirer_id.get_base_url() - signature = payment_utils.generate_access_token( - converted_amount, self.currency_id.name, self.reference - ) - data = { - 'amount': { - 'value': converted_amount, - 'currency': self.currency_id.name, - }, - 'reference': self.reference, - 'shopperLocale': lang_code, - 'shopperReference': self.acquirer_id._odoo_compute_shopper_reference( - self.partner_id.id - ) if self.tokenize else '', - 'recurringProcessingModel': 'Subscription' if self.tokenize else '', - 'storePaymentMethod': self.tokenize, # True by default on Adyen side - # Since the Pay by Link API redirects the customer without any payload, we use the - # /payment/status route directly as return url. - 'returnUrl': urls.url_join(base_url, '/payment/status'), - 'metadata': { - 'merchant_signature': signature, - 'notification_url': urls.url_join(base_url, OdooController._notification_url), - 'adyen_uuid': self.acquirer_id.odoo_adyen_account_id.adyen_uuid, - 'payout': self.acquirer_id.odoo_adyen_account_id.account_code, - }, # Proxy-specific data - } - return { - 'data': json.dumps(data), - 'api_url': self.acquirer_id._odoo_get_api_url(), - } - - def _send_payment_request(self): - """ Override of payment to send a payment request to Adyen through the Odoo proxy. - - Note: self.ensure_one() - - :return: None - :raise: UserError if the transaction is not linked to a token - """ - super()._send_payment_request() - if self.provider != 'odoo': - return - - # Make the payment request - if not self.token_id: - raise UserError("Odoo Payments: " + _("The transaction is not linked to a token.")) - - converted_amount = payment_utils.to_minor_currency_units( - self.amount, self.currency_id, CURRENCY_DECIMALS.get(self.currency_id.name) - ) - base_url = self.acquirer_id.get_base_url() - signature = payment_utils.generate_access_token( - converted_amount, self.currency_id.name, self.reference - ) - data = { - 'amount': { - 'value': converted_amount, - 'currency': self.currency_id.name, - }, - 'reference': self.reference, - 'paymentMethod': { - 'type': self.token_id.odoo_payment_method_type, - 'storedPaymentMethodId': self.token_id.acquirer_ref, - }, - 'shopperReference': self.acquirer_id._odoo_compute_shopper_reference( - self.partner_id.id - ), - 'recurringProcessingModel': 'Subscription', - 'shopperInteraction': 'ContAuth', - 'metadata': { - 'merchant_signature': signature, - 'notification_url': urls.url_join(base_url, OdooController._notification_url), - 'adyen_uuid': self.acquirer_id.odoo_adyen_account_id.adyen_uuid, - 'payout': self.acquirer_id.odoo_adyen_account_id.account_code, - }, # Proxy-specific data - } - response_content = self.acquirer_id.odoo_adyen_account_id._adyen_rpc('v1/payments', data) - - # Handle the payment request response - _logger.info("payment request response:\n%s", pprint.pformat(response_content)) - self._handle_feedback_data('odoo', response_content) - - @api.model - def _get_tx_from_feedback_data(self, provider, data): - """ Override of payment to find the transaction based on Adyen data. - - :param str provider: The provider of the acquirer that handled the transaction - :param dict data: The feedback data sent by the provider - :return: The transaction if found - :rtype: recordset of `payment.transaction` - :raise: ValidationError if inconsistent data were received - :raise: ValidationError if the data match no transaction - """ - tx = super()._get_tx_from_feedback_data(provider, data) - if provider != 'odoo': - return tx - - reference = data.get('merchantReference') or data.get('additionalData', {}).get('merchantReference') - if not reference: - raise ValidationError( - "Odoo Payments: " + _("Received data with missing merchant reference") - ) - - tx = self.search([('reference', '=', reference), ('provider', '=', 'odoo')]) - if not tx: - raise ValidationError( - "Odoo Payments: " + _("No transaction found matching reference %s.", reference) - ) - return tx - - def _process_feedback_data(self, data): - """ Override of payment to process the transaction based on Adyen data. - - Since only webhook notifications send data, the parsing is exclusively done according to the - structure of NotificationRequestItem object. - See https://docs.adyen.com/development-resources/webhooks/notifications-api - - Note: self.ensure_one() - - :param dict data: The feedback data sent by the provider - :return: None - :raise: ValidationError if inconsistent data were received - """ - super()._process_feedback_data(data) - if self.provider != 'odoo': - return - - # Handle the acquirer reference - if 'originalReference' in data: - self.acquirer_reference = data['originalReference'] - elif 'pspReference' in data: - self.acquirer_reference = data['pspReference'] - - # Handle the payment state - payment_state = data.get('resultCode') - if not payment_state: - raise ValidationError( - "Odoo Payments: " + _("Received data with missing payment state.") - ) - - if payment_state in RESULT_CODES_MAPPING['pending']: - self._set_pending() - elif payment_state in RESULT_CODES_MAPPING['done']: - has_token_data = 'recurring.recurringDetailReference' in data.get('additionalData', {}) - if self.tokenize and has_token_data: - self._odoo_tokenize_from_feedback_data(data) - self._set_done() - elif payment_state in RESULT_CODES_MAPPING['cancel']: - self._set_canceled() - else: # Classify unsupported payment state as `error` tx state - _logger.info("received data with invalid payment state: %s", payment_state) - self._set_error( - "Odoo Payments: " + _("Received data with invalid payment state: %s", payment_state) - ) - - def _odoo_tokenize_from_feedback_data(self, data): - """ Create a new token based on the feedback data. - - Note: self.ensure_one() - - :param dict data: The feedback data sent by the provider - :return: None - """ - self.ensure_one() - - # Retrieve all stored payment methods for the customer from the API and match them with the - # acquirer reference of the transaction to find its payment method - response_content = self.acquirer_id.odoo_adyen_account_id._adyen_rpc( - 'v1/payment_methods', - dict(shopperReference=data['additionalData']['recurring.shopperReference']), - ) - payment_methods = response_content['storedPaymentMethods'] - acquirer_ref = data['additionalData']['recurring.recurringDetailReference'] - payment_method_type = next(pm['type'] for pm in payment_methods if pm['id'] == acquirer_ref) - - # Create the token - token = self.env['payment.token'].create({ - 'acquirer_id': self.acquirer_id.id, - 'name': payment_utils.build_token_name(data['additionalData'].get('cardSummary')), - 'partner_id': self.partner_id.id, - 'acquirer_ref': acquirer_ref, - 'verified': True, # The payment is authorized, so the payment method is valid - 'odoo_payment_method_type': payment_method_type, - }) - self.write({ - 'token_id': token, - 'tokenize': False, - }) - _logger.info( - "created token with id %s for partner with id %s", token.id, self.partner_id.id - ) diff --git a/addons/payment_odoo/static/description/icon.png b/addons/payment_odoo/static/description/icon.png deleted file mode 100644 index 25161e25ebd..00000000000 Binary files a/addons/payment_odoo/static/description/icon.png and /dev/null differ diff --git a/addons/payment_odoo/static/description/icon.svg b/addons/payment_odoo/static/description/icon.svg deleted file mode 100644 index 0dc448c887d..00000000000 --- a/addons/payment_odoo/static/description/icon.svg +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/addons/payment_odoo/static/src/img/odoo_icon.png b/addons/payment_odoo/static/src/img/odoo_icon.png deleted file mode 100644 index 5701852c578..00000000000 Binary files a/addons/payment_odoo/static/src/img/odoo_icon.png and /dev/null differ diff --git a/addons/payment_odoo/views/adyen_transaction_views.xml b/addons/payment_odoo/views/adyen_transaction_views.xml deleted file mode 100644 index 48b914a85df..00000000000 --- a/addons/payment_odoo/views/adyen_transaction_views.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - adyen.transaction - - - - - - - - - - adyen.transaction - - - - - - - - - - - - - - diff --git a/addons/payment_odoo/views/payment_odoo_templates.xml b/addons/payment_odoo/views/payment_odoo_templates.xml deleted file mode 100644 index c9ae5def1dd..00000000000 --- a/addons/payment_odoo/views/payment_odoo_templates.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - diff --git a/addons/payment_odoo/views/payment_views.xml b/addons/payment_odoo/views/payment_views.xml deleted file mode 100644 index e35145c48b8..00000000000 --- a/addons/payment_odoo/views/payment_views.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - Odoo Payments Acquirer Form - payment.acquirer - - - - - - - - -