Files
odoo_source/addons/payment/tests/test_payment_provider.py
T
Antoine Vandevenne (anv) d6d5f142c3 [FIX] payment(_stripe): adapt validation currency to payment method
When payment details are tokenized through a validation operation, the
currency to use was usually (except overrides) chosen as that of the
payment provider's company. This sometimes caused compatibility issues
if the selected payment method did not support the company's main
currency. For example, the SEPA Direct Debit payment method only
supports the EUR currency.

This commit allows passing a payment method when getting the validation
currency so that only supported currencies can be returned.

Part-of: odoo/odoo#161883
2024-04-17 22:47:13 +00:00

261 lines
13 KiB
Python

# Part of Odoo. See LICENSE file for full copyright and licensing details.
from unittest.mock import patch
from odoo import Command
from odoo.tests import tagged
from odoo.addons.payment.tests.common import PaymentCommon
@tagged('-at_install', 'post_install')
class TestPaymentProvider(PaymentCommon):
def test_changing_provider_state_archives_tokens(self):
""" Test that all active tokens of a provider are archived when its state is changed. """
for old_state in ('enabled', 'test'): # No need to check when the provided was disabled.
for new_state in ('enabled', 'test', 'disabled'):
if old_state != new_state: # No need to check when the state is unchanged.
self.provider.state = old_state
token = self._create_token()
self.provider.state = new_state
self.assertFalse(token.active)
def test_enabling_provider_activates_default_payment_methods(self):
""" Test that the default payment methods of a provider are activated when it is
enabled. """
self.payment_methods.active = False
for new_state in ('enabled', 'test'):
self.provider.state = 'disabled'
with patch(
'odoo.addons.payment.models.payment_provider.PaymentProvider'
'._get_default_payment_method_codes', return_value=self.payment_method_code,
):
self.provider.state = new_state
self.assertTrue(self.payment_methods.active)
def test_disabling_provider_deactivates_default_payment_methods(self):
""" Test that the default payment methods of a provider are deactivated when it is
disabled. """
self.payment_methods.active = True
for old_state in ('enabled', 'test'):
self.provider.state = old_state
with patch(
'odoo.addons.payment.models.payment_provider.PaymentProvider'
'._get_default_payment_method_codes', return_value=self.payment_method_code,
):
self.provider.state = 'disabled'
self.assertFalse(self.payment_methods.active)
def test_published_provider_compatible_with_all_users(self):
""" Test that a published provider is always available to all users. """
for user in (self.public_user, self.portal_user):
self.env = self.env(user=user)
compatible_providers = self.env['payment.provider'].sudo()._get_compatible_providers(
self.company.id, self.partner.id, self.amount
)
self.assertIn(self.provider, compatible_providers)
def test_unpublished_provider_compatible_with_internal_user(self):
""" Test that an unpublished provider is still available to internal users. """
self.provider.is_published = False
compatible_providers = self.env['payment.provider']._get_compatible_providers(
self.company.id, self.partner.id, self.amount
)
self.assertIn(self.provider, compatible_providers)
def test_unpublished_provider_not_compatible_with_non_internal_user(self):
""" Test that an unpublished provider is not available to non-internal users. """
self.provider.is_published = False
for user in (self.public_user, self.portal_user):
self.env = self.env(user=user)
compatible_providers = self.env['payment.provider'].sudo()._get_compatible_providers(
self.company.id, self.partner.id, self.amount
)
self.assertNotIn(self.provider, compatible_providers)
def test_provider_compatible_with_available_countries(self):
""" Test that the provider is compatible with its available countries. """
belgium = self.env.ref('base.be')
self.provider.available_country_ids = [Command.set([belgium.id])]
self.partner.country_id = belgium
compatible_providers = self.provider._get_compatible_providers(
self.company.id, self.partner.id, self.amount
)
self.assertIn(self.provider, compatible_providers)
def test_provider_not_compatible_with_unavailable_countries(self):
""" Test that the provider is not compatible with a country that is not available. """
belgium = self.env.ref('base.be')
self.provider.available_country_ids = [Command.set([belgium.id])]
france = self.env.ref('base.fr')
self.partner.country_id = france
compatible_providers = self.provider._get_compatible_providers(
self.company.id, self.partner.id, self.amount
)
self.assertNotIn(self.provider, compatible_providers)
def test_provider_compatible_when_no_available_countries_set(self):
""" Test that the provider is always compatible when no available countries are set. """
self.provider.available_country_ids = [Command.clear()]
belgium = self.env.ref('base.be')
self.partner.country_id = belgium
compatible_providers = self.provider._get_compatible_providers(
self.company.id, self.partner.id, self.amount
)
self.assertIn(self.provider, compatible_providers)
def test_provider_compatible_when_maximum_amount_is_zero(self):
""" Test that the maximum amount has no effect on the provider's compatibility when it is
set to 0. """
self.provider.maximum_amount = 0.
currency = self.provider.main_currency_id.id
compatible_providers = self.env['payment.provider']._get_compatible_providers(
self.company.id, self.partner.id, self.amount, currency_id=currency
)
self.assertIn(self.provider, compatible_providers)
def test_provider_compatible_when_payment_below_maximum_amount(self):
""" Test that a provider is compatible when the payment amount is less than the maximum
amount. """
self.provider.maximum_amount = self.amount + 10.0
currency = self.provider.main_currency_id.id
compatible_providers = self.env['payment.provider']._get_compatible_providers(
self.company.id, self.partner.id, self.amount, currency_id=currency
)
self.assertIn(self.provider, compatible_providers)
def test_provider_not_compatible_when_payment_above_maximum_amount(self):
""" Test that a provider is not compatible when the payment amount is more than the maximum
amount. """
self.provider.maximum_amount = self.amount - 10.0
currency = self.provider.main_currency_id.id
compatible_providers = self.env['payment.provider']._get_compatible_providers(
self.company.id, self.partner.id, self.amount, currency_id=currency
)
self.assertNotIn(self.provider, compatible_providers)
def test_provider_compatible_with_available_currencies(self):
""" Test that the provider is compatible with its available currencies. """
compatible_providers = self.provider._get_compatible_providers(
self.company.id, self.partner.id, self.amount, currency_id=self.currency_euro.id
)
self.assertIn(self.provider, compatible_providers)
def test_provider_not_compatible_with_unavailable_currencies(self):
""" Test that the provider is not compatible with a currency that is not available. """
# Make sure the list of available currencies is not empty.
self.provider.available_currency_ids = [Command.unlink(self.currency_usd.id)]
compatible_providers = self.provider._get_compatible_providers(
self.company.id, self.partner.id, self.amount, currency_id=self.currency_usd.id
)
self.assertNotIn(self.provider, compatible_providers)
def test_provider_compatible_when_no_available_currencies_set(self):
""" Test that the provider is always compatible when no available currency is set. """
self.provider.available_currency_ids = [Command.clear()]
compatible_providers = self.provider._get_compatible_providers(
self.company.id, self.partner.id, self.amount, currency_id=self.currency_euro.id
)
self.assertIn(self.provider, compatible_providers)
def test_provider_compatible_when_tokenization_forced(self):
""" Test that the provider is compatible when it allows tokenization while it is forced by
the calling module. """
self.provider.allow_tokenization = True
compatible_providers = self.provider._get_compatible_providers(
self.company.id, self.partner.id, self.amount, force_tokenization=True
)
self.assertIn(self.provider, compatible_providers)
def test_provider_not_compatible_when_tokenization_forced(self):
""" Test that the provider is not compatible when it does not allow tokenization while it
is forced by the calling module. """
self.provider.allow_tokenization = False
compatible_providers = self.provider._get_compatible_providers(
self.company.id, self.partner.id, self.amount, force_tokenization=True
)
self.assertNotIn(self.provider, compatible_providers)
def test_provider_compatible_when_tokenization_required(self):
""" Test that the provider is compatible when it allows tokenization while it is required by
the payment context (e.g., when paying for a subscription). """
self.provider.allow_tokenization = True
with patch(
'odoo.addons.payment.models.payment_provider.PaymentProvider._is_tokenization_required',
return_value=True,
):
compatible_providers = self.provider._get_compatible_providers(
self.company.id, self.partner.id, self.amount
)
self.assertIn(self.provider, compatible_providers)
def test_provider_not_compatible_when_tokenization_required(self):
""" Test that the provider is not compatible when it does not allow tokenization while it
is required by the payment context (e.g., when paying for a subscription). """
self.provider.allow_tokenization = False
with patch(
'odoo.addons.payment.models.payment_provider.PaymentProvider._is_tokenization_required',
return_value=True,
):
compatible_providers = self.provider._get_compatible_providers(
self.company.id, self.partner.id, self.amount
)
self.assertNotIn(self.provider, compatible_providers)
def test_provider_compatible_with_express_checkout(self):
""" Test that the provider is compatible when it allows express checkout while it is an
express checkout flow. """
self.provider.allow_express_checkout = True
compatible_providers = self.provider._get_compatible_providers(
self.company.id, self.partner.id, self.amount, is_express_checkout=True
)
self.assertIn(self.provider, compatible_providers)
def test_provider_not_compatible_with_express_checkout(self):
""" Test that the provider is not compatible when it does not allow express checkout while
it is an express checkout flow. """
self.provider.allow_express_checkout = False
compatible_providers = self.provider._get_compatible_providers(
self.company.id, self.partner.id, self.amount, is_express_checkout=True
)
self.assertNotIn(self.provider, compatible_providers)
def test_validation_currency_is_supported(self):
""" Test that only currencies supported by both the provider and the payment method can be
used in validation operations. """
self.provider.available_currency_ids = [Command.clear()] # Supports all currencies.
self.payment_method.supported_currency_ids = [Command.clear()] # Supports all currencies.
validation_currency = self.provider.with_context(
validation_pm=self.payment_method
)._get_validation_currency()
self.assertEqual(validation_currency, self.provider.company_id.currency_id)
self.provider.available_currency_ids = [Command.set(self.currency_usd.ids)]
self.payment_method.supported_currency_ids = [Command.clear()] # Supports all currencies.
validation_currency = self.provider.with_context(
validation_pm=self.payment_method
)._get_validation_currency()
self.assertIn(validation_currency, self.provider.available_currency_ids)
self.provider.available_currency_ids = [Command.clear()] # Supports all currencies.
self.payment_method.supported_currency_ids = [Command.set(self.currency_usd.ids)]
validation_currency = self.provider.with_context(
validation_pm=self.payment_method
)._get_validation_currency()
self.assertIn(validation_currency, self.payment_method.supported_currency_ids)
self.provider.available_currency_ids = [Command.set(self.currency_usd.ids)]
self.payment_method.supported_currency_ids = [Command.set(self.currency_usd.ids)]
validation_currency = self.provider.with_context(
validation_pm=self.payment_method
)._get_validation_currency()
self.assertIn(validation_currency, self.provider.available_currency_ids)
self.assertIn(validation_currency, self.payment_method.supported_currency_ids)