[IMP] payment(_*): show available currencies for payment providers
Before this commit, the lists of supported currencies by payment provider were hard-coded in the Python scripts, which made them unavailable to the users. With this commit, the implemented initial lists of supported currencies are displayed on the form view and are editable, because Odoo lists may not be up-to-date. Empty lists do not trigger any filtering on the payment providers to access payment methods. For Authorize.net and Asiapay payment providers, the specific `(authorize,asiapay)_currency_id` are removed and the generic payment provider field `available_currency_ids` is restricted to a single-item list when one of those providers is enabled. task-2926016 closes odoo/odoo#101018 Related: odoo/enterprise#34158 Related: odoo/documentation#2788 Related: odoo/upgrade#4069 Signed-off-by: Antoine Vandevenne (anv) <anv@odoo.com>
This commit is contained in:
@@ -3,7 +3,7 @@
|
|||||||
from odoo import api, fields, models
|
from odoo import api, fields, models
|
||||||
|
|
||||||
|
|
||||||
class Paymentprovider(models.Model):
|
class PaymentProvider(models.Model):
|
||||||
_inherit = 'payment.provider'
|
_inherit = 'payment.provider'
|
||||||
|
|
||||||
journal_id = fields.Many2one(
|
journal_id = fields.Many2one(
|
||||||
|
|||||||
@@ -102,6 +102,19 @@ class PaymentProvider(models.Model):
|
|||||||
column1='payment_id',
|
column1='payment_id',
|
||||||
column2='country_id',
|
column2='country_id',
|
||||||
)
|
)
|
||||||
|
available_currency_ids = fields.Many2many(
|
||||||
|
string="Currencies",
|
||||||
|
help="The currencies available with this payment provider. Leave empty not to restrict "
|
||||||
|
"any.",
|
||||||
|
comodel_name='res.currency',
|
||||||
|
relation='payment_currency_rel',
|
||||||
|
column1="payment_provider_id",
|
||||||
|
column2="currency_id",
|
||||||
|
compute='_compute_available_currency_ids',
|
||||||
|
store=True,
|
||||||
|
readonly=False,
|
||||||
|
context={'active_test': False},
|
||||||
|
)
|
||||||
maximum_amount = fields.Monetary(
|
maximum_amount = fields.Monetary(
|
||||||
string="Maximum Amount",
|
string="Maximum Amount",
|
||||||
help="The maximum payment amount that this payment provider is available for. Leave blank "
|
help="The maximum payment amount that this payment provider is available for. Leave blank "
|
||||||
@@ -190,6 +203,22 @@ class PaymentProvider(models.Model):
|
|||||||
|
|
||||||
#=== COMPUTE METHODS ===#
|
#=== COMPUTE METHODS ===#
|
||||||
|
|
||||||
|
@api.depends('code')
|
||||||
|
def _compute_available_currency_ids(self):
|
||||||
|
""" Compute the available currencies based on their support by the providers.
|
||||||
|
|
||||||
|
If the provider does not filter out any currency, the field is left empty for UX reasons.
|
||||||
|
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
all_currencies = self.env['res.currency'].with_context(active_test=False).search([])
|
||||||
|
for provider in self:
|
||||||
|
supported_currencies = provider._get_supported_currencies()
|
||||||
|
if supported_currencies < all_currencies: # Some currencies have been filtered out.
|
||||||
|
provider.available_currency_ids = supported_currencies
|
||||||
|
else:
|
||||||
|
provider.available_currency_ids = None
|
||||||
|
|
||||||
@api.depends('state', 'module_state')
|
@api.depends('state', 'module_state')
|
||||||
def _compute_color(self):
|
def _compute_color(self):
|
||||||
""" Update the color of the kanban card based on the state of the provider.
|
""" Update the color of the kanban card based on the state of the provider.
|
||||||
@@ -242,6 +271,7 @@ class PaymentProvider(models.Model):
|
|||||||
'show_cancel_msg': True,
|
'show_cancel_msg': True,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@api.depends('code')
|
||||||
def _compute_feature_support_fields(self):
|
def _compute_feature_support_fields(self):
|
||||||
""" Compute the feature support fields based on the provider.
|
""" Compute the feature support fields based on the provider.
|
||||||
|
|
||||||
@@ -415,8 +445,8 @@ class PaymentProvider(models.Model):
|
|||||||
""" Select and return the providers matching the criteria.
|
""" Select and return the providers matching the criteria.
|
||||||
|
|
||||||
The criteria are that providers must not be disabled, be in the company that is provided,
|
The criteria are that providers must not be disabled, be in the company that is provided,
|
||||||
and support the country of the partner if it exists. The criteria can be further refined
|
support the country of the partner if it exists, and be compatible with the currency if
|
||||||
by providing the keyword arguments.
|
provided. The criteria can be further refined by providing the keyword arguments.
|
||||||
|
|
||||||
:param int company_id: The company to which providers must belong, as a `res.company` id.
|
:param int company_id: The company to which providers must belong, as a `res.company` id.
|
||||||
:param int partner_id: The partner making the payment, as a `res.partner` id.
|
:param int partner_id: The partner making the payment, as a `res.partner` id.
|
||||||
@@ -462,6 +492,16 @@ class PaymentProvider(models.Model):
|
|||||||
]
|
]
|
||||||
])
|
])
|
||||||
|
|
||||||
|
# Handle the available currencies (only if supported currencies list is not empty).
|
||||||
|
if currency:
|
||||||
|
domain = expression.AND([
|
||||||
|
domain, [
|
||||||
|
'|',
|
||||||
|
('available_currency_ids', '=', False),
|
||||||
|
('available_currency_ids', 'in', [currency.id]),
|
||||||
|
]
|
||||||
|
])
|
||||||
|
|
||||||
# Handle tokenization support requirements.
|
# Handle tokenization support requirements.
|
||||||
if force_tokenization or self._is_tokenization_required(**kwargs):
|
if force_tokenization or self._is_tokenization_required(**kwargs):
|
||||||
domain = expression.AND([domain, [('allow_tokenization', '=', True)]])
|
domain = expression.AND([domain, [('allow_tokenization', '=', True)]])
|
||||||
@@ -473,6 +513,21 @@ class PaymentProvider(models.Model):
|
|||||||
compatible_providers = self.env['payment.provider'].search(domain)
|
compatible_providers = self.env['payment.provider'].search(domain)
|
||||||
return compatible_providers
|
return compatible_providers
|
||||||
|
|
||||||
|
def _get_supported_currencies(self):
|
||||||
|
""" Return the supported currencies for the payment provider.
|
||||||
|
|
||||||
|
By default, all currencies are considered supported, including the inactive ones. For a
|
||||||
|
provider to filter out specific currencies, it must override this method and return the
|
||||||
|
subset of supported currencies.
|
||||||
|
|
||||||
|
Note: `self.ensure_one()`
|
||||||
|
|
||||||
|
:return: The supported currencies.
|
||||||
|
:rtype: res.currency
|
||||||
|
"""
|
||||||
|
self.ensure_one()
|
||||||
|
return self.env['res.currency'].with_context(active_test=False).search([])
|
||||||
|
|
||||||
def _is_tokenization_required(self, **kwargs):
|
def _is_tokenization_required(self, **kwargs):
|
||||||
""" Return whether tokenizing the transaction is required given its context.
|
""" Return whether tokenizing the transaction is required given its context.
|
||||||
|
|
||||||
|
|||||||
@@ -79,6 +79,7 @@ class PaymentCommon(BaseCommon):
|
|||||||
'is_published': True,
|
'is_published': True,
|
||||||
'allow_tokenization': True,
|
'allow_tokenization': True,
|
||||||
'redirect_form_view_id': redirect_form.id,
|
'redirect_form_view_id': redirect_form.id,
|
||||||
|
'available_currency_ids': [Command.set((cls.currency_euro + cls.currency_usd).ids)],
|
||||||
})
|
})
|
||||||
|
|
||||||
cls.provider = cls.dummy_provider
|
cls.provider = cls.dummy_provider
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
from odoo import Command
|
||||||
from odoo.tests import tagged
|
from odoo.tests import tagged
|
||||||
|
|
||||||
from odoo.addons.payment.tests.common import PaymentCommon
|
from odoo.addons.payment.tests.common import PaymentCommon
|
||||||
@@ -70,6 +71,30 @@ class TestPaymentProvider(PaymentCommon):
|
|||||||
)
|
)
|
||||||
self.assertNotIn(self.provider, compatible_providers)
|
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_currency_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_fees_null_when_deactivated(self):
|
def test_fees_null_when_deactivated(self):
|
||||||
""" Test that extra fees of a provider are null if these fees are deactivated. """
|
""" Test that extra fees of a provider are null if these fees are deactivated. """
|
||||||
self.provider.write({
|
self.provider.write({
|
||||||
|
|||||||
@@ -84,10 +84,19 @@
|
|||||||
</group>
|
</group>
|
||||||
<group string="Availability" name="availability">
|
<group string="Availability" name="availability">
|
||||||
<field name="maximum_amount"/>
|
<field name="maximum_amount"/>
|
||||||
|
<label for="available_currency_ids"/>
|
||||||
|
<!-- Use `o_row` to allow placing a button next to the field in overrides. -->
|
||||||
|
<div name="available_currencies" class="o_row">
|
||||||
|
<field name="available_currency_ids"
|
||||||
|
widget="many2many_tags"
|
||||||
|
placeholder="Select currencies. Leave empty not to restrict any."
|
||||||
|
context="{'active_test': False}"
|
||||||
|
options="{'no_create': True}"/>
|
||||||
|
</div>
|
||||||
<field name="available_country_ids"
|
<field name="available_country_ids"
|
||||||
widget="many2many_tags"
|
widget="many2many_tags"
|
||||||
placeholder="Select countries. Leave empty to make available everywhere."
|
placeholder="Select countries. Leave empty to make available everywhere."
|
||||||
options="{'no_open': True, 'no_create': True}"/>
|
options="{'no_create': True}"/>
|
||||||
</group>
|
</group>
|
||||||
<group string="Payment Followup" name="payment_followup" invisible="1"/>
|
<group string="Payment Followup" name="payment_followup" invisible="1"/>
|
||||||
</group>
|
</group>
|
||||||
|
|||||||
@@ -41,7 +41,8 @@ class PaymentProvider(models.Model):
|
|||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def _get_compatible_providers(self, *args, currency_id=None, **kwargs):
|
def _get_compatible_providers(self, *args, currency_id=None, **kwargs):
|
||||||
""" Override of payment to unlist Alipay providers for unsupported currencies. """
|
""" Override of payment to unlist Alipay providers when the currency is not CNY in case of
|
||||||
|
express checkout. """
|
||||||
providers = super()._get_compatible_providers(*args, currency_id=currency_id, **kwargs)
|
providers = super()._get_compatible_providers(*args, currency_id=currency_id, **kwargs)
|
||||||
|
|
||||||
currency = self.env['res.currency'].browse(currency_id).exists()
|
currency = self.env['res.currency'].browse(currency_id).exists()
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
-- disable asiapay payment provider
|
-- disable asiapay payment provider
|
||||||
UPDATE payment_provider
|
UPDATE payment_provider
|
||||||
SET asiapay_merchant_id = NULL,
|
SET asiapay_merchant_id = NULL,
|
||||||
asiapay_currency_id = NULL,
|
|
||||||
asiapay_secure_hash_secret = NULL,
|
asiapay_secure_hash_secret = NULL,
|
||||||
asiapay_secure_hash_function = NULL;
|
asiapay_secure_hash_function = NULL;
|
||||||
|
|||||||
@@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
from hashlib import new as hashnew
|
from hashlib import new as hashnew
|
||||||
|
|
||||||
from odoo import api, fields, models
|
from odoo import _, api, fields, models
|
||||||
|
from odoo.exceptions import ValidationError
|
||||||
|
|
||||||
from odoo.addons.payment_asiapay import const
|
from odoo.addons.payment_asiapay import const
|
||||||
|
|
||||||
@@ -10,10 +11,6 @@ from odoo.addons.payment_asiapay import const
|
|||||||
class PaymentProvider(models.Model):
|
class PaymentProvider(models.Model):
|
||||||
_inherit = 'payment.provider'
|
_inherit = 'payment.provider'
|
||||||
|
|
||||||
def _domain_asiapay_currency_id(self):
|
|
||||||
currency_xmlids = [f'base.{key}' for key in const.CURRENCY_MAPPING]
|
|
||||||
return [('id', 'in', [self.env.ref(xmlid).id for xmlid in currency_xmlids])]
|
|
||||||
|
|
||||||
code = fields.Selection(
|
code = fields.Selection(
|
||||||
selection_add=[('asiapay', "AsiaPay")], ondelete={'asiapay': 'set default'}
|
selection_add=[('asiapay', "AsiaPay")], ondelete={'asiapay': 'set default'}
|
||||||
)
|
)
|
||||||
@@ -22,13 +19,6 @@ class PaymentProvider(models.Model):
|
|||||||
help="The Merchant ID solely used to identify your AsiaPay account.",
|
help="The Merchant ID solely used to identify your AsiaPay account.",
|
||||||
required_if_provider='asiapay',
|
required_if_provider='asiapay',
|
||||||
)
|
)
|
||||||
asiapay_currency_id = fields.Many2one(
|
|
||||||
string="AsiaPay Currency",
|
|
||||||
help="The currency associated to your AsiaPay account.",
|
|
||||||
comodel_name='res.currency',
|
|
||||||
domain=_domain_asiapay_currency_id,
|
|
||||||
required_if_provider='asiapay',
|
|
||||||
)
|
|
||||||
asiapay_secure_hash_secret = fields.Char(
|
asiapay_secure_hash_secret = fields.Char(
|
||||||
string="AsiaPay Secure Hash Secret",
|
string="AsiaPay Secure Hash Secret",
|
||||||
required_if_provider='asiapay',
|
required_if_provider='asiapay',
|
||||||
@@ -42,21 +32,16 @@ class PaymentProvider(models.Model):
|
|||||||
required_if_provider='asiapay',
|
required_if_provider='asiapay',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# ==== CONSTRAINT METHODS ===#
|
||||||
|
|
||||||
|
@api.constrains('available_currency_ids', 'state')
|
||||||
|
def _limit_available_currency_ids(self):
|
||||||
|
for provider in self.filtered(lambda p: p.code == 'asiapay'):
|
||||||
|
if len(provider.available_currency_ids) > 1 and provider.state != 'disabled':
|
||||||
|
raise ValidationError(_("Only one currency can be selected by AsiaPay account."))
|
||||||
|
|
||||||
# === BUSINESS METHODS ===#
|
# === BUSINESS METHODS ===#
|
||||||
|
|
||||||
@api.model
|
|
||||||
def _get_compatible_providers(self, *args, currency_id=None, **kwargs):
|
|
||||||
""" Override of `payment` to filter out AsiaPay providers for unsupported currencies. """
|
|
||||||
providers = super()._get_compatible_providers(*args, currency_id=currency_id, **kwargs)
|
|
||||||
|
|
||||||
currency = self.env['res.currency'].browse(currency_id).exists()
|
|
||||||
if currency:
|
|
||||||
providers = providers.filtered(
|
|
||||||
lambda p: p.code != 'asiapay' or currency == p.asiapay_currency_id
|
|
||||||
)
|
|
||||||
|
|
||||||
return providers
|
|
||||||
|
|
||||||
def _asiapay_get_api_url(self):
|
def _asiapay_get_api_url(self):
|
||||||
""" Return the URL of the API corresponding to the provider's state.
|
""" Return the URL of the API corresponding to the provider's state.
|
||||||
|
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ class PaymentTransaction(models.Model):
|
|||||||
'merchant_id': self.provider_id.asiapay_merchant_id,
|
'merchant_id': self.provider_id.asiapay_merchant_id,
|
||||||
'amount': self.amount,
|
'amount': self.amount,
|
||||||
'reference': self.reference,
|
'reference': self.reference,
|
||||||
'currency_code': const.CURRENCY_MAPPING[self.provider_id.asiapay_currency_id.name],
|
'currency_code': const.CURRENCY_MAPPING[self.provider_id.available_currency_ids[0].name],
|
||||||
'mps_mode': 'SCP',
|
'mps_mode': 'SCP',
|
||||||
'return_url': urls.url_join(base_url, AsiaPayController._return_url),
|
'return_url': urls.url_join(base_url, AsiaPayController._return_url),
|
||||||
'payment_type': 'N',
|
'payment_type': 'N',
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||||
|
|
||||||
|
from odoo import Command
|
||||||
|
|
||||||
from odoo.addons.payment.tests.common import PaymentCommon
|
from odoo.addons.payment.tests.common import PaymentCommon
|
||||||
|
|
||||||
|
|
||||||
@@ -11,9 +13,9 @@ class AsiaPayCommon(PaymentCommon):
|
|||||||
|
|
||||||
cls.asiapay = cls._prepare_provider('asiapay', update_values={
|
cls.asiapay = cls._prepare_provider('asiapay', update_values={
|
||||||
'asiapay_merchant_id': '123456789',
|
'asiapay_merchant_id': '123456789',
|
||||||
'asiapay_currency_id': cls.currency_euro,
|
|
||||||
'asiapay_secure_hash_secret': 'coincoin_motherducker',
|
'asiapay_secure_hash_secret': 'coincoin_motherducker',
|
||||||
'asiapay_secure_hash_function': 'sha1',
|
'asiapay_secure_hash_function': 'sha1',
|
||||||
|
'available_currency_ids': [Command.set(cls.currency_euro.ids)],
|
||||||
})
|
})
|
||||||
|
|
||||||
cls.provider = cls.asiapay
|
cls.provider = cls.asiapay
|
||||||
|
|||||||
@@ -11,9 +11,6 @@
|
|||||||
<field name="asiapay_merchant_id"
|
<field name="asiapay_merchant_id"
|
||||||
string="Merchant ID"
|
string="Merchant ID"
|
||||||
attrs="{'required': [('code', '=', 'asiapay'), ('state', '!=', 'disabled')]}"/>
|
attrs="{'required': [('code', '=', 'asiapay'), ('state', '!=', 'disabled')]}"/>
|
||||||
<field name="asiapay_currency_id"
|
|
||||||
string="Currency"
|
|
||||||
attrs="{'required': [('code', '=', 'asiapay'), ('state', '!=', 'disabled')]}"/>
|
|
||||||
<field name="asiapay_secure_hash_secret"
|
<field name="asiapay_secure_hash_secret"
|
||||||
string="Secure Hash Secret"
|
string="Secure Hash Secret"
|
||||||
attrs="{'required': [('code', '=', 'asiapay'), ('state', '!=', 'disabled')]}"
|
attrs="{'required': [('code', '=', 'asiapay'), ('state', '!=', 'disabled')]}"
|
||||||
@@ -24,6 +21,9 @@
|
|||||||
groups="base.group_no_one"/>
|
groups="base.group_no_one"/>
|
||||||
</group>
|
</group>
|
||||||
</group>
|
</group>
|
||||||
|
<field name="available_currency_ids" position="attributes">
|
||||||
|
<attribute name="attrs">{'required': [('code', '=', 'asiapay'), ('state', '!=', 'disabled')]}</attribute>
|
||||||
|
</field>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
|||||||
@@ -27,10 +27,6 @@ class PaymentProvider(models.Model):
|
|||||||
authorize_client_key = fields.Char(
|
authorize_client_key = fields.Char(
|
||||||
string="API Client Key",
|
string="API Client Key",
|
||||||
help="The public client key. To generate directly from Odoo or from Authorize.Net backend.")
|
help="The public client key. To generate directly from Odoo or from Authorize.Net backend.")
|
||||||
# Authorize.Net supports only one currency: "One gateway account is required for each currency"
|
|
||||||
# See https://community.developer.authorize.net/t5/The-Authorize-Net-Developer-Blog/Authorize-Net-UK-Europe-Update/ba-p/35957
|
|
||||||
authorize_currency_id = fields.Many2one(
|
|
||||||
string="Authorize Currency", comodel_name='res.currency')
|
|
||||||
authorize_payment_method_type = fields.Selection(
|
authorize_payment_method_type = fields.Selection(
|
||||||
string="Allow Payments From",
|
string="Allow Payments From",
|
||||||
help="Determines with what payment method the customer can pay.",
|
help="Determines with what payment method the customer can pay.",
|
||||||
@@ -51,6 +47,16 @@ class PaymentProvider(models.Model):
|
|||||||
"method type on the duplicated provider."
|
"method type on the duplicated provider."
|
||||||
))
|
))
|
||||||
|
|
||||||
|
# Authorize.Net supports only one currency: "One gateway account is required for each currency"
|
||||||
|
# See https://community.developer.authorize.net/t5/The-Authorize-Net-Developer-Blog/Authorize-Net-UK-Europe-Update/ba-p/35957
|
||||||
|
@api.constrains('available_currency_ids', 'state')
|
||||||
|
def _limit_available_currency_ids(self):
|
||||||
|
for provider in self.filtered(lambda p: p.code == 'authorize'):
|
||||||
|
if len(provider.available_currency_ids) > 1 and provider.state != 'disabled':
|
||||||
|
raise ValidationError(
|
||||||
|
_("Only one currency can be selected by Authorize.Net account.")
|
||||||
|
)
|
||||||
|
|
||||||
#=== COMPUTE METHODS ===#
|
#=== COMPUTE METHODS ===#
|
||||||
|
|
||||||
def _compute_feature_support_fields(self):
|
def _compute_feature_support_fields(self):
|
||||||
@@ -104,24 +110,11 @@ class PaymentProvider(models.Model):
|
|||||||
raise UserError(_("Could not fetch merchant details:\n%s", res_content['err_msg']))
|
raise UserError(_("Could not fetch merchant details:\n%s", res_content['err_msg']))
|
||||||
|
|
||||||
currency = self.env['res.currency'].search([('name', 'in', res_content.get('currencies'))])
|
currency = self.env['res.currency'].search([('name', 'in', res_content.get('currencies'))])
|
||||||
self.authorize_currency_id = currency
|
self.available_currency_ids = [Command.set(currency.ids)]
|
||||||
self.authorize_client_key = res_content.get('publicClientKey')
|
self.authorize_client_key = res_content.get('publicClientKey')
|
||||||
|
|
||||||
# === BUSINESS METHODS ===#
|
# === BUSINESS METHODS ===#
|
||||||
|
|
||||||
@api.model
|
|
||||||
def _get_compatible_providers(self, *args, currency_id=None, **kwargs):
|
|
||||||
""" Override of payment to unlist Authorize providers for unsupported currencies. """
|
|
||||||
providers = super()._get_compatible_providers(*args, currency_id=currency_id, **kwargs)
|
|
||||||
|
|
||||||
currency = self.env['res.currency'].browse(currency_id).exists()
|
|
||||||
if currency:
|
|
||||||
providers = providers.filtered(
|
|
||||||
lambda p: p.code != 'authorize' or currency == p.authorize_currency_id
|
|
||||||
)
|
|
||||||
|
|
||||||
return providers
|
|
||||||
|
|
||||||
def _get_validation_amount(self):
|
def _get_validation_amount(self):
|
||||||
""" Override of payment to return the amount for Authorize.Net validation operations.
|
""" Override of payment to return the amount for Authorize.Net validation operations.
|
||||||
|
|
||||||
@@ -144,4 +137,4 @@ class PaymentProvider(models.Model):
|
|||||||
if self.code != 'authorize':
|
if self.code != 'authorize':
|
||||||
return res
|
return res
|
||||||
|
|
||||||
return self.authorize_currency_id
|
return self.available_currency_ids[0]
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||||
|
|
||||||
|
from odoo.fields import Command
|
||||||
|
|
||||||
from odoo.addons.payment.tests.common import PaymentCommon
|
from odoo.addons.payment.tests.common import PaymentCommon
|
||||||
|
|
||||||
|
|
||||||
@@ -13,7 +15,7 @@ class AuthorizeCommon(PaymentCommon):
|
|||||||
'authorize_login': 'dummy',
|
'authorize_login': 'dummy',
|
||||||
'authorize_transaction_key': 'dummy',
|
'authorize_transaction_key': 'dummy',
|
||||||
'authorize_signature_key': '00000000',
|
'authorize_signature_key': '00000000',
|
||||||
'authorize_currency_id': cls.currency_usd.id,
|
'available_currency_ids': [Command.set(cls.currency_usd.ids)]
|
||||||
})
|
})
|
||||||
|
|
||||||
cls.provider = cls.authorize
|
cls.provider = cls.authorize
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ from .common import AuthorizeCommon
|
|||||||
class AuthorizeTest(AuthorizeCommon):
|
class AuthorizeTest(AuthorizeCommon):
|
||||||
|
|
||||||
def test_compatible_providers(self):
|
def test_compatible_providers(self):
|
||||||
# Note: in the test common, 'USD' is specified as authorize_currency_id
|
# Note: in the test common, 'USD' is specified as the currency linked to the user account.
|
||||||
unsupported_currency = self._prepare_currency('CHF')
|
unsupported_currency = self._prepare_currency('CHF')
|
||||||
providers = self.env['payment.provider']._get_compatible_providers(
|
providers = self.env['payment.provider']._get_compatible_providers(
|
||||||
self.company.id, self.partner.id, self.amount, currency_id=unsupported_currency.id
|
self.company.id, self.partner.id, self.amount, currency_id=unsupported_currency.id
|
||||||
@@ -43,6 +43,6 @@ class AuthorizeTest(AuthorizeCommon):
|
|||||||
))
|
))
|
||||||
|
|
||||||
def test_validation(self):
|
def test_validation(self):
|
||||||
self.assertEqual(self.authorize.authorize_currency_id, self.currency_usd)
|
self.assertEqual(self.authorize.available_currency_ids[0], self.currency_usd)
|
||||||
self.assertEqual(self.authorize._get_validation_amount(), 0.01)
|
self.assertEqual(self.authorize._get_validation_amount(), 0.01)
|
||||||
self.assertEqual(self.authorize._get_validation_currency(), self.currency_usd)
|
self.assertEqual(self.authorize._get_validation_currency(), self.currency_usd)
|
||||||
|
|||||||
@@ -27,15 +27,14 @@
|
|||||||
<field name="authorize_payment_method_type"
|
<field name="authorize_payment_method_type"
|
||||||
attrs="{'invisible': [('code', '!=', 'authorize')], 'required':[('code', '=', 'authorize'), ('state', '!=', 'disabled')]}"/>
|
attrs="{'invisible': [('code', '!=', 'authorize')], 'required':[('code', '=', 'authorize'), ('state', '!=', 'disabled')]}"/>
|
||||||
</field>
|
</field>
|
||||||
<field name="available_country_ids" position="after">
|
<div name="available_currencies" position="inside">
|
||||||
<label for="authorize_currency_id" string="Currency" attrs="{'invisible': [('code', '!=', 'authorize')]}"/>
|
<button string="Set Account Currency"
|
||||||
<div class="o_row" col="2" attrs="{'invisible': [('code', '!=', 'authorize')]}">
|
type="object"
|
||||||
<field name="authorize_currency_id"/>
|
name="action_update_merchant_details"
|
||||||
<button class="oe_link" icon="fa-refresh" type="object"
|
attrs="{'invisible': [('code', '!=', 'authorize')]}"
|
||||||
name="action_update_merchant_details"
|
icon="fa-refresh"
|
||||||
string="Set Account Currency"/>
|
class="oe_link"/>
|
||||||
</div>
|
</div>
|
||||||
</field>
|
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
|||||||
@@ -10,3 +10,17 @@ STATUS_CODES_MAPPING = {
|
|||||||
'refused': (690,),
|
'refused': (690,),
|
||||||
'error': (490, 491, 492,),
|
'error': (490, 491, 492,),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# The currencies supported by Buckaroo, in ISO 4217 format.
|
||||||
|
# See https://support.buckaroo.eu/frequently-asked-questions
|
||||||
|
# Last seen online: 7 November 2022.
|
||||||
|
SUPPORTED_CURRENCIES = [
|
||||||
|
'EUR',
|
||||||
|
'GBP',
|
||||||
|
'PLN',
|
||||||
|
'DKK',
|
||||||
|
'NOK',
|
||||||
|
'SEK',
|
||||||
|
'CHF',
|
||||||
|
'USD',
|
||||||
|
]
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ from werkzeug import urls
|
|||||||
|
|
||||||
from odoo import fields, models
|
from odoo import fields, models
|
||||||
|
|
||||||
|
from odoo.addons.payment_buckaroo.const import SUPPORTED_CURRENCIES
|
||||||
|
|
||||||
|
|
||||||
class PaymentProvider(models.Model):
|
class PaymentProvider(models.Model):
|
||||||
_inherit = 'payment.provider'
|
_inherit = 'payment.provider'
|
||||||
@@ -18,6 +20,15 @@ class PaymentProvider(models.Model):
|
|||||||
buckaroo_secret_key = fields.Char(
|
buckaroo_secret_key = fields.Char(
|
||||||
string="Buckaroo Secret Key", required_if_provider='buckaroo', groups='base.group_system')
|
string="Buckaroo Secret Key", required_if_provider='buckaroo', groups='base.group_system')
|
||||||
|
|
||||||
|
def _get_supported_currencies(self):
|
||||||
|
""" Override of `payment` to return the supported currencies. """
|
||||||
|
supported_currencies = super()._get_supported_currencies()
|
||||||
|
if self.code == 'buckaroo':
|
||||||
|
supported_currencies = supported_currencies.filtered(
|
||||||
|
lambda c: c.name in SUPPORTED_CURRENCIES
|
||||||
|
)
|
||||||
|
return supported_currencies
|
||||||
|
|
||||||
def _buckaroo_get_api_url(self):
|
def _buckaroo_get_api_url(self):
|
||||||
""" Return the API URL according to the state.
|
""" Return the API URL according to the state.
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
SUPPORTED_CURRENCIES = [
|
SUPPORTED_CURRENCIES = [
|
||||||
'GBP',
|
'GBP',
|
||||||
'CAD',
|
'CAD',
|
||||||
|
'XAF',
|
||||||
'CLP',
|
'CLP',
|
||||||
'COP',
|
'COP',
|
||||||
'EGP',
|
'EGP',
|
||||||
@@ -24,7 +25,6 @@ SUPPORTED_CURRENCIES = [
|
|||||||
'TZS',
|
'TZS',
|
||||||
'UGX',
|
'UGX',
|
||||||
'USD',
|
'USD',
|
||||||
'XAF',
|
|
||||||
'XOF',
|
'XOF',
|
||||||
'ZMW',
|
'ZMW',
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -49,19 +49,24 @@ class PaymentProvider(models.Model):
|
|||||||
# === BUSINESS METHODS ===#
|
# === BUSINESS METHODS ===#
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def _get_compatible_providers(self, *args, currency_id=None, is_validation=False, **kwargs):
|
def _get_compatible_providers(self, *args, is_validation=False, **kwargs):
|
||||||
""" Override of payment to filter out Flutterwave providers for unsupported currencies or
|
""" Override of `payment` to filter out Flutterwave providers for validation operations. """
|
||||||
for validation operations. """
|
providers = super()._get_compatible_providers(*args, is_validation=is_validation, **kwargs)
|
||||||
providers = super()._get_compatible_providers(
|
|
||||||
*args, currency_id=currency_id, is_validation=is_validation, **kwargs
|
|
||||||
)
|
|
||||||
|
|
||||||
currency = self.env['res.currency'].browse(currency_id).exists()
|
if is_validation:
|
||||||
if (currency and currency.name not in SUPPORTED_CURRENCIES) or is_validation:
|
|
||||||
providers = providers.filtered(lambda p: p.code != 'flutterwave')
|
providers = providers.filtered(lambda p: p.code != 'flutterwave')
|
||||||
|
|
||||||
return providers
|
return providers
|
||||||
|
|
||||||
|
def _get_supported_currencies(self):
|
||||||
|
""" Override of `payment` to return the supported currencies. """
|
||||||
|
supported_currencies = super()._get_supported_currencies()
|
||||||
|
if self.code == 'flutterwave':
|
||||||
|
supported_currencies = supported_currencies.filtered(
|
||||||
|
lambda c: c.name in SUPPORTED_CURRENCIES
|
||||||
|
)
|
||||||
|
return supported_currencies
|
||||||
|
|
||||||
def _flutterwave_make_request(self, endpoint, payload=None, method='POST'):
|
def _flutterwave_make_request(self, endpoint, payload=None, method='POST'):
|
||||||
""" Make a request to Flutterwave API at the specified endpoint.
|
""" Make a request to Flutterwave API at the specified endpoint.
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import pprint
|
|||||||
import requests
|
import requests
|
||||||
from werkzeug import urls
|
from werkzeug import urls
|
||||||
|
|
||||||
from odoo import _, api, fields, models
|
from odoo import _, fields, models
|
||||||
from odoo.exceptions import ValidationError
|
from odoo.exceptions import ValidationError
|
||||||
|
|
||||||
from odoo.addons.payment_mercado_pago.const import SUPPORTED_CURRENCIES
|
from odoo.addons.payment_mercado_pago.const import SUPPORTED_CURRENCIES
|
||||||
@@ -15,7 +15,7 @@ from odoo.addons.payment_mercado_pago.const import SUPPORTED_CURRENCIES
|
|||||||
_logger = logging.getLogger(__name__)
|
_logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class Paymentprovider(models.Model):
|
class PaymentProvider(models.Model):
|
||||||
_inherit = 'payment.provider'
|
_inherit = 'payment.provider'
|
||||||
|
|
||||||
code = fields.Selection(
|
code = fields.Selection(
|
||||||
@@ -29,16 +29,14 @@ class Paymentprovider(models.Model):
|
|||||||
|
|
||||||
# === BUSINESS METHODS === #
|
# === BUSINESS METHODS === #
|
||||||
|
|
||||||
@api.model
|
def _get_supported_currencies(self):
|
||||||
def _get_compatible_providers(self, *args, currency_id=None, **kwargs):
|
""" Override of `payment` to return the supported currencies. """
|
||||||
""" Override of `payment` to unlist Mercado Pago providers for unsupported currencies. """
|
supported_currencies = super()._get_supported_currencies()
|
||||||
providers = super()._get_compatible_providers(*args, currency_id=currency_id, **kwargs)
|
if self.code == 'mercado_pago':
|
||||||
|
supported_currencies = supported_currencies.filtered(
|
||||||
currency = self.env['res.currency'].browse(currency_id).exists()
|
lambda c: c.name in SUPPORTED_CURRENCIES
|
||||||
if currency and currency.name not in SUPPORTED_CURRENCIES:
|
)
|
||||||
providers = providers.filtered(lambda p: p.code != 'mercado_pago')
|
return supported_currencies
|
||||||
|
|
||||||
return providers
|
|
||||||
|
|
||||||
def _mercado_pago_make_request(self, endpoint, payload=None, method='POST'):
|
def _mercado_pago_make_request(self, endpoint, payload=None, method='POST'):
|
||||||
""" Make a request to Mercado Pago API at the specified endpoint.
|
""" Make a request to Mercado Pago API at the specified endpoint.
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ class TestPaymentTransaction(MercadoPagoCommon, PaymentHttpCommon):
|
|||||||
successful payment. """
|
successful payment. """
|
||||||
tx = self._create_transaction(flow='redirect')
|
tx = self._create_transaction(flow='redirect')
|
||||||
with patch(
|
with patch(
|
||||||
'odoo.addons.payment_mercado_pago.models.payment_provider.Paymentprovider'
|
'odoo.addons.payment_mercado_pago.models.payment_provider.PaymentProvider'
|
||||||
'._mercado_pago_make_request', return_value=self.verification_data
|
'._mercado_pago_make_request', return_value=self.verification_data
|
||||||
):
|
):
|
||||||
tx._process_notification_data(self.redirect_notification_data)
|
tx._process_notification_data(self.redirect_notification_data)
|
||||||
|
|||||||
@@ -12,11 +12,37 @@ SUPPORTED_LOCALES = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
# Currency codes in ISO 4217 format supported by mollie.
|
# Currency codes in ISO 4217 format supported by mollie.
|
||||||
# See https://docs.mollie.com/payments/multicurrency
|
# Note: support varies per payment method.
|
||||||
|
# See https://docs.mollie.com/payments/multicurrency. Last seen online: 22 September 2022.
|
||||||
SUPPORTED_CURRENCIES = [
|
SUPPORTED_CURRENCIES = [
|
||||||
'AED', 'AUD', 'BGN', 'BRL', 'CAD', 'CHF',
|
'AED',
|
||||||
'CZK', 'DKK', 'EUR', 'GBP', 'HKD', 'HRK',
|
'AUD',
|
||||||
'HUF', 'ILS', 'ISK', 'JPY', 'MXN', 'MYR',
|
'BGN',
|
||||||
'NOK', 'NZD', 'PHP', 'PLN', 'RON', 'RUB',
|
'BRL',
|
||||||
'SEK', 'SGD', 'THB', 'TWD', 'USD', 'ZAR'
|
'CAD',
|
||||||
|
'CHF',
|
||||||
|
'CZK',
|
||||||
|
'DKK',
|
||||||
|
'EUR',
|
||||||
|
'GBP',
|
||||||
|
'HKD',
|
||||||
|
'HRK',
|
||||||
|
'HUF',
|
||||||
|
'ILS',
|
||||||
|
'ISK',
|
||||||
|
'JPY',
|
||||||
|
'MXN',
|
||||||
|
'MYR',
|
||||||
|
'NOK',
|
||||||
|
'NZD',
|
||||||
|
'PHP',
|
||||||
|
'PLN',
|
||||||
|
'RON',
|
||||||
|
'RUB',
|
||||||
|
'SEK',
|
||||||
|
'SGD',
|
||||||
|
'THB',
|
||||||
|
'TWD',
|
||||||
|
'USD',
|
||||||
|
'ZAR'
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import logging
|
|||||||
import requests
|
import requests
|
||||||
from werkzeug import urls
|
from werkzeug import urls
|
||||||
|
|
||||||
from odoo import _, api, fields, models, service
|
from odoo import _, fields, models, service
|
||||||
from odoo.exceptions import ValidationError
|
from odoo.exceptions import ValidationError
|
||||||
|
|
||||||
from odoo.addons.payment_mollie.const import SUPPORTED_CURRENCIES
|
from odoo.addons.payment_mollie.const import SUPPORTED_CURRENCIES
|
||||||
@@ -27,16 +27,14 @@ class PaymentProvider(models.Model):
|
|||||||
|
|
||||||
#=== BUSINESS METHODS ===#
|
#=== BUSINESS METHODS ===#
|
||||||
|
|
||||||
@api.model
|
def _get_supported_currencies(self):
|
||||||
def _get_compatible_providers(self, *args, currency_id=None, **kwargs):
|
""" Override of `payment` to return the supported currencies. """
|
||||||
""" Override of payment to unlist Mollie providers for unsupported currencies. """
|
supported_currencies = super()._get_supported_currencies()
|
||||||
providers = super()._get_compatible_providers(*args, currency_id=currency_id, **kwargs)
|
if self.code == 'mollie':
|
||||||
|
supported_currencies = supported_currencies.filtered(
|
||||||
currency = self.env['res.currency'].browse(currency_id).exists()
|
lambda c: c.name in SUPPORTED_CURRENCIES
|
||||||
if currency and currency.name not in SUPPORTED_CURRENCIES:
|
)
|
||||||
providers = providers.filtered(lambda p: p.code != 'mollie')
|
return supported_currencies
|
||||||
|
|
||||||
return providers
|
|
||||||
|
|
||||||
def _mollie_make_request(self, endpoint, data=None, method='POST'):
|
def _mollie_make_request(self, endpoint, data=None, method='POST'):
|
||||||
""" Make a request at mollie endpoint.
|
""" Make a request at mollie endpoint.
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||||
|
|
||||||
# ISO 4217 codes of currencies supported by PayPal
|
# ISO 4217 codes of currencies supported by PayPal
|
||||||
|
# See https://developer.paypal.com/docs/reports/reference/paypal-supported-currencies/.
|
||||||
|
# Last seen on: 22 September 2022.
|
||||||
SUPPORTED_CURRENCIES = (
|
SUPPORTED_CURRENCIES = (
|
||||||
'AUD',
|
'AUD',
|
||||||
'BRL',
|
'BRL',
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from odoo import _, api, fields, models
|
from odoo import _, fields, models
|
||||||
|
|
||||||
from odoo.addons.payment_paypal.const import SUPPORTED_CURRENCIES
|
from odoo.addons.payment_paypal.const import SUPPORTED_CURRENCIES
|
||||||
|
|
||||||
@@ -35,16 +35,14 @@ class PaymentProvider(models.Model):
|
|||||||
|
|
||||||
#=== BUSINESS METHODS ===#
|
#=== BUSINESS METHODS ===#
|
||||||
|
|
||||||
@api.model
|
def _get_supported_currencies(self):
|
||||||
def _get_compatible_providers(self, *args, currency_id=None, **kwargs):
|
""" Override of `payment` to return the supported currencies. """
|
||||||
""" Override of payment to unlist PayPal providers when the currency is not supported. """
|
supported_currencies = super()._get_supported_currencies()
|
||||||
providers = super()._get_compatible_providers(*args, currency_id=currency_id, **kwargs)
|
if self.code == 'paypal':
|
||||||
|
supported_currencies = supported_currencies.filtered(
|
||||||
currency = self.env['res.currency'].browse(currency_id).exists()
|
lambda c: c.name in SUPPORTED_CURRENCIES
|
||||||
if currency and currency.name not in SUPPORTED_CURRENCIES:
|
)
|
||||||
providers = providers.filtered(lambda p: p.code != 'paypal')
|
return supported_currencies
|
||||||
|
|
||||||
return providers
|
|
||||||
|
|
||||||
def _paypal_get_api_url(self):
|
def _paypal_get_api_url(self):
|
||||||
""" Return the API URL according to the provider state.
|
""" Return the API URL according to the provider state.
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||||
|
|
||||||
|
# Supported currencies of PayuLatam, in ISO 4217 currency codes.
|
||||||
|
# https://developers.payulatam.com/latam/en/docs/getting-started/response-codes-and-variables.html#accepted-currencies.
|
||||||
|
# Last seen online: 22 September 2022.
|
||||||
|
SUPPORTED_CURRENCIES = [
|
||||||
|
'ARS',
|
||||||
|
'BRL',
|
||||||
|
'CLP',
|
||||||
|
'COP',
|
||||||
|
'MXN',
|
||||||
|
'PEN',
|
||||||
|
'USD'
|
||||||
|
]
|
||||||
@@ -2,11 +2,10 @@
|
|||||||
|
|
||||||
from hashlib import md5
|
from hashlib import md5
|
||||||
|
|
||||||
from odoo import api, fields, models
|
from odoo import fields, models
|
||||||
from odoo.tools.float_utils import float_repr
|
from odoo.tools.float_utils import float_repr
|
||||||
|
|
||||||
SUPPORTED_CURRENCIES = ('ARS', 'BRL', 'CLP', 'COP', 'MXN', 'PEN', 'USD')
|
from odoo.addons.payment_payulatam.const import SUPPORTED_CURRENCIES
|
||||||
|
|
||||||
|
|
||||||
class PaymentProvider(models.Model):
|
class PaymentProvider(models.Model):
|
||||||
_inherit = 'payment.provider'
|
_inherit = 'payment.provider'
|
||||||
@@ -25,16 +24,14 @@ class PaymentProvider(models.Model):
|
|||||||
string="PayU Latam API Key", required_if_provider='payulatam',
|
string="PayU Latam API Key", required_if_provider='payulatam',
|
||||||
groups='base.group_system')
|
groups='base.group_system')
|
||||||
|
|
||||||
@api.model
|
def _get_supported_currencies(self):
|
||||||
def _get_compatible_providers(self, *args, currency_id=None, **kwargs):
|
""" Override of `payment` to return the supported currencies. """
|
||||||
""" Override of payment to unlist PayU Latam providers for unsupported currencies. """
|
supported_currencies = super()._get_supported_currencies()
|
||||||
providers = super()._get_compatible_providers(*args, currency_id=currency_id, **kwargs)
|
if self.code == 'payulatam':
|
||||||
|
supported_currencies = supported_currencies.filtered(
|
||||||
currency = self.env['res.currency'].browse(currency_id).exists()
|
lambda c: c.name in SUPPORTED_CURRENCIES
|
||||||
if currency and currency.name not in SUPPORTED_CURRENCIES:
|
)
|
||||||
providers = providers.filtered(lambda p: p.code != 'payulatam')
|
return supported_currencies
|
||||||
|
|
||||||
return providers
|
|
||||||
|
|
||||||
def _payulatam_generate_sign(self, values, incoming=True):
|
def _payulatam_generate_sign(self, values, incoming=True):
|
||||||
""" Generate the signature for incoming or outgoing communications.
|
""" Generate the signature for incoming or outgoing communications.
|
||||||
|
|||||||
@@ -12,22 +12,12 @@ from odoo.tools import mute_logger
|
|||||||
|
|
||||||
from odoo.addons.payment.tests.http_common import PaymentHttpCommon
|
from odoo.addons.payment.tests.http_common import PaymentHttpCommon
|
||||||
from odoo.addons.payment_payulatam.controllers.main import PayuLatamController
|
from odoo.addons.payment_payulatam.controllers.main import PayuLatamController
|
||||||
from odoo.addons.payment_payulatam.models.payment_provider import SUPPORTED_CURRENCIES
|
|
||||||
from odoo.addons.payment_payulatam.tests.common import PayULatamCommon
|
from odoo.addons.payment_payulatam.tests.common import PayULatamCommon
|
||||||
|
|
||||||
|
|
||||||
@tagged('post_install', '-at_install')
|
@tagged('post_install', '-at_install')
|
||||||
class PayULatamTest(PayULatamCommon, PaymentHttpCommon):
|
class PayULatamTest(PayULatamCommon, PaymentHttpCommon):
|
||||||
|
|
||||||
def test_compatibility_with_supported_currencies(self):
|
|
||||||
""" Test that the PayULatam provider is compatible with all supported currencies. """
|
|
||||||
for supported_currency_code in SUPPORTED_CURRENCIES:
|
|
||||||
supported_currency = self._prepare_currency(supported_currency_code)
|
|
||||||
compatible_providers = self.env['payment.provider']._get_compatible_providers(
|
|
||||||
self.company.id, self.partner.id, self.amount, currency_id=supported_currency.id
|
|
||||||
)
|
|
||||||
self.assertIn(self.payulatam, compatible_providers)
|
|
||||||
|
|
||||||
def test_incompatibility_with_unsupported_currency(self):
|
def test_incompatibility_with_unsupported_currency(self):
|
||||||
""" Test that the PayULatam provider is not compatible with an unsupported currency. """
|
""" Test that the PayULatam provider is not compatible with an unsupported currency. """
|
||||||
compatible_providers = self.env['payment.provider']._get_compatible_providers(
|
compatible_providers = self.env['payment.provider']._get_compatible_providers(
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import hashlib
|
import hashlib
|
||||||
|
|
||||||
from odoo import api, fields, models
|
from odoo import fields, models
|
||||||
|
|
||||||
|
|
||||||
class PaymentProvider(models.Model):
|
class PaymentProvider(models.Model):
|
||||||
@@ -16,16 +16,12 @@ class PaymentProvider(models.Model):
|
|||||||
payumoney_merchant_salt = fields.Char(
|
payumoney_merchant_salt = fields.Char(
|
||||||
string="Merchant Salt", required_if_provider='payumoney', groups='base.group_system')
|
string="Merchant Salt", required_if_provider='payumoney', groups='base.group_system')
|
||||||
|
|
||||||
@api.model
|
def _get_supported_currencies(self):
|
||||||
def _get_compatible_providers(self, *args, currency_id=None, **kwargs):
|
""" Override of `payment` to return EUR as the only supported currency. """
|
||||||
""" Override of payment to unlist PayUmoney providers when the currency is not INR. """
|
supported_currencies = super()._get_supported_currencies()
|
||||||
providers = super()._get_compatible_providers(*args, currency_id=currency_id, **kwargs)
|
if self.code == 'payumoney':
|
||||||
|
supported_currencies = supported_currencies.filtered(lambda c: c.name == 'INR')
|
||||||
currency = self.env['res.currency'].browse(currency_id).exists()
|
return supported_currencies
|
||||||
if currency and currency.name != 'INR':
|
|
||||||
providers = providers.filtered(lambda p: p.code != 'payumoney')
|
|
||||||
|
|
||||||
return providers
|
|
||||||
|
|
||||||
def _payumoney_generate_sign(self, values, incoming=True):
|
def _payumoney_generate_sign(self, values, incoming=True):
|
||||||
""" Generate the shasign for incoming or outgoing communications.
|
""" Generate the shasign for incoming or outgoing communications.
|
||||||
|
|||||||
@@ -2,15 +2,100 @@
|
|||||||
|
|
||||||
# The currencies supported by Razorpay, in ISO 4217 format. Last updated on May 26, 2021.
|
# The currencies supported by Razorpay, in ISO 4217 format. Last updated on May 26, 2021.
|
||||||
# See https://razorpay.com/docs/payments/payments/international-payments/#supported-currencies.
|
# See https://razorpay.com/docs/payments/payments/international-payments/#supported-currencies.
|
||||||
|
# Last seen online: 16 November 2022.
|
||||||
SUPPORTED_CURRENCIES = [
|
SUPPORTED_CURRENCIES = [
|
||||||
'AED', 'ALL', 'AMD', 'ARS', 'AUD', 'AWG', 'BBD', 'BDT', 'BMD', 'BND', 'BOB', 'BSD', 'BWP',
|
'AED',
|
||||||
'BZD', 'CAD', 'CHF', 'CNY', 'COP', 'CRC', 'CUP', 'CZK', 'DKK', 'DOP', 'DZD', 'EGP', 'ETB',
|
'ALL',
|
||||||
'EUR', 'FJD', 'GBP', 'GHS', 'GIP', 'GMD', 'GTQ', 'GYD', 'HKD', 'HNL', 'HRK', 'HTG', 'HUF',
|
'AMD',
|
||||||
'IDR', 'ILS', 'INR', 'JMD', 'KES', 'KGS', 'KHR', 'KYD', 'KZT', 'LAK', 'LBP', 'LKR', 'LRD',
|
'ARS',
|
||||||
'LSL', 'MAD', 'MDL', 'MKD', 'MMK', 'MNT', 'MOP', 'MUR', 'MVR', 'MWK', 'MXN', 'MYR', 'NAD',
|
'AUD',
|
||||||
'NGN', 'NIO', 'NOK', 'NPR', 'NZD', 'PEN', 'PGK', 'PHP', 'PKR', 'QAR', 'RUB', 'SAR', 'SCR',
|
'AWG',
|
||||||
'SEK', 'SGD', 'SLL', 'SOS', 'SSP', 'SVC', 'SZL', 'THB', 'TTD', 'TZS', 'USD', 'UYU', 'UZS',
|
'BBD',
|
||||||
'YER', 'ZAR',
|
'BDT',
|
||||||
|
'BMD',
|
||||||
|
'BND',
|
||||||
|
'BOB',
|
||||||
|
'BSD',
|
||||||
|
'BWP',
|
||||||
|
'BZD',
|
||||||
|
'CAD',
|
||||||
|
'CHF',
|
||||||
|
'CNY',
|
||||||
|
'COP',
|
||||||
|
'CRC',
|
||||||
|
'CUP',
|
||||||
|
'CZK',
|
||||||
|
'DKK',
|
||||||
|
'DOP',
|
||||||
|
'DZD',
|
||||||
|
'EGP',
|
||||||
|
'ETB',
|
||||||
|
'EUR',
|
||||||
|
'FJD',
|
||||||
|
'GBP',
|
||||||
|
'GHS',
|
||||||
|
'GIP',
|
||||||
|
'GMD',
|
||||||
|
'GTQ',
|
||||||
|
'GYD',
|
||||||
|
'HKD',
|
||||||
|
'HNL',
|
||||||
|
'HRK',
|
||||||
|
'HTG',
|
||||||
|
'HUF',
|
||||||
|
'IDR',
|
||||||
|
'ILS',
|
||||||
|
'INR',
|
||||||
|
'JMD',
|
||||||
|
'KES',
|
||||||
|
'KGS',
|
||||||
|
'KHR',
|
||||||
|
'KYD',
|
||||||
|
'KZT',
|
||||||
|
'LAK',
|
||||||
|
'LKR',
|
||||||
|
'LRD',
|
||||||
|
'LSL',
|
||||||
|
'MAD',
|
||||||
|
'MDL',
|
||||||
|
'MKD',
|
||||||
|
'MMK',
|
||||||
|
'MNT',
|
||||||
|
'MOP',
|
||||||
|
'MUR',
|
||||||
|
'MVR',
|
||||||
|
'MWK',
|
||||||
|
'MXN',
|
||||||
|
'MYR',
|
||||||
|
'NAD',
|
||||||
|
'NGN',
|
||||||
|
'NIO',
|
||||||
|
'NOK',
|
||||||
|
'NPR',
|
||||||
|
'NZD',
|
||||||
|
'PEN',
|
||||||
|
'PGK',
|
||||||
|
'PHP',
|
||||||
|
'PKR',
|
||||||
|
'QAR',
|
||||||
|
'RUB',
|
||||||
|
'SAR',
|
||||||
|
'SCR',
|
||||||
|
'SEK',
|
||||||
|
'SGD',
|
||||||
|
'SLL',
|
||||||
|
'SOS',
|
||||||
|
'SSP',
|
||||||
|
'SVC',
|
||||||
|
'SZL',
|
||||||
|
'THB',
|
||||||
|
'TTD',
|
||||||
|
'TZS',
|
||||||
|
'USD',
|
||||||
|
'UYU',
|
||||||
|
'UZS',
|
||||||
|
'YER',
|
||||||
|
'ZAR',
|
||||||
]
|
]
|
||||||
|
|
||||||
# Mapping of transaction states to Razorpay's payment statuses.
|
# Mapping of transaction states to Razorpay's payment statuses.
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import pprint
|
|||||||
import requests
|
import requests
|
||||||
from werkzeug.urls import url_join
|
from werkzeug.urls import url_join
|
||||||
|
|
||||||
from odoo import _, api, fields, models
|
from odoo import _, fields, models
|
||||||
from odoo.exceptions import ValidationError
|
from odoo.exceptions import ValidationError
|
||||||
|
|
||||||
from odoo.addons.payment_razorpay.const import SUPPORTED_CURRENCIES
|
from odoo.addons.payment_razorpay.const import SUPPORTED_CURRENCIES
|
||||||
@@ -51,16 +51,14 @@ class PaymentProvider(models.Model):
|
|||||||
|
|
||||||
# === BUSINESS METHODS ===#
|
# === BUSINESS METHODS ===#
|
||||||
|
|
||||||
@api.model
|
def _get_supported_currencies(self):
|
||||||
def _get_compatible_providers(self, *args, currency_id=None, **kwargs):
|
""" Override of `payment` to return the supported currencies. """
|
||||||
""" Override of `payment` to filter out Razorpay providers for unsupported currencies. """
|
supported_currencies = super()._get_supported_currencies()
|
||||||
providers = super()._get_compatible_providers(*args, currency_id=currency_id, **kwargs)
|
if self.code == 'razorpay':
|
||||||
|
supported_currencies = supported_currencies.filtered(
|
||||||
currency = self.env['res.currency'].browse(currency_id).exists()
|
lambda c: c.name in SUPPORTED_CURRENCIES
|
||||||
if currency and currency.name not in SUPPORTED_CURRENCIES:
|
)
|
||||||
providers = providers.filtered(lambda p: p.code != 'razorpay')
|
return supported_currencies
|
||||||
|
|
||||||
return providers
|
|
||||||
|
|
||||||
def _razorpay_make_request(self, endpoint, payload=None, method='POST'):
|
def _razorpay_make_request(self, endpoint, payload=None, method='POST'):
|
||||||
""" Make a request to Razorpay API at the specified endpoint.
|
""" Make a request to Razorpay API at the specified endpoint.
|
||||||
|
|||||||
@@ -3,12 +3,7 @@
|
|||||||
# ISO 4217 Data for currencies supported by sips
|
# ISO 4217 Data for currencies supported by sips
|
||||||
# NOTE: these are listed on the Atos Wordline SIPS POST documentation page
|
# NOTE: these are listed on the Atos Wordline SIPS POST documentation page
|
||||||
# at https://documentation.sips.worldline.com/en/WLSIPS.001-GD-Data-dictionary.html#Sips.001_DD_en-Value-currencyCode
|
# at https://documentation.sips.worldline.com/en/WLSIPS.001-GD-Data-dictionary.html#Sips.001_DD_en-Value-currencyCode
|
||||||
# Yet with the simu environment, some of these currencies are *not* working
|
# Last seen on: 22 September 2022.
|
||||||
# I have no way to know if this is caused by the SIMU environment, or if it's
|
|
||||||
# the doc of SIPS that lists currencies that don't work, but since this list is
|
|
||||||
# restrictive, I'm gonna assume they are supported when using the right flow
|
|
||||||
# and payment methods, which may not work in SIMU...
|
|
||||||
# Since SIPS advises to use 'in production', well...
|
|
||||||
SUPPORTED_CURRENCIES = {
|
SUPPORTED_CURRENCIES = {
|
||||||
'ARS': '032',
|
'ARS': '032',
|
||||||
'AUD': '036',
|
'AUD': '036',
|
||||||
@@ -3,9 +3,9 @@
|
|||||||
|
|
||||||
from hashlib import sha256
|
from hashlib import sha256
|
||||||
|
|
||||||
from odoo import api, fields, models
|
from odoo import fields, models
|
||||||
|
|
||||||
from .const import SUPPORTED_CURRENCIES
|
from odoo.addons.payment_sips.const import SUPPORTED_CURRENCIES
|
||||||
|
|
||||||
|
|
||||||
class PaymentProvider(models.Model):
|
class PaymentProvider(models.Model):
|
||||||
@@ -29,16 +29,14 @@ class PaymentProvider(models.Model):
|
|||||||
sips_version = fields.Char(
|
sips_version = fields.Char(
|
||||||
string="Interface Version", required_if_provider='sips', default="HP_2.31")
|
string="Interface Version", required_if_provider='sips', default="HP_2.31")
|
||||||
|
|
||||||
@api.model
|
def _get_supported_currencies(self):
|
||||||
def _get_compatible_providers(self, *args, currency_id=None, **kwargs):
|
""" Override of `payment` to return the supported currencies. """
|
||||||
""" Override of payment to unlist Sips providers when the currency is not supported. """
|
supported_currencies = super()._get_supported_currencies()
|
||||||
providers = super()._get_compatible_providers(*args, currency_id=currency_id, **kwargs)
|
if self.code == 'sips':
|
||||||
|
supported_currencies = supported_currencies.filtered(
|
||||||
currency = self.env['res.currency'].browse(currency_id).exists()
|
lambda c: c.name in SUPPORTED_CURRENCIES.keys()
|
||||||
if currency and currency.name not in SUPPORTED_CURRENCIES:
|
)
|
||||||
providers = providers.filtered(lambda p: p.code != 'sips')
|
return supported_currencies
|
||||||
|
|
||||||
return providers
|
|
||||||
|
|
||||||
def _sips_generate_shasign(self, data):
|
def _sips_generate_shasign(self, data):
|
||||||
""" Generate the shasign for incoming or outgoing communications.
|
""" Generate the shasign for incoming or outgoing communications.
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ from odoo import _, api, models
|
|||||||
from odoo.exceptions import ValidationError
|
from odoo.exceptions import ValidationError
|
||||||
|
|
||||||
from odoo.addons.payment import utils as payment_utils
|
from odoo.addons.payment import utils as payment_utils
|
||||||
|
from odoo.addons.payment_sips.const import RESPONSE_CODES_MAPPING, SUPPORTED_CURRENCIES
|
||||||
from odoo.addons.payment_sips.controllers.main import SipsController
|
from odoo.addons.payment_sips.controllers.main import SipsController
|
||||||
from .const import RESPONSE_CODES_MAPPING, SUPPORTED_CURRENCIES
|
|
||||||
|
|
||||||
_logger = logging.getLogger(__name__)
|
_logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ from odoo.tools import mute_logger
|
|||||||
|
|
||||||
from odoo.addons.payment.tests.http_common import PaymentHttpCommon
|
from odoo.addons.payment.tests.http_common import PaymentHttpCommon
|
||||||
from odoo.addons.payment_sips.controllers.main import SipsController
|
from odoo.addons.payment_sips.controllers.main import SipsController
|
||||||
from odoo.addons.payment_sips.models.payment_provider import SUPPORTED_CURRENCIES
|
|
||||||
from odoo.addons.payment_sips.tests.common import SipsCommon
|
from odoo.addons.payment_sips.tests.common import SipsCommon
|
||||||
|
|
||||||
|
|
||||||
@@ -20,13 +19,6 @@ from odoo.addons.payment_sips.tests.common import SipsCommon
|
|||||||
class SipsTest(SipsCommon, PaymentHttpCommon):
|
class SipsTest(SipsCommon, PaymentHttpCommon):
|
||||||
|
|
||||||
def test_compatible_providers(self):
|
def test_compatible_providers(self):
|
||||||
for curr in SUPPORTED_CURRENCIES:
|
|
||||||
currency = self._prepare_currency(curr)
|
|
||||||
providers = self.env['payment.provider']._get_compatible_providers(
|
|
||||||
self.company.id, self.partner.id, self.amount, currency_id=currency.id
|
|
||||||
)
|
|
||||||
self.assertIn(self.sips, providers)
|
|
||||||
|
|
||||||
unsupported_currency = self._prepare_currency('VEF')
|
unsupported_currency = self._prepare_currency('VEF')
|
||||||
providers = self.env['payment.provider']._get_compatible_providers(
|
providers = self.env['payment.provider']._get_compatible_providers(
|
||||||
self.company.id, self.partner.id, self.amount, currency_id=unsupported_currency.id
|
self.company.id, self.partner.id, self.amount, currency_id=unsupported_currency.id
|
||||||
|
|||||||
Reference in New Issue
Block a user