From 8aadce1270d4d7d404f9163e2577e8a9320066ae Mon Sep 17 00:00:00 2001 From: Ricardoalso Date: Mon, 10 Aug 2026 11:00:15 +0200 Subject: [PATCH] [ADD] website_sale_hide_no_variant_attributes Exclude attributes with Variant Creation set to Never from the website variant selector and from combination-exclusion rules, so a hidden informational attribute can no longer gray out or block Add to Cart for a visible variant-defining value. --- .../README.rst | 112 +++++ .../__init__.py | 1 + .../__manifest__.py | 26 + .../models/__init__.py | 1 + .../models/product_template.py | 84 ++++ .../pyproject.toml | 3 + .../readme/CONTRIBUTORS.md | 2 + .../readme/DESCRIPTION.md | 10 + .../readme/USAGE.md | 14 + .../static/description/index.html | 462 ++++++++++++++++++ ...ale_hide_no_variant_attributes_tour.esm.js | 48 ++ .../tests/__init__.py | 2 + ...website_sale_hide_no_variant_attributes.py | 108 ++++ ...te_sale_hide_no_variant_attributes_tour.py | 79 +++ .../views/variant_templates.xml | 25 + 15 files changed, 977 insertions(+) create mode 100644 website_sale_hide_no_variant_attributes/README.rst create mode 100644 website_sale_hide_no_variant_attributes/__init__.py create mode 100644 website_sale_hide_no_variant_attributes/__manifest__.py create mode 100644 website_sale_hide_no_variant_attributes/models/__init__.py create mode 100644 website_sale_hide_no_variant_attributes/models/product_template.py create mode 100644 website_sale_hide_no_variant_attributes/pyproject.toml create mode 100644 website_sale_hide_no_variant_attributes/readme/CONTRIBUTORS.md create mode 100644 website_sale_hide_no_variant_attributes/readme/DESCRIPTION.md create mode 100644 website_sale_hide_no_variant_attributes/readme/USAGE.md create mode 100644 website_sale_hide_no_variant_attributes/static/description/index.html create mode 100644 website_sale_hide_no_variant_attributes/static/tests/tours/website_sale_hide_no_variant_attributes_tour.esm.js create mode 100644 website_sale_hide_no_variant_attributes/tests/__init__.py create mode 100644 website_sale_hide_no_variant_attributes/tests/test_website_sale_hide_no_variant_attributes.py create mode 100644 website_sale_hide_no_variant_attributes/tests/test_website_sale_hide_no_variant_attributes_tour.py create mode 100644 website_sale_hide_no_variant_attributes/views/variant_templates.xml diff --git a/website_sale_hide_no_variant_attributes/README.rst b/website_sale_hide_no_variant_attributes/README.rst new file mode 100644 index 0000000000..2c8940257a --- /dev/null +++ b/website_sale_hide_no_variant_attributes/README.rst @@ -0,0 +1,112 @@ +.. image:: https://odoo-community.org/readme-banner-image + :target: https://odoo-community.org/get-involved?utm_source=readme + :alt: Odoo Community Association + +======================================= +Website Sale Hide No Variant Attributes +======================================= + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:95dfd5888476316eb16cd9f97321a9731b2cee9340c7b1f74d59df275af7f160 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/license-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fe--commerce-lightgray.png?logo=github + :target: https://github.com/OCA/e-commerce/tree/19.0/website_sale_hide_no_variant_attributes + :alt: OCA/e-commerce +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/e-commerce-19-0/e-commerce-19-0-website_sale_hide_no_variant_attributes + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/e-commerce&target_branch=19.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module keeps attributes that never generate a variant (attributes +with their *Variant Creation* setting on *Never*, e.g. purely +informational specs) out of the website product page's variant selector, +and out of the combination-exclusion rules used to gray out incompatible +options. + +Without this module, an informational attribute's value can still +exclude a real, variant-defining value through a configured *Exclude +for* rule, even though the informational attribute itself is never shown +to the shopper as a selectable option — resulting in a visible option +being grayed out because of an attribute the shopper cannot see, with a +tooltip naming it. + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +This module requires no configuration: it applies automatically to every +product attribute whose *Variant Creation* is set to *Never*. + +1. On a product, add an attribute with *Variant Creation* set to *Never* + (e.g. an informational spec such as a material or a care + instruction), alongside your normal variant-defining attributes. +2. Optionally, configure an *Exclude for* rule on one of that + attribute's values, targeting one of the variant-defining values. +3. Open the product page on the website: the informational attribute no + longer appears in the variant selector, and the variant-defining + value targeted by its exclusion rule is no longer grayed out because + of it. +4. Add the product to the cart: the hidden informational attribute never + blocks *Add to Cart*, even when its excluded or default value would + have conflicted with the one visibly selected. + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +------- + +* Camptocamp + +Contributors +------------ + +- `Camptocamp `__: + + - Ricardoalso + +Maintainers +----------- + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +This module is part of the `OCA/e-commerce `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/website_sale_hide_no_variant_attributes/__init__.py b/website_sale_hide_no_variant_attributes/__init__.py new file mode 100644 index 0000000000..0650744f6b --- /dev/null +++ b/website_sale_hide_no_variant_attributes/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/website_sale_hide_no_variant_attributes/__manifest__.py b/website_sale_hide_no_variant_attributes/__manifest__.py new file mode 100644 index 0000000000..41cd7c4892 --- /dev/null +++ b/website_sale_hide_no_variant_attributes/__manifest__.py @@ -0,0 +1,26 @@ +# Copyright 2026 Camptocamp SA (https://www.camptocamp.com). +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +{ + "name": "Website Sale Hide No Variant Attributes", + "summary": "Exclude non-variant-defining attributes from the variant " + "selector and its exclusion rules", + "version": "19.0.1.0.0", + "development_status": "Beta", + "category": "Website", + "website": "https://github.com/OCA/e-commerce", + "author": "Camptocamp, Odoo Community Association (OCA)", + "license": "AGPL-3", + "application": False, + "installable": True, + "depends": [ + "website_sale", + ], + "data": [ + "views/variant_templates.xml", + ], + "assets": { + "web.assets_tests": [ + "website_sale_hide_no_variant_attributes/static/tests/**/*", + ], + }, +} diff --git a/website_sale_hide_no_variant_attributes/models/__init__.py b/website_sale_hide_no_variant_attributes/models/__init__.py new file mode 100644 index 0000000000..e8fa8f6bf1 --- /dev/null +++ b/website_sale_hide_no_variant_attributes/models/__init__.py @@ -0,0 +1 @@ +from . import product_template diff --git a/website_sale_hide_no_variant_attributes/models/product_template.py b/website_sale_hide_no_variant_attributes/models/product_template.py new file mode 100644 index 0000000000..8dac1d6845 --- /dev/null +++ b/website_sale_hide_no_variant_attributes/models/product_template.py @@ -0,0 +1,84 @@ +# Copyright 2026 Camptocamp SA (https://www.camptocamp.com). +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import models + + +class ProductTemplate(models.Model): + _inherit = "product.template" + + def _get_attribute_exclusions( + self, parent_combination=None, parent_name=None, combination_ids=None + ): + result = super()._get_attribute_exclusions( + parent_combination=parent_combination, + parent_name=parent_name, + combination_ids=combination_ids, + ) + no_variant_ptav_ids = set( + self.attribute_line_ids.filtered( + lambda line: line.attribute_id.create_variant == "no_variant" + ).product_template_value_ids.ids + ) + if not no_variant_ptav_ids: + return result + + result["exclusions"] = { + ptav_id: ( + [] + if ptav_id in no_variant_ptav_ids + else [ + excluded_id + for excluded_id in excluded_ids + if excluded_id not in no_variant_ptav_ids + ] + ) + for ptav_id, excluded_ids in result["exclusions"].items() + } + result["parent_exclusions"] = { + parent_ptav_id: [ + excluded_id + for excluded_id in excluded_ids + if excluded_id not in no_variant_ptav_ids + ] + for parent_ptav_id, excluded_ids in result["parent_exclusions"].items() + } + result["mapped_attribute_names"] = { + ptav_id: name + for ptav_id, name in result["mapped_attribute_names"].items() + if ptav_id not in no_variant_ptav_ids + } + return result + + def _get_combination_info( + self, + combination=False, + product_id=False, + add_qty=1.0, + uom_id=False, + only_template=False, + ): + combination_info = super()._get_combination_info( + combination=combination, + product_id=product_id, + add_qty=add_qty, + uom_id=uom_id, + only_template=only_template, + ) + if combination_info.get("is_combination_possible"): + return combination_info + # Since no_variant attributes are never shown to the shopper (see the + # website_sale.variants override), they can never be submitted or + # corrected from the website, so they must not be able to block Add + # to Cart either: a missing or template-picked no_variant value would + # otherwise fail the exact-attribute-match/exclusion check in + # `_is_combination_possible` with no way for the shopper to fix it. + resolved_combination = ( + combination_info.get("combination") + or self.env["product.template.attribute.value"] + ) + combination_info["is_combination_possible"] = self._is_combination_possible( + combination=resolved_combination._without_no_variant_attributes(), + ignore_no_variant=True, + ) + return combination_info diff --git a/website_sale_hide_no_variant_attributes/pyproject.toml b/website_sale_hide_no_variant_attributes/pyproject.toml new file mode 100644 index 0000000000..4231d0cccb --- /dev/null +++ b/website_sale_hide_no_variant_attributes/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/website_sale_hide_no_variant_attributes/readme/CONTRIBUTORS.md b/website_sale_hide_no_variant_attributes/readme/CONTRIBUTORS.md new file mode 100644 index 0000000000..f27dfd8053 --- /dev/null +++ b/website_sale_hide_no_variant_attributes/readme/CONTRIBUTORS.md @@ -0,0 +1,2 @@ +- [Camptocamp](https://www.camptocamp.com/): + - Ricardoalso \<\> diff --git a/website_sale_hide_no_variant_attributes/readme/DESCRIPTION.md b/website_sale_hide_no_variant_attributes/readme/DESCRIPTION.md new file mode 100644 index 0000000000..754d12ee5c --- /dev/null +++ b/website_sale_hide_no_variant_attributes/readme/DESCRIPTION.md @@ -0,0 +1,10 @@ +This module keeps attributes that never generate a variant (attributes with +their *Variant Creation* setting on *Never*, e.g. purely informational specs) +out of the website product page's variant selector, and out of the +combination-exclusion rules used to gray out incompatible options. + +Without this module, an informational attribute's value can still exclude a +real, variant-defining value through a configured *Exclude for* rule, even +though the informational attribute itself is never shown to the shopper as a +selectable option — resulting in a visible option being grayed out because of +an attribute the shopper cannot see, with a tooltip naming it. diff --git a/website_sale_hide_no_variant_attributes/readme/USAGE.md b/website_sale_hide_no_variant_attributes/readme/USAGE.md new file mode 100644 index 0000000000..bd95cd55c8 --- /dev/null +++ b/website_sale_hide_no_variant_attributes/readme/USAGE.md @@ -0,0 +1,14 @@ +This module requires no configuration: it applies automatically to every +product attribute whose *Variant Creation* is set to *Never*. + +1. On a product, add an attribute with *Variant Creation* set to *Never* + (e.g. an informational spec such as a material or a care instruction), + alongside your normal variant-defining attributes. +2. Optionally, configure an *Exclude for* rule on one of that attribute's + values, targeting one of the variant-defining values. +3. Open the product page on the website: the informational attribute no + longer appears in the variant selector, and the variant-defining value + targeted by its exclusion rule is no longer grayed out because of it. +4. Add the product to the cart: the hidden informational attribute never + blocks *Add to Cart*, even when its excluded or default value would have + conflicted with the one visibly selected. diff --git a/website_sale_hide_no_variant_attributes/static/description/index.html b/website_sale_hide_no_variant_attributes/static/description/index.html new file mode 100644 index 0000000000..cf73154a2d --- /dev/null +++ b/website_sale_hide_no_variant_attributes/static/description/index.html @@ -0,0 +1,462 @@ + + + + + +Website Sale Hide No Variant Attributes + + + +
+ + + +Odoo Community Association + +
+

Website Sale Hide No Variant Attributes

+ +

Beta License: AGPL-3 OCA/e-commerce Translate me on Weblate Try me on Runboat

+

This module keeps attributes that never generate a variant (attributes +with their Variant Creation setting on Never, e.g. purely +informational specs) out of the website product page’s variant selector, +and out of the combination-exclusion rules used to gray out incompatible +options.

+

Without this module, an informational attribute’s value can still +exclude a real, variant-defining value through a configured Exclude +for rule, even though the informational attribute itself is never shown +to the shopper as a selectable option — resulting in a visible option +being grayed out because of an attribute the shopper cannot see, with a +tooltip naming it.

+

Table of contents

+ +
+

Usage

+

This module requires no configuration: it applies automatically to every +product attribute whose Variant Creation is set to Never.

+
    +
  1. On a product, add an attribute with Variant Creation set to Never +(e.g. an informational spec such as a material or a care +instruction), alongside your normal variant-defining attributes.
  2. +
  3. Optionally, configure an Exclude for rule on one of that +attribute’s values, targeting one of the variant-defining values.
  4. +
  5. Open the product page on the website: the informational attribute no +longer appears in the variant selector, and the variant-defining +value targeted by its exclusion rule is no longer grayed out because +of it.
  6. +
  7. Add the product to the cart: the hidden informational attribute never +blocks Add to Cart, even when its excluded or default value would +have conflicted with the one visibly selected.
  8. +
+
+
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Camptocamp
  • +
+
+ +
+

Maintainers

+

This module is maintained by the OCA.

+ +Odoo Community Association + +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

This module is part of the OCA/e-commerce project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+
+ + diff --git a/website_sale_hide_no_variant_attributes/static/tests/tours/website_sale_hide_no_variant_attributes_tour.esm.js b/website_sale_hide_no_variant_attributes/static/tests/tours/website_sale_hide_no_variant_attributes_tour.esm.js new file mode 100644 index 0000000000..fe9e19b849 --- /dev/null +++ b/website_sale_hide_no_variant_attributes/static/tests/tours/website_sale_hide_no_variant_attributes_tour.esm.js @@ -0,0 +1,48 @@ +// Copyright 2026 Camptocamp SA (https://www.camptocamp.com). +// License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +import {registry} from "@web/core/registry"; + +registry.category("web_tour.tours").add("website_sale_hide_no_variant_attributes", { + steps: () => [ + { + content: + "The informational (non-variant-defining) attribute must not be" + + " rendered in the variant selector.", + trigger: + 'ul.js_add_cart_variants:not(:has(li.variant_attribute[data-attribute-name="Test Material"]))', + }, + { + content: "The variant-defining attribute is rendered normally.", + trigger: + 'li.variant_attribute[data-attribute-name="Test Size"] ' + + 'input[data-value-name="Large"]', + }, + { + content: "Select the size value excluded by the hidden material value.", + trigger: + 'li.variant_attribute[data-attribute-name="Test Size"] ' + + 'input[data-value-name="Large"]', + run: "click", + }, + { + content: + "The selected size is not grayed out by the hidden material's" + + " exclusion rule.", + trigger: + 'li.variant_attribute[data-attribute-name="Test Size"] ' + + 'label:not(.css_not_available):has(input[data-value-name="Large"])', + }, + { + content: "Add the product to the cart.", + trigger: "#add_to_cart", + run: "click", + }, + { + content: + "The product was added to the cart, confirming the hidden" + + " material attribute never blocked Add to Cart.", + trigger: "sup.my_cart_quantity:contains(1)", + }, + ], +}); diff --git a/website_sale_hide_no_variant_attributes/tests/__init__.py b/website_sale_hide_no_variant_attributes/tests/__init__.py new file mode 100644 index 0000000000..9063ef7969 --- /dev/null +++ b/website_sale_hide_no_variant_attributes/tests/__init__.py @@ -0,0 +1,2 @@ +from . import test_website_sale_hide_no_variant_attributes +from . import test_website_sale_hide_no_variant_attributes_tour diff --git a/website_sale_hide_no_variant_attributes/tests/test_website_sale_hide_no_variant_attributes.py b/website_sale_hide_no_variant_attributes/tests/test_website_sale_hide_no_variant_attributes.py new file mode 100644 index 0000000000..f84be050f2 --- /dev/null +++ b/website_sale_hide_no_variant_attributes/tests/test_website_sale_hide_no_variant_attributes.py @@ -0,0 +1,108 @@ +# Copyright 2026 Camptocamp SA (https://www.camptocamp.com). +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + + +from odoo import Command +from odoo.tests import TransactionCase + +from odoo.addons.website_sale.tests.common import MockRequest + + +class TestWebsiteSaleHideNoVariantAttributes(TransactionCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.variant_attribute = cls.env["product.attribute"].create( + { + "name": "Test Size", + "create_variant": "always", + "value_ids": [ + Command.create({"name": "Small"}), + Command.create({"name": "Large"}), + ], + } + ) + cls.informational_attribute = cls.env["product.attribute"].create( + { + "name": "Test Material", + "create_variant": "no_variant", + "value_ids": [ + Command.create({"name": "Cotton"}), + Command.create({"name": "Wool"}), + ], + } + ) + cls.product = cls.env["product.template"].create( + { + "name": "Test product with mixed attributes", + "attribute_line_ids": [ + Command.create( + { + "attribute_id": cls.variant_attribute.id, + "value_ids": [ + Command.set(cls.variant_attribute.value_ids.ids) + ], + } + ), + Command.create( + { + "attribute_id": cls.informational_attribute.id, + "value_ids": [ + Command.set(cls.informational_attribute.value_ids.ids) + ], + } + ), + ], + } + ) + cls.variant_ptav_large = cls.product.attribute_line_ids.filtered( + lambda line: line.attribute_id == cls.variant_attribute + ).product_template_value_ids.filtered(lambda ptav: ptav.name == "Large") + cls.informational_ptav_wool = cls.product.attribute_line_ids.filtered( + lambda line: line.attribute_id == cls.informational_attribute + ).product_template_value_ids.filtered(lambda ptav: ptav.name == "Wool") + cls.informational_ptav_wool.exclude_for = [ + Command.create( + { + "product_tmpl_id": cls.product.id, + "value_ids": [Command.link(cls.variant_ptav_large.id)], + } + ) + ] + cls.website = cls.env["website"].get_current_website() + + def test_exclusions_ignore_informational_attribute(self): + exclusions = self.product._get_attribute_exclusions()["exclusions"] + self.assertIn(self.informational_ptav_wool.id, exclusions) + self.assertEqual(exclusions[self.informational_ptav_wool.id], []) + for excluded_ids in exclusions.values(): + self.assertNotIn(self.variant_ptav_large.id, excluded_ids) + + def test_mapped_attribute_names_ignore_informational_attribute(self): + mapped_names = self.product._get_attribute_exclusions()[ + "mapped_attribute_names" + ] + self.assertNotIn(self.informational_ptav_wool.id, mapped_names) + self.assertIn(self.variant_ptav_large.id, mapped_names) + + def test_combination_info_ignores_missing_informational_attribute(self): + # Mimics a combination check triggered after page load: since the + # informational attribute's input is never rendered, the browser can + # never submit a value for it again, so the combination only carries + # the variant-defining value. + with MockRequest(self.env, website=self.website): + combination_info = self.product._get_combination_info( + combination=self.variant_ptav_large + ) + self.assertTrue(combination_info["is_combination_possible"]) + + def test_combination_info_ignores_conflicting_informational_default(self): + # Mimics the very first page render, where the server still picks a + # default value for the hidden informational attribute; here that + # default happens to be the "Wool" value excluded by the rule above. + combination = self.variant_ptav_large | self.informational_ptav_wool + with MockRequest(self.env, website=self.website): + combination_info = self.product._get_combination_info( + combination=combination + ) + self.assertTrue(combination_info["is_combination_possible"]) diff --git a/website_sale_hide_no_variant_attributes/tests/test_website_sale_hide_no_variant_attributes_tour.py b/website_sale_hide_no_variant_attributes/tests/test_website_sale_hide_no_variant_attributes_tour.py new file mode 100644 index 0000000000..5d01cf42a3 --- /dev/null +++ b/website_sale_hide_no_variant_attributes/tests/test_website_sale_hide_no_variant_attributes_tour.py @@ -0,0 +1,79 @@ +# Copyright 2026 Camptocamp SA (https://www.camptocamp.com). +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import Command +from odoo.tests import HttpCase, tagged + + +@tagged("post_install", "-at_install") +class TestWebsiteSaleHideNoVariantAttributesTour(HttpCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.variant_attribute = cls.env["product.attribute"].create( + { + "name": "Test Size", + "create_variant": "always", + "value_ids": [ + Command.create({"name": "Small"}), + Command.create({"name": "Large"}), + ], + } + ) + cls.informational_attribute = cls.env["product.attribute"].create( + { + "name": "Test Material", + "create_variant": "no_variant", + "value_ids": [ + Command.create({"name": "Cotton"}), + Command.create({"name": "Wool"}), + ], + } + ) + cls.product = cls.env["product.template"].create( + { + "name": "Test product with mixed attributes", + "sale_ok": True, + "is_published": True, + "list_price": 100.0, + "attribute_line_ids": [ + Command.create( + { + "attribute_id": cls.variant_attribute.id, + "value_ids": [ + Command.set(cls.variant_attribute.value_ids.ids) + ], + } + ), + Command.create( + { + "attribute_id": cls.informational_attribute.id, + "value_ids": [ + Command.set(cls.informational_attribute.value_ids.ids) + ], + } + ), + ], + } + ) + variant_ptav_large = cls.product.attribute_line_ids.filtered( + lambda line: line.attribute_id == cls.variant_attribute + ).product_template_value_ids.filtered(lambda ptav: ptav.name == "Large") + informational_ptav_wool = cls.product.attribute_line_ids.filtered( + lambda line: line.attribute_id == cls.informational_attribute + ).product_template_value_ids.filtered(lambda ptav: ptav.name == "Wool") + informational_ptav_wool.exclude_for = [ + Command.create( + { + "product_tmpl_id": cls.product.id, + "value_ids": [Command.link(variant_ptav_large.id)], + } + ) + ] + + def test_hide_no_variant_attributes(self): + self.start_tour( + self.product.website_url, + "website_sale_hide_no_variant_attributes", + login="admin", + ) diff --git a/website_sale_hide_no_variant_attributes/views/variant_templates.xml b/website_sale_hide_no_variant_attributes/views/variant_templates.xml new file mode 100644 index 0000000000..3844a328c5 --- /dev/null +++ b/website_sale_hide_no_variant_attributes/views/variant_templates.xml @@ -0,0 +1,25 @@ + + + +