Odoo18-Base/addons/payment/tests/test_payment_method.py
2025-01-06 10:57:38 +07:00

236 lines
12 KiB
Python

# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.exceptions import UserError
from odoo.models import Command
from odoo.tests import tagged
from odoo.addons.payment import utils as payment_utils
from odoo.addons.payment.const import REPORT_REASONS_MAPPING
from odoo.addons.payment.tests.common import PaymentCommon
@tagged('-at_install', 'post_install')
class TestPaymentMethod(PaymentCommon):
def test_unlinking_payment_method_from_provider_state_archives_tokens(self):
""" Test that the active tokens of a payment method created through a provider are archived
when the method is unlinked from the provider. """
token = self._create_token()
self.payment_method.provider_ids = [Command.unlink(self.payment_method.provider_ids[:1].id)]
self.assertFalse(token.active)
def test_payment_method_requires_provider_to_be_activated(self):
""" Test that activating a payment method that is not linked to an enabled provider is
forbidden. """
self.provider.state = 'disabled'
with self.assertRaises(UserError):
self.payment_methods.active = True
def test_payment_method_compatible_when_provider_is_enabled(self):
""" Test that a payment method is available when it is supported by an enabled provider. """
compatible_payment_methods = self.env['payment.method']._get_compatible_payment_methods(
self.provider.ids, self.partner.id
)
self.assertIn(self.payment_method, compatible_payment_methods)
def test_payment_method_not_compatible_when_provider_is_disabled(self):
""" Test that a payment method is not available when there is no enabled provider that
supports it. """
self.provider.state = 'disabled'
compatible_payment_methods = self.env['payment.method']._get_compatible_payment_methods(
self.provider.ids, self.partner.id
)
self.assertNotIn(self.payment_method, compatible_payment_methods)
def test_non_primary_payment_method_not_compatible(self):
""" Test that a "brand" (i.e., non-primary) payment method is never available. """
brand_payment_method = self.payment_method.copy()
brand_payment_method.primary_payment_method_id = self.payment_method_id # Make it a brand.
compatible_payment_methods = self.env['payment.method']._get_compatible_payment_methods(
self.provider.ids, self.partner.id
)
self.assertNotIn(brand_payment_method, compatible_payment_methods)
def test_payment_method_compatible_with_supported_countries(self):
""" Test that the payment method is compatible with its supported countries. """
belgium = self.env.ref('base.be')
self.payment_method.supported_country_ids = [Command.set([belgium.id])]
self.partner.country_id = belgium
compatible_payment_methods = self.env['payment.method']._get_compatible_payment_methods(
self.provider.ids, self.partner.id
)
self.assertIn(self.payment_method, compatible_payment_methods)
def test_payment_method_not_compatible_with_unsupported_countries(self):
""" Test that the payment method is not compatible with a country that is not supported. """
belgium = self.env.ref('base.be')
self.payment_method.supported_country_ids = [Command.set([belgium.id])]
france = self.env.ref('base.fr')
self.partner.country_id = france
compatible_payment_methods = self.env['payment.method']._get_compatible_payment_methods(
self.provider.ids, self.partner.id
)
self.assertNotIn(self.payment_method, compatible_payment_methods)
def test_payment_method_compatible_when_no_supported_countries_set(self):
""" Test that the payment method is always compatible when no supported countries are
set. """
self.payment_method.supported_country_ids = [Command.clear()]
belgium = self.env.ref('base.be')
self.partner.country_id = belgium
compatible_payment_methods = self.env['payment.method']._get_compatible_payment_methods(
self.provider.ids, self.partner.id
)
self.assertIn(self.payment_method, compatible_payment_methods)
def test_payment_method_compatible_with_supported_currencies(self):
""" Test that the payment method is compatible with its supported currencies. """
self.payment_method.supported_currency_ids = [Command.set([self.currency_euro.id])]
compatible_payment_methods = self.env['payment.method']._get_compatible_payment_methods(
self.provider.ids, self.partner.id, currency_id=self.currency_euro.id
)
self.assertIn(self.payment_method, compatible_payment_methods)
def test_payment_method_not_compatible_with_unsupported_currencies(self):
""" Test that the payment method is not compatible with a currency that is not
supported. """
self.payment_method.supported_currency_ids = [Command.set([self.currency_euro.id])]
compatible_payment_methods = self.env['payment.method']._get_compatible_payment_methods(
self.provider.ids, self.partner.id, currency_id=self.currency_usd.id
)
self.assertNotIn(self.payment_method, compatible_payment_methods)
def test_payment_method_compatible_when_no_supported_currencies_set(self):
""" Test that the payment method is always compatible when no supported currencies are
set. """
self.payment_method.supported_currency_ids = [Command.clear()]
compatible_payment_methods = self.env['payment.method']._get_compatible_payment_methods(
self.provider.ids, self.partner.id, currency_id=self.currency_euro.id
)
self.assertIn(self.payment_method, compatible_payment_methods)
def test_payment_method_compatible_when_tokenization_forced(self):
""" Test that the payment method is compatible when it supports tokenization while it is
forced by the calling module. """
self.payment_method.support_tokenization = True
compatible_payment_methods = self.env['payment.method']._get_compatible_payment_methods(
self.provider.ids, self.partner.id, force_tokenization=True
)
self.assertIn(self.payment_method, compatible_payment_methods)
def test_payment_method_not_compatible_when_tokenization_forced(self):
""" Test that the payment method is not compatible when it does not support tokenization
while it is forced by the calling module. """
self.payment_method.support_tokenization = False
compatible_payment_methods = self.env['payment.method']._get_compatible_payment_methods(
self.provider.ids, self.partner.id, force_tokenization=True
)
self.assertNotIn(self.payment_method, compatible_payment_methods)
def test_payment_method_compatible_with_express_checkout(self):
""" Test that the payment method is compatible when it supports express checkout while it is
an express checkout flow. """
self.payment_method.support_express_checkout = True
compatible_payment_methods = self.env['payment.method']._get_compatible_payment_methods(
self.provider.ids, self.partner.id, is_express_checkout=True
)
self.assertIn(self.payment_method, compatible_payment_methods)
def test_payment_method_not_compatible_with_express_checkout(self):
""" Test that the payment method is not compatible when it does not support express checkout
while it is an express checkout flow. """
self.payment_method.support_express_checkout = False
compatible_payment_methods = self.env['payment.method']._get_compatible_payment_methods(
self.provider.ids, self.partner.id, is_express_checkout=True
)
self.assertNotIn(self.payment_method, compatible_payment_methods)
def test_availability_report_covers_all_reasons(self):
""" Test that every possible unavailability reason is correctly reported. """
# Disable all payment methods.
pms = self.env['payment.method'].search([('is_primary', '=', True)])
pms.active = False
# Prepare a base payment method.
self.payment_method.write({
'active': True,
'support_express_checkout': True,
'support_tokenization': True,
})
# Prepare the report with a provider to allow checking provider availability.
report = {}
payment_utils.add_to_report(report, self.provider)
# Prepare a payment method with an unavailable provider.
unavailable_provider = self.provider.copy()
payment_utils.add_to_report(report, unavailable_provider, available=False, reason="test")
no_provider_pm = self.payment_method.copy()
no_provider_pm.provider_ids = [Command.set([unavailable_provider.id])]
unavailable_provider.payment_method_ids = [Command.set([no_provider_pm.id])]
# Prepare a payment method with an incompatible country.
invalid_country_pm = self.payment_method.copy()
belgium = self.env.ref('base.be')
invalid_country_pm.supported_country_ids = [Command.set([belgium.id])]
france = self.env.ref('base.fr')
self.partner.country_id = france
# Prepare a payment method with an incompatible currency.
invalid_currency_pm = self.payment_method.copy()
invalid_currency_pm.supported_currency_ids = [Command.set([self.currency_euro.id])]
# Prepare a payment method without support for tokenization.
no_tokenization_pm = self.payment_method.copy()
no_tokenization_pm.support_tokenization = False
# Prepare a payment method without support for express checkout.
no_express_checkout_pm = self.payment_method.copy()
no_express_checkout_pm.support_express_checkout = False
# Get compatible payment methods to generate their availability report.
self.env['payment.method']._get_compatible_payment_methods(
self.provider.ids,
self.partner.id,
currency_id=self.currency_usd.id,
force_tokenization=True,
is_express_checkout=True,
report=report,
)
# Compare the generated payment methods report with the expected one.
expected_pms_report = {
self.payment_method: {
'available': True,
'reason': '',
'supported_providers': [(self.provider, True)],
},
no_provider_pm: {
'available': False,
'reason': REPORT_REASONS_MAPPING['provider_not_available'],
'supported_providers': [(unavailable_provider, False)],
},
invalid_country_pm: {
'available': False,
'reason': REPORT_REASONS_MAPPING['incompatible_country'],
'supported_providers': [(self.provider, True)],
},
invalid_currency_pm: {
'available': False,
'reason': REPORT_REASONS_MAPPING['incompatible_currency'],
'supported_providers': [(self.provider, True)],
},
no_tokenization_pm: {
'available': False,
'reason': REPORT_REASONS_MAPPING['tokenization_not_supported'],
'supported_providers': [(self.provider, True)],
},
no_express_checkout_pm: {
'available': False,
'reason': REPORT_REASONS_MAPPING['express_checkout_not_supported'],
'supported_providers': [(self.provider, True)],
},
}
self.maxDiff = None
self.assertDictEqual(report['payment_methods'], expected_pms_report)