diff --git a/addons/payment_ogone/models/payment_transaction.py b/addons/payment_ogone/models/payment_transaction.py index 3f2b39102bb..cb902274350 100644 --- a/addons/payment_ogone/models/payment_transaction.py +++ b/addons/payment_ogone/models/payment_transaction.py @@ -20,7 +20,7 @@ class PaymentTransaction(models.Model): _inherit = 'payment.transaction' @api.model - def _compute_reference(self, provider, prefix=None, **kwargs): + def _compute_reference(self, provider, prefix=None, separator='-', **kwargs): """ Override of payment to ensure that Ogone requirements for references are satisfied. Ogone requirements for references are as follows: @@ -31,12 +31,20 @@ class PaymentTransaction(models.Model): :param str provider: The provider of the acquirer handling the transaction :param str prefix: The custom prefix used to compute the full reference + :param str separator: The custom separator used to separate the prefix from the suffix :return: The unique reference for the transaction :rtype: str """ if provider != 'ogone': return super()._compute_reference(provider, prefix=prefix, **kwargs) + if not prefix: + # If no prefix is provided, it could mean that a module has passed a kwarg intended for + # the `_compute_reference_prefix` method, as it is only called if the prefix is empty. + # We call it manually here because singularizing the prefix would generate a default + # value if it was empty, hence preventing the method from ever being called and the + # transaction from received a reference named after the related document. + prefix = self.sudo()._compute_reference_prefix(provider, separator, **kwargs) or None prefix = payment_utils.singularize_reference_prefix(prefix=prefix, max_length=40) return super()._compute_reference(provider, prefix=prefix, **kwargs) diff --git a/addons/payment_ogone/tests/common.py b/addons/payment_ogone/tests/common.py index 1ab0ac137cd..fcec80c7d10 100644 --- a/addons/payment_ogone/tests/common.py +++ b/addons/payment_ogone/tests/common.py @@ -1,4 +1,5 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. + from odoo.addons.payment.tests.common import PaymentCommon diff --git a/addons/payment_ogone/tests/test_ogone.py b/addons/payment_ogone/tests/test_ogone.py index 05a9bb341f8..79899923bce 100644 --- a/addons/payment_ogone/tests/test_ogone.py +++ b/addons/payment_ogone/tests/test_ogone.py @@ -2,6 +2,7 @@ from freezegun import freeze_time +from odoo.fields import Command from odoo.tests import tagged from odoo.tools import mute_logger @@ -15,32 +16,45 @@ from ..controllers.main import OgoneController class OgoneTest(OgoneCommon): def test_validation_amount(self): + """ Test the value of the validation amount. """ self.assertEqual(self.ogone._get_validation_amount(), 1.0) - # freeze time for consistent singularize_prefix behavior during the test - @freeze_time("2011-11-02 12:00:21") - def test_reference(self): - tx = self.create_transaction(flow="redirect", reference="") - self.assertEqual(tx.reference, "tx-20111102120021", - "Ogone: transaction reference wasn't correctly singularized.") - - # Test prefixes of length > 40 chars - reference = self.env['payment.transaction']._compute_reference( - provider=self.ogone.provider, - prefix="This is a reference of more than 40 characters to annoy ogone", + @freeze_time('2011-11-02 12:00:21') # Freeze time for consistent singularization behavior + def test_reference_is_singularized(self): + """ Test singularization of reference prefixes. """ + reference = self.env['payment.transaction']._compute_reference(self.ogone.provider) + self.assertEqual( + reference, 'tx-20111102120021', "transaction reference was not correctly singularized" ) - self.assertEqual(reference, "This is a reference of mo-20111102120021") + + @freeze_time('2011-11-02 12:00:21') # Freeze time for consistent singularization behavior + def test_reference_is_stripped_at_max_length(self): + """ Test stripping of reference prefixes of length > 40 chars. """ + reference = self.env['payment.transaction']._compute_reference( + self.ogone.provider, + prefix='this is a reference of more than 40 characters to annoy ogone', + ) + self.assertEqual(reference, 'this is a reference of mo-20111102120021') self.assertEqual(len(reference), 40) - # freeze time for consistent singularize_prefix behavior during the test - @freeze_time("2011-11-02 12:00:21") + @freeze_time('2011-11-02 12:00:21') # Freeze time for consistent singularization behavior + def test_reference_is_computed_based_on_document_name(self): + """ Test computation of reference prefixes based on the provided invoice. """ + invoice = self.env['account.move'].create({}) + reference = self.env['payment.transaction']._compute_reference( + self.ogone.provider, invoice_ids=[Command.set([invoice.id])] + ) + self.assertEqual(reference, 'MISC/2011/11/0001-20111102120021') + + @freeze_time('2011-11-02 12:00:21') # Freeze time for consistent singularization behavior def test_redirect_form_values(self): + """ Test the values of the redirect form inputs. """ return_url = self._build_url(OgoneController._flexcheckout_return_url) expected_values = { 'ACCOUNT_PSPID': self.ogone.ogone_pspid, 'ALIAS_ALIASID': payment_utils.singularize_reference_prefix(prefix='ODOO-ALIAS'), 'ALIAS_ORDERID': self.reference, - 'ALIAS_STOREPERMANENTLY': 'N', # 'Y' if self.tokenize + 'ALIAS_STOREPERMANENTLY': 'N', # 'Y' if self.tokenize 'CARD_PAYMENTMETHOD': 'CreditCard', 'LAYOUT_LANGUAGE': self.partner.lang, 'PARAMETERS_ACCEPTURL': return_url, @@ -50,7 +64,7 @@ class OgoneTest(OgoneCommon): expected_values, incoming=False, format_keys=True ).upper() - tx = self.create_transaction(flow="redirect") + tx = self.create_transaction(flow='redirect') with mute_logger('odoo.addons.payment.models.payment_transaction'): processing_values = tx._get_processing_values() @@ -64,7 +78,5 @@ class OgoneTest(OgoneCommon): self.assertEqual( inputs[form_key], value, - "Ogone: received value %s for input %s (expected %s)" % ( - inputs[form_key], form_key, value, - ) + f"received value {inputs[form_key]} for input {form_key} (expected {value})" ) diff --git a/addons/payment_payulatam/models/payment_transaction.py b/addons/payment_payulatam/models/payment_transaction.py index a6d7811ab27..15ea8bb28cd 100644 --- a/addons/payment_payulatam/models/payment_transaction.py +++ b/addons/payment_payulatam/models/payment_transaction.py @@ -34,6 +34,15 @@ class PaymentTransaction(models.Model): :rtype: str """ if provider == 'payulatam': + if not prefix: + # If no prefix is provided, it could mean that a module has passed a kwarg intended + # for the `_compute_reference_prefix` method, as it is only called if the prefix is + # empty. We call it manually here because singularizing the prefix would generate a + # default value if it was empty, hence preventing the method from ever being called + # and the transaction from received a reference named after the related document. + prefix = self.sudo()._compute_reference_prefix( + provider, separator, **kwargs + ) or None prefix = payment_utils.singularize_reference_prefix(prefix=prefix, separator=separator) return super()._compute_reference(provider, prefix=prefix, separator=separator, **kwargs) diff --git a/addons/payment_payulatam/tests/common.py b/addons/payment_payulatam/tests/common.py index 2f5242871bb..b26a2507ad2 100644 --- a/addons/payment_payulatam/tests/common.py +++ b/addons/payment_payulatam/tests/common.py @@ -1,8 +1,9 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. + from odoo.addons.payment.tests.common import PaymentCommon -class PayulatamCommon(PaymentCommon): +class PayULatamCommon(PaymentCommon): @classmethod def setUpClass(cls, chart_template_ref=None): diff --git a/addons/payment_payulatam/tests/test_payulatam.py b/addons/payment_payulatam/tests/test_payulatam.py index 752e10da6ba..1573059af2c 100644 --- a/addons/payment_payulatam/tests/test_payulatam.py +++ b/addons/payment_payulatam/tests/test_payulatam.py @@ -3,42 +3,53 @@ from freezegun import freeze_time from odoo.exceptions import ValidationError +from odoo.fields import Command from odoo.tests import tagged from odoo.tools import mute_logger -from .common import PayulatamCommon +from .common import PayULatamCommon from ..controllers.main import PayuLatamController from ..models.payment_acquirer import SUPPORTED_CURRENCIES @tagged('post_install', '-at_install') -class PayUlatamTest(PayulatamCommon): +class PayULatamTest(PayULatamCommon): - def test_compatible_acquirers(self): - for curr in SUPPORTED_CURRENCIES: - currency = self._prepare_currency(curr) - acquirers = self.env['payment.acquirer']._get_compatible_acquirers( - partner_id=self.partner.id, - company_id=self.company.id, - currency_id=currency.id, + def test_compatibility_with_supported_currencies(self): + """ Test that the PayULatam acquirer is compatible with all supported currencies. """ + for supported_currency_code in SUPPORTED_CURRENCIES: + supported_currency = self._prepare_currency(supported_currency_code) + compatible_acquirers = self.env['payment.acquirer']._get_compatible_acquirers( + self.company.id, self.partner.id, currency_id=supported_currency.id, ) - self.assertIn(self.payulatam, acquirers) + self.assertIn(self.payulatam, compatible_acquirers) - acquirers = self.env['payment.acquirer']._get_compatible_acquirers( - partner_id=self.partner.id, - company_id=self.company.id, - currency_id=self.currency_euro.id, + def test_incompatibility_with_unsupported_currency(self): + """ Test that the PayULatam acquirer is not compatible with an unsupported currency. """ + compatible_acquirers = self.env['payment.acquirer']._get_compatible_acquirers( + self.company.id, self.partner.id, currency_id=self.currency_euro.id, ) - self.assertNotIn(self.payulatam, acquirers) + self.assertNotIn(self.payulatam, compatible_acquirers) - # freeze time for consistent singularize_prefix behavior during the test - @freeze_time("2011-11-02 12:00:21") - def test_reference(self): - tx = self.create_transaction(flow="redirect", reference="") - self.assertEqual(tx.reference, "tx-20111102120021", - "Payulatam: transaction reference wasn't correctly singularized.") + @freeze_time('2011-11-02 12:00:21') # Freeze time for consistent singularization behavior + def test_reference_is_singularized(self): + """ Test singularization of reference prefixes. """ + reference = self.env['payment.transaction']._compute_reference(self.payulatam.provider) + self.assertEqual( + reference, 'tx-20111102120021', "transaction reference was not correctly singularized" + ) + + @freeze_time('2011-11-02 12:00:21') # Freeze time for consistent singularization behavior + def test_reference_is_computed_based_on_document_name(self): + """ Test computation of reference prefixes based on the provided invoice. """ + invoice = self.env['account.move'].create({}) + reference = self.env['payment.transaction']._compute_reference( + self.payulatam.provider, invoice_ids=[Command.set([invoice.id])] + ) + self.assertEqual(reference, 'MISC/2011/11/0001-20111102120021') def test_redirect_form_values(self): + """ Test the values of the redirect form inputs. """ tx = self.create_transaction(flow='redirect') with mute_logger('odoo.addons.payment.models.payment_transaction'): processing_values = tx._get_processing_values() @@ -56,13 +67,15 @@ class PayUlatamTest(PayulatamCommon): 'buyerEmail': self.partner.email, 'buyerFullName': self.partner.name, 'responseUrl': self._build_url(PayuLatamController._return_url), - 'test': str(1), # test is always done in test mode. + 'test': str(1), # testing is always performed in test mode } expected_values['signature'] = self.payulatam._payulatam_generate_sign( - expected_values, incoming=False) + expected_values, incoming=False + ) - self.assertEqual(form_info['action'], - 'https://sandbox.checkout.payulatam.com/ppp-web-gateway-payu/') + self.assertEqual( + form_info['action'], 'https://sandbox.checkout.payulatam.com/ppp-web-gateway-payu/' + ) self.assertDictEqual(form_info['inputs'], expected_values) def test_feedback_processing(self):