From 6965066e9cd1499dc51b7f49f523c54a60fa2a86 Mon Sep 17 00:00:00 2001 From: Laura Schauer Date: Wed, 22 Jun 2022 08:02:54 +0000 Subject: [PATCH] [IMP] payment: allow (un)publishing of payment acquirers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before this commit, it was impossible to migrate from one payment acquirer to another as the only way to do so was to change a payment acquirer’s state to ‘disabled’, subsequently disabling all tokens of that acquirer (detrimental for eg. running subscriptions). After this commit, payment acquirers have an additional boolean ‘Published’. With this functionality, users can safely migrate by keeping an acquirer ‘enabled’, but invisible for customers. There are five combined states an acquirer can take: ‘enabled’ & ‘published’: Visible to all users ‘enabled’ & ‘unpublished’: Visible only to internal users ‘disabled’ & ‘unpublished’: Same as previously ‘disabled’ ‘test’ & ‘published’: Same as previously ‘test’ ‘test’ & ‘unpublished’: visible only to internal users task-2871459 closes odoo/odoo#94242 Related: odoo/upgrade#3688 Related: odoo/documentation#2308 Signed-off-by: Antoine Vandevenne (anv) --- addons/payment/models/payment_acquirer.py | 32 +++++++++++++++-- addons/payment/tests/__init__.py | 1 + addons/payment/tests/common.py | 1 + addons/payment/tests/test_payment_acquirer.py | 36 +++++++++++++++++++ .../payment/views/payment_acquirer_views.xml | 26 ++++++++++++++ addons/payment/views/payment_templates.xml | 20 ++++++++++- .../data/payment_acquirer_data.xml | 1 + 7 files changed, 114 insertions(+), 3 deletions(-) create mode 100644 addons/payment/tests/test_payment_acquirer.py diff --git a/addons/payment/models/payment_acquirer.py b/addons/payment/models/payment_acquirer.py index 590727e2ab8..dc84d709e17 100644 --- a/addons/payment/models/payment_acquirer.py +++ b/addons/payment/models/payment_acquirer.py @@ -5,7 +5,7 @@ import logging from psycopg2 import sql from odoo import _, api, fields, models, SUPERUSER_ID -from odoo.exceptions import ValidationError +from odoo.exceptions import UserError, ValidationError from odoo.osv import expression _logger = logging.getLogger(__name__) @@ -31,6 +31,11 @@ class PaymentAcquirer(models.Model): "This mode is advised when setting up the acquirer.", selection=[('disabled', "Disabled"), ('enabled', "Enabled"), ('test', "Test Mode")], default='disabled', required=True, copy=False) + is_published = fields.Boolean( + string="Published", + help="Whether the acquirer is visible on the website or not. Tokens remain functional but " + "are only visible on manage forms.", + ) company_id = fields.Many2one( # Indexed to speed-up ORM searches (from ir_rule or others) string="Company", comodel_name='res.company', default=lambda self: self.env.company.id, required=True, index=True) @@ -236,7 +241,15 @@ class PaymentAcquirer(models.Model): #=== ONCHANGE METHODS ===# @api.onchange('state') - def _onchange_state(self): + def _onchange_state_switch_is_published(self): + """ Automatically publish or unpublish the acquirer depending on its state. + + :return: None + """ + self.is_published = self.state == 'enabled' + + @api.onchange('state') + def _onchange_state_warn_before_disabling_tokens(self): """ Display a warning about the consequences of disabling an acquirer. Let the user know that tokens related to an acquirer get archived if it is disabled or if @@ -348,6 +361,17 @@ class PaymentAcquirer(models.Model): 'tag': 'reload', } + def action_toggle_is_published(self): + """ Toggle the acquirer's is_published state. + + :return: none + :raise UserError: If the acquirer is disabled. + """ + if self.state != 'disabled': + self.is_published = not self.is_published + else: + raise UserError(_("You cannot publish a disabled acquirer.")) + #=== BUSINESS METHODS ===# @api.model @@ -372,6 +396,10 @@ class PaymentAcquirer(models.Model): # Compute the base domain for compatible acquirers domain = ['&', ('state', 'in', ['enabled', 'test']), ('company_id', '=', company_id)] + # Handle the is_published state. + if not self.env.user._is_internal(): + domain = expression.AND([domain, [('is_published', '=', True)]]) + # Handle partner country partner = self.env['res.partner'].browse(partner_id) if partner.country_id: # The partner country must either not be set or be supported diff --git a/addons/payment/tests/__init__.py b/addons/payment/tests/__init__.py index d17e2d6a0f4..fb7389458f4 100644 --- a/addons/payment/tests/__init__.py +++ b/addons/payment/tests/__init__.py @@ -5,4 +5,5 @@ from . import http_common from . import test_account_payment from . import test_flows from . import test_multicompany_flows +from . import test_payment_acquirer from . import test_payment_transaction diff --git a/addons/payment/tests/common.py b/addons/payment/tests/common.py index 940847c25bd..bc7bf6681f1 100644 --- a/addons/payment/tests/common.py +++ b/addons/payment/tests/common.py @@ -92,6 +92,7 @@ class PaymentCommon(AccountTestInvoicingCommon): 'name': "Dummy Acquirer", 'provider': 'none', 'state': 'test', + 'is_published': True, 'allow_tokenization': True, 'redirect_form_view_id': redirect_form.id, 'journal_id': cls.company_data['default_journal_bank'].id, diff --git a/addons/payment/tests/test_payment_acquirer.py b/addons/payment/tests/test_payment_acquirer.py new file mode 100644 index 00000000000..b3351bef425 --- /dev/null +++ b/addons/payment/tests/test_payment_acquirer.py @@ -0,0 +1,36 @@ +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo.tests import tagged + +from odoo.addons.payment.tests.common import PaymentCommon + + +@tagged('-at_install', 'post_install') +class TestPaymentAcquirer(PaymentCommon): + + def test_published_acquirer_compatible_with_all_users(self): + for user in (self.public_user, self.portal_user): + self.env = self.env(user=user) + + compatible_acquirers = self.env['payment.acquirer'].sudo()._get_compatible_acquirers( + self.company.id, self.partner.id + ) + self.assertIn(self.acquirer, compatible_acquirers) + + def test_unpublished_acquirer_compatible_with_internal_user(self): + self.acquirer.is_published = False + + compatible_acquirers = self.env['payment.acquirer']._get_compatible_acquirers( + self.company.id, self.partner.id + ) + self.assertIn(self.acquirer, compatible_acquirers) + + def test_unpublished_acquirer_not_compatible_with_non_internal_user(self): + self.acquirer.is_published = False + for user in (self.public_user, self.portal_user): + self.env = self.env(user=user) + + compatible_acquirers = self.env['payment.acquirer'].sudo()._get_compatible_acquirers( + self.company.id, self.partner.id + ) + self.assertNotIn(self.acquirer, compatible_acquirers) diff --git a/addons/payment/views/payment_acquirer_views.xml b/addons/payment/views/payment_acquirer_views.xml index 3158495c4ee..975ccbeeea6 100644 --- a/addons/payment/views/payment_acquirer_views.xml +++ b/addons/payment/views/payment_acquirer_views.xml @@ -6,6 +6,7 @@ payment.acquirer
+ @@ -21,6 +22,27 @@ + +
+ + +
@@ -117,6 +139,7 @@ + @@ -126,6 +149,7 @@ +
@@ -138,6 +162,8 @@ + Published + Unpublished diff --git a/addons/payment/views/payment_templates.xml b/addons/payment/views/payment_templates.xml index 25c8d379da8..3bcaf5e05e4 100644 --- a/addons/payment/views/payment_templates.xml +++ b/addons/payment/views/payment_templates.xml @@ -66,6 +66,11 @@ class="rounded-pill text-bg-warning ms-1"> Test Mode + + + Unpublished + @@ -118,6 +123,10 @@ + + + Unpublished +
@@ -195,7 +204,7 @@ data-payment-option-type="acquirer"/> - + Test Mode + + + Unpublished + @@ -244,6 +257,11 @@ + + + Unpublished +