diff --git a/addons/payment/models/payment_provider.py b/addons/payment/models/payment_provider.py
index abec35a96a8..1b6aa7595a3 100644
--- a/addons/payment/models/payment_provider.py
+++ b/addons/payment/models/payment_provider.py
@@ -111,10 +111,14 @@ class PaymentProvider(models.Model):
# Fees fields
fees_active = fields.Boolean(string="Add Extra Fees")
- fees_dom_fixed = fields.Float(string="Fixed domestic fees")
- fees_dom_var = fields.Float(string="Variable domestic fees (in percents)")
- fees_int_fixed = fields.Float(string="Fixed international fees")
- fees_int_var = fields.Float(string="Variable international fees (in percents)")
+ fees_dom_fixed = fields.Monetary(
+ string="Fixed domestic fees", currency_field='main_currency_id'
+ )
+ fees_dom_var = fields.Float(string="Variable domestic fees")
+ fees_int_fixed = fields.Monetary(
+ string="Fixed international fees", currency_field='main_currency_id'
+ )
+ fees_int_var = fields.Float(string="Variable international fees")
# Message fields
display_as = fields.Char(
@@ -315,7 +319,7 @@ class PaymentProvider(models.Model):
:return None
"""
for provider in self:
- if any(not 0 <= fee < 100 for fee in (provider.fees_dom_var, provider.fees_int_var)):
+ if any(not 0 <= fee < 1 for fee in (provider.fees_dom_var, provider.fees_int_var)):
raise ValidationError(_("Variable fees must always be positive and below 100%."))
#=== CRUD METHODS ===#
@@ -499,9 +503,9 @@ class PaymentProvider(models.Model):
The computation is based on the fields `fees_dom_fixed`, `fees_dom_var`, `fees_int_fixed`
and `fees_int_var`, and is performed with the formula
- :code:`fees = (amount * variable / 100.0 + fixed) / (1 - variable / 100.0)` where the values
- of `fixed` and `variable` are taken from either the domestic (`dom`) or international
- (`int`) fields, depending on whether the country matches the company's country.
+ :code:`fees = (amount * variable + fixed) / (1 - variable)` where the values of `fixed` and
+ `variable` are taken from either the domestic (`dom`) or international (`int`) fields,
+ depending on whether the country matches the company's country.
For a provider to base the computation on different variables, or to use a different
formula, it must override this method and return the resulting fees.
@@ -522,7 +526,10 @@ class PaymentProvider(models.Model):
else:
fixed = self.fees_int_fixed
variable = self.fees_int_var
- fees = (amount * variable / 100.0 + fixed) / (1 - variable / 100.0)
+ fixed_converted = self.main_currency_id._convert(
+ fixed, currency, self.company_id, fields.Date.context_today(self)
+ )
+ fees = (amount * variable + fixed_converted) / (1 - variable)
return fees
def _get_validation_amount(self):
diff --git a/addons/payment/tests/common.py b/addons/payment/tests/common.py
index e298dca688b..44e3deaa405 100644
--- a/addons/payment/tests/common.py
+++ b/addons/payment/tests/common.py
@@ -6,13 +6,13 @@ from unittest.mock import patch
from lxml import objectify
from odoo.fields import Command
-from odoo.tests.common import TransactionCase
+from odoo.addons.base.tests.common import BaseCommon
from odoo.tools.misc import hmac as hmac_tool
_logger = logging.getLogger(__name__)
-class PaymentCommon(TransactionCase):
+class PaymentCommon(BaseCommon):
@classmethod
def setUpClass(cls):
diff --git a/addons/payment/tests/test_payment_provider.py b/addons/payment/tests/test_payment_provider.py
index aa4ebb9561b..ccce69d3dcd 100644
--- a/addons/payment/tests/test_payment_provider.py
+++ b/addons/payment/tests/test_payment_provider.py
@@ -1,12 +1,14 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
+from unittest.mock import patch
+
from odoo.tests import tagged
from odoo.addons.payment.tests.common import PaymentCommon
@tagged('-at_install', 'post_install')
-class TestPaymentprovider(PaymentCommon):
+class TestPaymentProvider(PaymentCommon):
def test_published_provider_compatible_with_all_users(self):
""" Test that a published provider is always available to all users. """
@@ -67,3 +69,52 @@ class TestPaymentprovider(PaymentCommon):
self.company.id, self.partner.id, self.amount, currency_id=self.env.company.currency_id.id,
)
self.assertNotIn(self.provider, compatible_providers)
+
+ def test_fees_null_when_deactivated(self):
+ """ Test that extra fees of a provider are null if these fees are deactivated. """
+ self.provider.write({
+ 'fees_active': False,
+ 'fees_dom_fixed': 1.0,
+ 'fees_dom_var': 0.35,
+ 'fees_int_fixed': 0.1,
+ 'fees_int_var': 0.2,
+ })
+ transaction_fees = self.provider._compute_fees(
+ self.amount, self.currency, self.partner.country_id
+ )
+ self.assertEqual(transaction_fees, 0)
+
+ def test_fees_formula(self):
+ """ Test that the extra fees of a provider are correctly computed in a domestic case. """
+ self.provider.write({
+ 'fees_active': True,
+ 'fees_dom_fixed': 1.0,
+ 'fees_dom_var': 0.0035,
+ 'fees_int_fixed': 0.,
+ 'fees_int_var': 0.,
+ })
+ transaction_fees = self.currency.round(
+ self.provider._compute_fees(
+ self.amount, self.currency_usd, self.provider.company_id.country_id
+ )
+ )
+ self.assertEqual(transaction_fees, 4.91)
+
+ def test_fees_with_currency_conversion(self):
+ """ Test that the conversion of the fees is correctly computed. """
+ self.provider.write({
+ 'fees_active': True,
+ 'fees_dom_fixed': 0.,
+ 'fees_dom_var': 0.,
+ 'fees_int_fixed': 1.,
+ 'fees_int_var': 0.,
+ })
+
+ with patch(
+ 'odoo.addons.base.models.res_currency.Currency._get_rates',
+ return_value={self.currency_euro.id: 2., self.currency_usd.id: 1.},
+ ):
+ transaction_fees = self.currency.round(
+ self.provider._compute_fees(self.amount, self.currency_euro, self.country_france)
+ )
+ self.assertEqual(transaction_fees, 2.)
diff --git a/addons/payment/views/payment_provider_views.xml b/addons/payment/views/payment_provider_views.xml
index 7896f9f1dd1..25a1668d094 100644
--- a/addons/payment/views/payment_provider_views.xml
+++ b/addons/payment/views/payment_provider_views.xml
@@ -94,11 +94,19 @@
-
-
-
-
-
+
+
+
+
+
+
+