355 lines
17 KiB
Python
355 lines
17 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.const import REPORT_REASONS_MAPPING
|
|
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_availability_report_covers_all_reasons(self):
|
|
""" Test that every possible unavailability reason is correctly reported. """
|
|
# Disable all providers.
|
|
providers = self.env['payment.provider'].search([])
|
|
providers.state = 'disabled'
|
|
|
|
# Prepare a base provider.
|
|
self.provider.write({
|
|
'state': 'test',
|
|
'allow_express_checkout': True,
|
|
'allow_tokenization': True,
|
|
})
|
|
|
|
# Prepare a provider with an incompatible country.
|
|
invalid_country_provider = self.provider.copy()
|
|
belgium = self.env.ref('base.be')
|
|
invalid_country_provider.write({
|
|
'state': 'test',
|
|
'available_country_ids': [Command.set([belgium.id])],
|
|
})
|
|
france = self.env.ref('base.fr')
|
|
self.partner.country_id = france
|
|
|
|
# Prepare a provider with a maximum amount lower than the payment amount.
|
|
exceeding_max_provider = self.provider.copy()
|
|
exceeding_max_provider.write({
|
|
'state': 'test',
|
|
'maximum_amount': self.amount - 10.0,
|
|
})
|
|
|
|
# Prepare a provider with an incompatible currency.
|
|
invalid_currency_provider = self.provider.copy()
|
|
invalid_currency_provider.write({
|
|
'state': 'test',
|
|
'available_currency_ids': [Command.unlink(self.currency_usd.id)],
|
|
})
|
|
|
|
# Prepare a provider without tokenization support.
|
|
no_tokenization_provider = self.provider.copy()
|
|
no_tokenization_provider.write({
|
|
'state': 'test',
|
|
'allow_tokenization': False,
|
|
})
|
|
|
|
# Prepare a provider without express checkout support.
|
|
no_express_checkout_provider = self.provider.copy()
|
|
no_express_checkout_provider.write({
|
|
'state': 'test',
|
|
'allow_express_checkout': False,
|
|
})
|
|
|
|
# Get compatible providers to generate their availability report.
|
|
report = {}
|
|
self.env['payment.provider']._get_compatible_providers(
|
|
self.company_id,
|
|
self.partner.id,
|
|
self.amount,
|
|
currency_id=self.currency_usd.id,
|
|
force_tokenization=True,
|
|
is_express_checkout=True,
|
|
report=report,
|
|
)
|
|
|
|
# Compare the generated providers report with the expected one.
|
|
expected_providers_report = {
|
|
self.provider: {
|
|
'available': True,
|
|
'reason': '',
|
|
},
|
|
invalid_country_provider: {
|
|
'available': False,
|
|
'reason': REPORT_REASONS_MAPPING['incompatible_country'],
|
|
},
|
|
exceeding_max_provider: {
|
|
'available': False,
|
|
'reason': REPORT_REASONS_MAPPING['exceed_max_amount'],
|
|
},
|
|
invalid_currency_provider: {
|
|
'available': False,
|
|
'reason': REPORT_REASONS_MAPPING['incompatible_currency'],
|
|
},
|
|
no_tokenization_provider: {
|
|
'available': False,
|
|
'reason': REPORT_REASONS_MAPPING['tokenization_not_supported'],
|
|
},
|
|
no_express_checkout_provider: {
|
|
'available': False,
|
|
'reason': REPORT_REASONS_MAPPING['express_checkout_not_supported'],
|
|
},
|
|
}
|
|
self.maxDiff = None
|
|
self.assertDictEqual(report['providers'], expected_providers_report)
|
|
|
|
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)
|