From fb5d191ebb062d2446053e49dd866d333187d6ef Mon Sep 17 00:00:00 2001 From: Vandan Pandeji Date: Tue, 4 Jun 2024 14:47:40 +0530 Subject: [PATCH] [IMP]product_configurator:Allow Reset and Back with required fields that are blank and Configuration Session Search More issues when restrictions are set. --- .../models/product_attribute.py | 76 +++++++++++++++++++ .../static/src/js/form_widgets.esm.js | 15 ++-- .../wizard/product_configurator.py | 4 +- .../wizard/product_configurator_view.xml | 1 + 4 files changed, 86 insertions(+), 10 deletions(-) diff --git a/product_configurator/models/product_attribute.py b/product_configurator/models/product_attribute.py index 76dd4630f0..1e7938e636 100644 --- a/product_configurator/models/product_attribute.py +++ b/product_configurator/models/product_attribute.py @@ -310,6 +310,82 @@ def _compute_display_name(self): ) rec.display_name = name or rec.display_name + @api.model + def web_search_read( + self, domain, specification, offset=0, limit=None, order=None, count_limit=None + ): + """Use name_search as a domain restriction for the frontend to show + only values set on the product template taking all the configuration + restrictions into account. + + TODO: This only works when activating the selection not when typing + """ + if self.env.context.get("wizard_id"): + wiz_id = self.env["product.configurator"].browse( + self.env.context.get("wizard_id") + ) + if ( + wiz_id.domain_attr_ids + and self.env.context.get("field_name") == wiz_id.dyn_field_value + ): + if self.env.context.get("is_m2m"): + if len(domain) > 2: + vals1 = domain[-1] + vals2 = domain[1] + if vals2 and vals1: + vals = list(set(vals2[2]) - set(vals1[2])) + domain = [("id", "in", vals)] + else: + domain = [("id", "in", wiz_id.domain_attr_ids.ids)] + + elif wiz_id.domain_attr_2_ids and ( + self.env.context.get("field_name") == wiz_id.dyn_field_2_value + or not wiz_id.dyn_field_2_value + ): + domain = [("id", "in", wiz_id.domain_attr_2_ids.ids)] + + product_tmpl_id = self.env.context.get("_cfg_product_tmpl_id") + if product_tmpl_id: + # TODO: Avoiding browse here could be a good performance enhancer + product_tmpl = self.env["product.template"].browse(product_tmpl_id) + tmpl_vals = product_tmpl.attribute_line_ids.mapped("value_ids") + attr_restrict_ids = [] + preset_val_ids = [] + new_args = [] + for arg in domain: + # Restrict values only to value_ids set on product_template + if arg[0] == "id" and arg[1] == "not in": + preset_val_ids = arg[2] + # TODO: Check if all values are available for configuration + else: + new_args.append(arg) + val_ids = set(tmpl_vals.ids) + if preset_val_ids: + val_ids -= set(arg[2]) + val_ids = self.env["product.config.session"].values_available( + val_ids, preset_val_ids, product_tmpl_id=product_tmpl_id + ) + new_args.append(("id", "in", val_ids)) + mono_tmpl_lines = product_tmpl.attribute_line_ids.filtered( + lambda line: not line.multi + ) + for line in mono_tmpl_lines: + line_val_ids = set(line.mapped("value_ids").ids) + if line_val_ids & set(preset_val_ids): + attr_restrict_ids.append(line.attribute_id.id) + if attr_restrict_ids: + new_args.append(("attribute_id", "not in", attr_restrict_ids)) + domain = new_args + res = super().web_search_read( + domain, + specification, + offset=offset, + limit=limit, + order=order, + count_limit=count_limit, + ) + return res + @api.model def name_search(self, name="", args=None, operator="ilike", limit=100): """Use name_search as a domain restriction for the frontend to show diff --git a/product_configurator/static/src/js/form_widgets.esm.js b/product_configurator/static/src/js/form_widgets.esm.js index 69ebf52c74..81efb2449e 100644 --- a/product_configurator/static/src/js/form_widgets.esm.js +++ b/product_configurator/static/src/js/form_widgets.esm.js @@ -26,14 +26,13 @@ patch(FormController.prototype, { } }); }, - // Async beforeExecuteActionButton(clickParams) { - // console.log("beforeExecuteActionButton", clickParams); - // if (clickParams.special === "no_save") { - // delete clickParams.special; - // return true; - // } - // return super.beforeExecuteActionButton(...arguments); - // }, + async beforeExecuteActionButton(clickParams) { + if (clickParams.special === "no_save") { + delete clickParams.special; + return true; + } + return super.beforeExecuteActionButton(...arguments); + }, }); patch(ListController.prototype, { diff --git a/product_configurator/wizard/product_configurator.py b/product_configurator/wizard/product_configurator.py index a9a9b815af..1363393f4f 100644 --- a/product_configurator/wizard/product_configurator.py +++ b/product_configurator/wizard/product_configurator.py @@ -963,7 +963,6 @@ def action_next_step(self): wizard_action = self.with_context( allow_preset_selection=False ).get_wizard_action(wizard=self) - if not self.product_tmpl_id: return wizard_action @@ -1041,7 +1040,6 @@ def get_wizard_action(self, view_cache=False, wizard=None): ) if wizard: ctx.update({"wizard_id": wizard.id, "wizard_id_view_ref": wizard.id}) - wizard_action = { "type": "ir.actions.act_window", "res_model": self._name, @@ -1058,6 +1056,8 @@ def get_wizard_action(self, view_cache=False, wizard=None): } if wizard: wizard_action.update({"res_id": wizard.id}) + if self and not self.state: + self.state = "select" return wizard_action def open_step(self, step): diff --git a/product_configurator/wizard/product_configurator_view.xml b/product_configurator/wizard/product_configurator_view.xml index a3bc6aafc7..806c432f25 100644 --- a/product_configurator/wizard/product_configurator_view.xml +++ b/product_configurator/wizard/product_configurator_view.xml @@ -14,6 +14,7 @@ name="action_reset" confirm="Are you sure? This will remove your current configuration for this template!" class="oe_highlight" + special="no_save" invisible="not product_tmpl_id or state == 'select'" />