From fdb6f62742dbc135bc2d422e270bf3f5657d9f91 Mon Sep 17 00:00:00 2001 From: "Valeriya(vchu)" Date: Tue, 24 Oct 2023 17:09:48 +0200 Subject: [PATCH] [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) --- addons/payment/models/payment_method.py | 17 ++++++- addons/payment/models/payment_provider.py | 46 +++++++++++++++++-- addons/payment/tests/common.py | 10 ++-- addons/payment/views/payment_method_views.xml | 14 +++--- addons/payment_demo/const.py | 6 +++ .../payment_demo/data/payment_method_data.xml | 1 - .../payment_demo/models/payment_provider.py | 9 ++++ addons/payment_stripe/__manifest__.py | 1 - addons/payment_stripe/const.py | 14 ++++++ .../data/payment_method_data.xml | 34 -------------- .../payment_stripe/models/payment_provider.py | 7 +++ addons/website_sale_picking/const.py | 6 +++ .../models/payment_provider.py | 9 +++- 13 files changed, 121 insertions(+), 53 deletions(-) create mode 100644 addons/payment_demo/const.py delete mode 100644 addons/payment_stripe/data/payment_method_data.xml create mode 100644 addons/website_sale_picking/const.py diff --git a/addons/payment/models/payment_method.py b/addons/payment/models/payment_method.py index 6d7368653c8..c737531ebab 100644 --- a/addons/payment/models/payment_method.py +++ b/addons/payment/models/payment_method.py @@ -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 === # diff --git a/addons/payment/models/payment_provider.py b/addons/payment/models/payment_provider.py index 09ea73c7931..e70ef44ccd4 100644 --- a/addons/payment/models/payment_provider.py +++ b/addons/payment/models/payment_provider.py @@ -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 [] diff --git a/addons/payment/tests/common.py b/addons/payment/tests/common.py index 84b4792ff60..222c4c9cb43 100644 --- a/addons/payment/tests/common.py +++ b/addons/payment/tests/common.py @@ -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 = """
@@ -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 diff --git a/addons/payment/views/payment_method_views.xml b/addons/payment/views/payment_method_views.xml index fb76e125971..b71cee38836 100644 --- a/addons/payment/views/payment_method_views.xml +++ b/addons/payment/views/payment_method_views.xml @@ -89,7 +89,7 @@ payment.method.tree payment.method - + @@ -130,6 +130,10 @@ + @@ -138,12 +142,8 @@ Payment Methods payment.method tree,kanban,form - [ - ('is_primary', '=', True), - ('provider_ids.state', '!=', 'disabled') - ] - - {'active_test': False} + [('is_primary', '=', True)] + {'active_test': False, 'search_default_available_pms': 1}

No payment methods found for your payment providers. diff --git a/addons/payment_demo/const.py b/addons/payment_demo/const.py new file mode 100644 index 00000000000..28c46ba53cc --- /dev/null +++ b/addons/payment_demo/const.py @@ -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', +] diff --git a/addons/payment_demo/data/payment_method_data.xml b/addons/payment_demo/data/payment_method_data.xml index 5b713e30450..46b0d6f83a9 100644 --- a/addons/payment_demo/data/payment_method_data.xml +++ b/addons/payment_demo/data/payment_method_data.xml @@ -5,7 +5,6 @@ Demo demo 1 - True True False diff --git a/addons/payment_demo/models/payment_provider.py b/addons/payment_demo/models/payment_provider.py index 021a1164b07..1521f01c49e 100644 --- a/addons/payment_demo/models/payment_provider.py +++ b/addons/payment_demo/models/payment_provider.py @@ -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 diff --git a/addons/payment_stripe/__manifest__.py b/addons/payment_stripe/__manifest__.py index dd4d8f524d7..955ac84d34a 100644 --- a/addons/payment_stripe/__manifest__.py +++ b/addons/payment_stripe/__manifest__.py @@ -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', diff --git a/addons/payment_stripe/const.py b/addons/payment_stripe/const.py index efec33c1c85..f6391503d5f 100644 --- a/addons/payment_stripe/const.py +++ b/addons/payment_stripe/const.py @@ -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', diff --git a/addons/payment_stripe/data/payment_method_data.xml b/addons/payment_stripe/data/payment_method_data.xml deleted file mode 100644 index b8298c5aa85..00000000000 --- a/addons/payment_stripe/data/payment_method_data.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - True - - - True - - - True - - - True - - - - - - True - - - True - - - True - - - True - - - diff --git a/addons/payment_stripe/models/payment_provider.py b/addons/payment_stripe/models/payment_provider.py index e3b448afc2c..8146b9b6628 100644 --- a/addons/payment_stripe/models/payment_provider.py +++ b/addons/payment_stripe/models/payment_provider.py @@ -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 diff --git a/addons/website_sale_picking/const.py b/addons/website_sale_picking/const.py new file mode 100644 index 00000000000..6c2e34cd2b2 --- /dev/null +++ b/addons/website_sale_picking/const.py @@ -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', +] diff --git a/addons/website_sale_picking/models/payment_provider.py b/addons/website_sale_picking/models/payment_provider.py index 8458c12725e..cb6d799af98 100644 --- a/addons/website_sale_picking/models/payment_provider.py +++ b/addons/website_sale_picking/models/payment_provider.py @@ -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