diff --git a/product_configurator/README.rst b/product_configurator/README.rst index 284d996f1..85eb1450e 100644 --- a/product_configurator/README.rst +++ b/product_configurator/README.rst @@ -17,13 +17,13 @@ Product Configurator :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fproduct--configurator-lightgray.png?logo=github - :target: https://github.com/OCA/product-configurator/tree/17.0/product_configurator + :target: https://github.com/OCA/product-configurator/tree/18.0/product_configurator :alt: OCA/product-configurator .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/product-configurator-17-0/product-configurator-17-0-product_configurator + :target: https://translation.odoo-community.org/projects/product-configurator-18-0/product-configurator-18-0-product_configurator :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/product-configurator&target_branch=17.0 + :target: https://runboat.odoo-community.org/builds?repo=OCA/product-configurator&target_branch=18.0 :alt: Try me on Runboat |badge1| |badge2| |badge3| |badge4| |badge5| @@ -42,7 +42,7 @@ 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 `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -82,6 +82,6 @@ Current `maintainer `__: |maintainer-PCatinean| -This module is part of the `OCA/product-configurator `_ project on GitHub. +This module is part of the `OCA/product-configurator `_ project on GitHub. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/product_configurator/__manifest__.py b/product_configurator/__manifest__.py index 6daf59370..52a389dd9 100644 --- a/product_configurator/__manifest__.py +++ b/product_configurator/__manifest__.py @@ -1,6 +1,6 @@ { "name": "Product Configurator", - "version": "17.0.1.0.1", + "version": "18.0.1.0.0", "category": "Generic Modules/Base", "summary": "Base for product configuration interface modules", "author": "Pledra, Odoo Community Association (OCA)", diff --git a/product_configurator/data/menu_configurable_product.xml b/product_configurator/data/menu_configurable_product.xml index 3823aa8ca..eb36ee49d 100644 --- a/product_configurator/data/menu_configurable_product.xml +++ b/product_configurator/data/menu_configurable_product.xml @@ -24,7 +24,7 @@ Configurable Templates ir.actions.act_window product.template - kanban,tree,form + kanban,list,form Configured Variants ir.actions.act_window product.product - kanban,form,tree + kanban,form,list @@ -88,7 +88,7 @@ Configuration Steps ir.actions.act_window product.config.step - tree,form + list,form Configuration Restrictions ir.actions.act_window product.config.domain - tree,form + list,form Configuration Sessions ir.actions.act_window product.config.session - tree,form + list,form ") - .addClass("o_stat_text o_boolean_button o_not_hover " + val_color) - .text(this.text); - var $hover = $("") - .addClass("o_stat_text o_boolean_button o_hover d-none " + hover_color) - .text(this.hover); + // Create elements using vanilla JS + const valSpan = document.createElement("span"); + valSpan.className = `o_stat_text o_boolean_button o_not_hover ${val_color}`; + valSpan.textContent = this.text; + + const hoverSpan = document.createElement("span"); + hoverSpan.className = `o_stat_text o_boolean_button o_hover d-none ${hover_color}`; + hoverSpan.textContent = this.hover; - $(this.root.el).empty(); - $(this.root.el).append($val).append($hover); + this.root.el.innerHTML = ""; + this.root.el.appendChild(valSpan); + this.root.el.appendChild(hoverSpan); } } diff --git a/product_configurator/tests/test_configuration_rules.py b/product_configurator/tests/test_configuration_rules.py index 58bf1c79c..a6aee9499 100644 --- a/product_configurator/tests/test_configuration_rules.py +++ b/product_configurator/tests/test_configuration_rules.py @@ -4,7 +4,7 @@ from odoo import SUPERUSER_ID, Command from odoo.exceptions import ValidationError from odoo.fields import first -from odoo.tests.common import Form, TransactionCase +from odoo.tests import Form, TransactionCase from odoo.tools.safe_eval import safe_eval diff --git a/product_configurator/views/product_attribute_view.xml b/product_configurator/views/product_attribute_view.xml index 99c7a1b54..eaf9128ed 100644 --- a/product_configurator/views/product_attribute_view.xml +++ b/product_configurator/views/product_attribute_view.xml @@ -1,7 +1,6 @@ - product.config.product.attribute.tree product.attribute @@ -83,7 +82,7 @@ Attributes ir.actions.act_window product.attribute - tree,form + list,form {'flag_config_ok': True} @@ -96,7 +95,6 @@ /> - - tree + list - product.attribute.value.list.inherit product.attribute.value @@ -190,7 +187,7 @@ Attribute Values ir.actions.act_window product.attribute.value - tree,form + list,form - product.configurator.config.step.form product.config.step @@ -23,15 +22,14 @@ product.config.step
- + - +
- product.configurator.domain.form product.config.domain @@ -45,7 +43,7 @@ - + - + @@ -89,7 +87,7 @@ - + - + @@ -125,7 +123,7 @@ product.config.session.tree product.config.session - + @@ -140,7 +138,7 @@ - + @@ -174,14 +172,14 @@ - + - + diff --git a/product_configurator/views/product_view.xml b/product_configurator/views/product_view.xml index ef35cf6be..c1e3a46ce 100644 --- a/product_configurator/views/product_view.xml +++ b/product_configurator/views/product_view.xml @@ -63,7 +63,7 @@ not custom {'flag_config_ok': context.get('default_config_ok', False)} - - - - - + - + - + - +
- + - + - @@ -224,7 +217,7 @@ ]" widget="many2many_tags" /> - +
- +
- +
+ > + +
diff --git a/product_configurator/wizard/product_configurator.py b/product_configurator/wizard/product_configurator.py index 7e5152aba..dfae9ac8f 100644 --- a/product_configurator/wizard/product_configurator.py +++ b/product_configurator/wizard/product_configurator.py @@ -1,8 +1,9 @@ import logging +from itertools import chain from lxml import etree -from odoo import _, api, fields, models, tools +from odoo import _, api, fields, models from odoo.exceptions import UserError, ValidationError from odoo.fields import Command from odoo.tools import frozendict @@ -53,19 +54,17 @@ def _remove_dynamic_fields(self, fields): prefixes = self._prefixes.values() - field_type = type(fields) - - if field_type == list: + if isinstance(fields, list): static_fields = [] - elif field_type == dict: + elif isinstance(fields, dict): static_fields = {} for field_name in fields: if any(prefix in field_name for prefix in prefixes): continue - if field_type == list: + if isinstance(fields, list): static_fields.append(field_name) - elif field_type == dict: + elif isinstance(fields, dict): static_fields[field_name] = fields[field_name] return static_fields @@ -276,12 +275,21 @@ def get_form_vals( # To solve the Multi selection problem removing extra [] if "value_ids" in vals: val_ids = vals["value_ids"][0] - vals["value_ids"] = [[val_ids[0], val_ids[1], tools.flatten(val_ids[2])]] + value_data = val_ids[2] + if not isinstance(value_data, list): + flattened_values = [value_data] + else: + flattened_values = list( + chain.from_iterable( + i if isinstance(i, list) else [i] for i in value_data + ) + ) + vals["value_ids"] = [Command.set(flattened_values)] return vals def apply_onchange_values(self, values, field_names, field_onchange): """Called from web-controller - - original onchage return M2o values in formate + - original onchange returns M2o values in format (attr-value.id, attr-value.name) but on website we need only attr-value.id""" product_tmpl_id = self.env["product.template"].browse( @@ -300,9 +308,10 @@ def apply_onchange_values(self, values, field_names, field_onchange): if not state: state = self.state cfg_vals = self.env["product.attribute.value"] - if values.get("value_ids", []): + value_ids = values.get("value_ids", []) + if value_ids and isinstance(value_ids, list) and value_ids[0]: cfg_vals = self.env["product.attribute.value"].browse( - values.get("value_ids", [])[0][2] + value_ids[0][2] if len(value_ids[0]) > 2 else [] ) if not cfg_vals: cfg_vals = self.value_ids @@ -339,9 +348,6 @@ def apply_onchange_values(self, values, field_names, field_onchange): # Get the unstored values from the client view for k, v in dynamic_fields.items(): attr_id = int(k.split(field_prefix)[1]) - # if isinstance(v, list): - # dynamic_fields[k] = v[0][2] - line_attributes = cfg_step.attribute_line_ids.mapped("attribute_id") if not cfg_step or attr_id in line_attributes.ids: view_attribute_ids.add(attr_id) @@ -455,8 +461,8 @@ def _onchange_product_preset(self): preset_id = self.env["product.product"].browse(preset_id) pta_value_ids = preset_id.product_template_attribute_value_ids attr_value_ids = pta_value_ids.mapped("product_attribute_value_id") - self._origin.value_ids = attr_value_ids - self._origin.price = ( + self.value_ids = attr_value_ids + self.price = ( preset_id and preset_id.lst_price or self.product_tmpl_id.list_price ) @@ -557,7 +563,7 @@ def fields_get(self, allfields=None, write_access=True, attributes=None): res[domain_field] = dict( default_attrs, type="binary", - string="Domain %s" % line.attribute_id.name, + string=f"Domain {line.attribute_id.name}", change_default=True, ) @@ -566,7 +572,7 @@ def fields_get(self, allfields=None, write_access=True, attributes=None): res[field_prefix + str(attribute.id)] = dict( default_attrs, type="many2many" if line.multi else "many2one", - domain="%s" % domain_field, + domain=f"{domain_field}", string=line.attribute_id.name, relation="product.attribute.value", change_default=True, @@ -878,8 +884,10 @@ def create(self, vals_list): ) vals.update({"user_id": self.env.uid, "config_session_id": session.id}) wz_value_ids = vals.get("value_ids", []) + # Check if wz_value_ids is not empty and has a valid structure. if session.value_ids and ( - (wz_value_ids and not wz_value_ids[0][2]) or not wz_value_ids + not wz_value_ids + or (len(wz_value_ids[0]) > 2 and not wz_value_ids[0][2]) ): vals.update({"value_ids": [(6, 0, session.value_ids.ids)]}) return super().create(vals_list) @@ -1106,7 +1114,7 @@ def open_step(self, step): if not step: return wizard_action if isinstance(step, type(self.env["product.config.step.line"])): - step = "%s" % (step.id) + step = f"{step.id}" self.state = step self.config_session_id.config_step = step return wizard_action diff --git a/product_configurator/wizard/product_configurator_view.xml b/product_configurator/wizard/product_configurator_view.xml index cae08cbf7..ec1156ffe 100644 --- a/product_configurator/wizard/product_configurator_view.xml +++ b/product_configurator/wizard/product_configurator_view.xml @@ -47,6 +47,7 @@ name="product_preset_id" invisible="not context.get('allow_preset_selection')" options="{'no_create': True}" + domain="[('product_tmpl_id', '=', product_tmpl_id),('config_preset_ok', '=', True)]" /> - + - +