diff --git a/product_configurator_website_fix/__init__.py b/product_configurator_website_fix/__init__.py new file mode 100644 index 0000000..0650744 --- /dev/null +++ b/product_configurator_website_fix/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/product_configurator_website_fix/__manifest__.py b/product_configurator_website_fix/__manifest__.py new file mode 100644 index 0000000..6fcbf2f --- /dev/null +++ b/product_configurator_website_fix/__manifest__.py @@ -0,0 +1,9 @@ +{ + "name": "Product Configurator Website Fix", + "version": "17.0.1.0.0", + "summary": "Avoid cartesian product explosion on /shop for configurable products", + "license": "AGPL-3", + "category": "website", + "depends": ["website_sale", "product_configurator"], + "installable": True, +} diff --git a/product_configurator_website_fix/models/__init__.py b/product_configurator_website_fix/models/__init__.py new file mode 100644 index 0000000..e8fa8f6 --- /dev/null +++ b/product_configurator_website_fix/models/__init__.py @@ -0,0 +1 @@ +from . import product_template diff --git a/product_configurator_website_fix/models/product_template.py b/product_configurator_website_fix/models/product_template.py new file mode 100644 index 0000000..2b8e47a --- /dev/null +++ b/product_configurator_website_fix/models/product_template.py @@ -0,0 +1,35 @@ +from odoo import models + + +class ProductTemplate(models.Model): + _inherit = "product.template" + + def _get_possible_combinations(self, parent_combination=None, necessary_values=None): + """Configurable templates keep no variants on purpose (see + ``product_configurator._create_variant_ids``). For a non-dynamic + template core treats a combination without an existing variant as + impossible, so the generator walks the *whole* cartesian product + without ever yielding. Short-circuit it. + """ + self.ensure_one() + if self.config_ok: + return iter(()) + return super()._get_possible_combinations(parent_combination, necessary_values) + + def _get_first_possible_combination( + self, parent_combination=None, necessary_values=None + ): + self.ensure_one() + if self.config_ok: + return self.env["product.template.attribute.value"] + return super()._get_first_possible_combination( + parent_combination, necessary_values + ) + + def _is_add_to_cart_possible(self, parent_combination=None): + """A configurable product is always addable: the variant is created + when the configuration session is validated.""" + self.ensure_one() + if self.config_ok: + return self.active and self._can_be_added_to_cart() + return super()._is_add_to_cart_possible(parent_combination)