[IMP] payment(_demo, _stripe), website_sale_picking: PM improvements

1) Add default filter to list view of payment methods.
2) Raise UserError when the user activates a PM linked to
   only disabled providers.
3) Activate default PMs with the activation of the provider.
4) Disable PMs linked to only disabled providers.
5) Add multi editing to list view of PMs.

task-3557315

closes odoo/odoo#139641

closes odoo/odoo#140084

Related: odoo/enterprise#49551
Related: odoo/enterprise#49729
Signed-off-by: Antoine Vandevenne (anv) <anv@odoo.com>
This commit is contained in:
Valeriya(vchu)
2023-10-27 16:09:39 +00:00
parent c5237e1ac1
commit fdb6f62742
13 changed files with 121 additions and 53 deletions
+16 -1
View File
@@ -1,6 +1,7 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import _, api, fields, models, Command
from odoo import Command, _, api, fields, models
from odoo.exceptions import UserError
from odoo.osv import expression
@@ -164,6 +165,20 @@ class PaymentMethod(models.Model):
('payment_method_id', 'in', (self + self.brand_ids).ids),
]) # Fix `active_test` in the context forwarded by the view.
linked_tokens.active = False
# Prevent enabling a payment method if it is not linked to an enabled provider.
if values.get('active'):
for pm in self:
primary_pm = pm if pm.is_primary else pm.primary_payment_method_id
if (
not primary_pm.active # Don't bother for already enabled payment methods.
and all(p.state == 'disabled' for p in primary_pm.provider_ids)
):
raise UserError(_(
"This payment method needs a partner in crime; you should enable a payment"
" provider supporting this method first."
))
return super().write(values)
# === BUSINESS METHODS === #
+43 -3
View File
@@ -331,16 +331,25 @@ class PaymentProvider(models.Model):
return providers
def write(self, values):
# Handle provider disabling.
# Handle provider state changes.
deactivated_providers = self.env['payment.provider']
activated_providers = self.env['payment.provider']
if 'state' in values:
state_changed_providers = self.filtered(
lambda p: p.state not in ('disabled', values['state'])
) # Don't handle providers being enabled or whose state is not updated.
state_changed_providers._handle_state_change()
state_changed_providers._archive_linked_tokens()
if values['state'] == 'disabled':
deactivated_providers = state_changed_providers
else: # 'enabled' or 'test'
activated_providers = self.filtered(lambda p: p.state == 'disabled')
result = super().write(values)
self._check_required_if_provider()
deactivated_providers._deactivate_unsupported_payment_methods()
activated_providers._activate_default_pms()
return result
def _check_required_if_provider(self):
@@ -370,13 +379,33 @@ class PaymentProvider(models.Model):
_("The following fields must be filled: %s", ", ".join(field_names))
)
def _handle_state_change(self):
def _archive_linked_tokens(self):
""" Archive all the payment tokens linked to the providers.
:return: None
"""
self.env['payment.token'].search([('provider_id', 'in', self.ids)]).write({'active': False})
def _deactivate_unsupported_payment_methods(self):
""" Deactivate payment methods linked to only disabled providers.
:return: None
"""
unsupported_pms = self.payment_method_ids.filtered(
lambda pm: all(p.state == 'disabled' for p in pm.provider_ids)
)
(unsupported_pms + unsupported_pms.brand_ids).active = False
def _activate_default_pms(self):
""" Activate the default payment methods of the provider.
:return: None
"""
for provider in self:
pm_codes = provider._get_default_payment_method_codes()
pms = provider.with_context(active_test=False).payment_method_ids
(pms + pms.brand_ids).filtered(lambda pm: pm.code in pm_codes).active = True
@api.ondelete(at_uninstall=False)
def _unlink_except_master_data(self):
""" Prevent the deletion of the payment provider if it has an xmlid. """
@@ -656,3 +685,14 @@ class PaymentProvider(models.Model):
"""
self.ensure_one()
return self.code
def _get_default_payment_method_codes(self):
""" Return the default payment methods for this provider.
Note: self.ensure_one()
:return: The default payment method codes.
:rtype: list
"""
self.ensure_one()
return []
+5 -5
View File
@@ -61,11 +61,6 @@ class PaymentCommon(BaseCommon):
'country_id': cls.country_belgium.id,
})
# Activate pm
cls.env.ref('payment.payment_method_unknown').write({
'active': True,
'support_tokenization': True,
})
# Create a dummy provider to allow basic tests without any specific provider implementation
arch = """
<form action="dummy" method="post">
@@ -91,6 +86,11 @@ class PaymentCommon(BaseCommon):
(cls.currency_euro + cls.currency_usd + cls.env.company.currency_id).ids
)],
})
# Activate pm
cls.env.ref('payment.payment_method_unknown').write({
'active': True,
'support_tokenization': True,
})
cls.provider = cls.dummy_provider
cls.payment_methods = cls.provider.payment_method_ids
@@ -89,7 +89,7 @@
<field name="name">payment.method.tree</field>
<field name="model">payment.method</field>
<field name="arch" type="xml">
<tree decoration-muted="not active">
<tree multi_edit="True" decoration-muted="not active">
<field name="sequence" widget="handle"/>
<field name="name"/>
<field name="active" widget="boolean_toggle"/>
@@ -130,6 +130,10 @@
<field name="arch" type="xml">
<search>
<field name="name" string="Name"/>
<filter name="available_pms"
string="Available methods"
domain="[('provider_ids.state', '!=', 'disabled')]"
/>
</search>
</field>
</record>
@@ -138,12 +142,8 @@
<field name="name">Payment Methods</field>
<field name="res_model">payment.method</field>
<field name="view_mode">tree,kanban,form</field>
<field name="domain">[
('is_primary', '=', True),
('provider_ids.state', '!=', 'disabled')
]
</field>
<field name="context">{'active_test': False}</field>
<field name="domain">[('is_primary', '=', True)]</field>
<field name="context">{'active_test': False, 'search_default_available_pms': 1}</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
No payment methods found for your payment providers.
+6
View File
@@ -0,0 +1,6 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# The codes of the payment methods to activate when Demo is activated.
DEFAULT_PAYMENT_METHOD_CODES = [
'demo',
]
@@ -5,7 +5,6 @@
<field name="name">Demo</field>
<field name="code">demo</field>
<field name="sequence">1</field>
<field name="active">True</field>
<field name="image" type="base64" file="payment_demo/static/img/demo.png"/>
<field name="support_tokenization">True</field>
<field name="support_express_checkout">False</field>
@@ -3,6 +3,8 @@
from odoo import _, api, fields, models
from odoo.exceptions import UserError
from odoo.addons.payment_demo import const
class PaymentProvider(models.Model):
_inherit = 'payment.provider'
@@ -36,3 +38,10 @@ class PaymentProvider(models.Model):
def _check_provider_state(self):
if self.filtered(lambda p: p.code == 'demo' and p.state not in ('test', 'disabled')):
raise UserError(_("Demo providers should never be enabled."))
def _get_default_payment_method_codes(self):
""" Override of `payment` to return the default payment method codes. """
default_codes = super()._get_default_payment_method_codes()
if self.code != 'demo':
return default_codes
return const.DEFAULT_PAYMENT_METHOD_CODES
-1
View File
@@ -12,7 +12,6 @@
'views/payment_stripe_templates.xml',
'views/payment_templates.xml', # Only load the SDK on pages with a payment form.
'data/payment_method_data.xml',
'data/payment_provider_data.xml', # Depends on views/payment_stripe_templates.xml
],
'post_init_hook': 'post_init_hook',
+14
View File
@@ -5,6 +5,20 @@ API_VERSION = '2019-05-16' # The API version of Stripe implemented in this modu
# Stripe proxy URL
PROXY_URL = 'https://stripe.api.odoo.com/api/stripe/'
# The codes of the payment methods to activate when Stripe is activated.
DEFAULT_PAYMENT_METHODS_CODES = [
# Primary payment methods.
'card',
'paypal',
'bancontact',
'ideal',
# Brand payment methods.
'visa',
'mastercard',
'amex',
'discover',
]
# Mapping of payment method codes to Stripe codes.
PAYMENT_METHODS_MAPPING = {
'ach_direct_debit': 'us_bank_account',
@@ -1,34 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo noupdate="1">
<!-- === PRIMARY PAYMENT METHODS === -->
<record id="payment.payment_method_card" model="payment.method">
<field name="active">True</field>
</record>
<record id="payment.payment_method_paypal" model="payment.method">
<field name="active">True</field>
</record>
<record id="payment.payment_method_bancontact" model="payment.method">
<field name="active">True</field>
</record>
<record id="payment.payment_method_ideal" model="payment.method">
<field name="active">True</field>
</record>
<!-- === BRAND PAYMENT METHODS === -->
<record id="payment.payment_method_visa" model="payment.method">
<field name="active">True</field>
</record>
<record id="payment.payment_method_mastercard" model="payment.method">
<field name="active">True</field>
</record>
<record id="payment.payment_method_amex" model="payment.method">
<field name="active">True</field>
</record>
<record id="payment.payment_method_discover" model="payment.method">
<field name="active">True</field>
</record>
</odoo>
@@ -503,3 +503,10 @@ class PaymentProvider(models.Model):
'payment_methods_mapping': const.PAYMENT_METHODS_MAPPING,
}
return json.dumps(inline_form_values)
def _get_default_payment_method_codes(self):
""" Override of `payment` to return the default payment method codes. """
default_codes = super()._get_default_payment_method_codes()
if self.code != 'stripe':
return default_codes
return const.DEFAULT_PAYMENT_METHODS_CODES
+6
View File
@@ -0,0 +1,6 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# The codes of the payment method to activate when Pay on site is activated.
DEFAULT_PAYMENT_METHOD_CODES = [
'pay_on_site',
]
@@ -1,7 +1,7 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models
from odoo.addons.website_sale_picking import const
class PaymentProvider(models.Model):
_inherit = 'payment.provider'
@@ -42,3 +42,10 @@ class PaymentProvider(models.Model):
)
return compatible_providers
def _get_default_payment_method_codes(self):
""" Override of `payment` to return the default payment method codes. """
default_codes = super()._get_default_payment_method_codes()
if self.custom_mode != 'onsite':
return default_codes
return const.DEFAULT_PAYMENT_METHOD_CODES