[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:
@@ -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 === #
|
||||
|
||||
@@ -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 []
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user