diff --git a/product_configurator/models/product.py b/product_configurator/models/product.py index 3ceb2915..a0632643 100644 --- a/product_configurator/models/product.py +++ b/product_configurator/models/product.py @@ -340,7 +340,7 @@ def create_variant(self, value_ids, custom_values=None): """ if custom_values is None: custom_values = {} - valid = self.validate_configuration(value_ids, custom_values) + valid = self.validate_configuration(value_ids, custom_values, do_raise=True) if not valid: raise ValidationError(_('Invalid Configuration')) # TODO: Add all custom values to order line instead of product @@ -353,7 +353,7 @@ def create_variant(self, value_ids, custom_values=None): # also a better method for building the domain using the logical # operators is required @api.multi - def value_available(self, attr_val_id, value_ids): + def value_available(self, attr_val_id, value_ids, do_raise=False): """Determines whether the attr_value from the product_template is available for selection given the configuration ids and the dependencies set on the product template @@ -369,19 +369,25 @@ def value_available(self, attr_val_id, value_ids): lambda l: attr_val_id in l.value_ids.ids ) - domains = config_lines.mapped('domain_id').compute_domain() - - for domain in domains: - if domain[1] == 'in': - if not set(domain[2]) & set(value_ids): - return False - else: - if set(domain[2]) & set(value_ids): - return False + for config_line in config_lines: + domains = config_line.mapped('domain_id').compute_domain() + for domain in domains: + if domain[1] == 'in': + if not set(domain[2]) & set(value_ids): + # Don't break if the module has not been upgraded... + if do_raise and 'rule_description' in config_line._fields and config_line.rule_description: + raise ValidationError(config_line.rule_description) + return False + else: + if set(domain[2]) & set(value_ids): + # Don't break if the module has not been upgraded... + if do_raise and 'rule_description' in config_line._fields and config_line.rule_description: + raise ValidationError(config_line.rule_description) + return False return True @api.multi - def validate_configuration(self, value_ids, custom_vals=None, final=True): + def validate_configuration(self, value_ids, custom_vals=None, final=True, do_raise=False): """ Verifies if the configuration values passed via value_ids and custom_vals are valid @@ -407,14 +413,21 @@ def validate_configuration(self, value_ids, custom_vals=None, final=True): common_vals = set(value_ids) & set(line.value_ids.ids) custom_val = custom_vals.get(attr.id) if line.required and not common_vals and not custom_val: + if do_raise: + raise ValidationError(_("No value provided for %s") % line.attribute.name) # TODO: Verify custom value type to be correct return False # Check if all all the values passed are not restricted for val in value_ids: available = self.value_available( - val, [v for v in value_ids if v != val]) + val, [v for v in value_ids if v != val], do_raise=do_raise) if not available: + # if do_raise is True, we may have already raised a specific error message. + # if not, then raise a more generic one... + if do_raise: + attr_val = self.env['product.attribute.value'].browse(val) + raise ValidationError(_("%s can not be selected for %s") % (attr_val.name, attr_val.attribute_id.name)) return False # Check if custom values are allowed @@ -422,6 +435,9 @@ def validate_configuration(self, value_ids, custom_vals=None, final=True): 'custom').mapped('attribute_id').ids if not set(custom_vals.keys()) <= set(custom_attr_ids): + if do_raise: + # TODO: Provide a proper error description for this. + raise ValidationError(_()) return False # Check if there are multiple values passed for non-multi attributes diff --git a/product_configurator/models/product_config.py b/product_configurator/models/product_config.py index 3ee966df..8049fa81 100644 --- a/product_configurator/models/product_config.py +++ b/product_configurator/models/product_config.py @@ -121,6 +121,8 @@ def _get_domain_operators(self): class ProductConfigLine(models.Model): _name = 'product.config.line' + rule_description = fields.Char(string='Rule Description', help='User Displayed error if rule is broken') + # TODO: Prevent config lines having dependencies that are not set in other # config lines # TODO: Prevent circular depdencies: Length -> Color, Color -> Length @@ -211,7 +213,7 @@ def _check_value_ids(self): if not valid: raise ValidationError( _("Values entered for line '%s' generate " - "a incompatible configuration" % cfg_img.name) + "an incompatible configuration" % cfg_img.name) ) @@ -433,7 +435,7 @@ def write(self, vals): for x in self.custom_value_ids } valid = self.product_tmpl_id.validate_configuration( - self.value_ids.ids, custom_val_dict, final=False) + self.value_ids.ids, custom_val_dict, final=False, do_raise=True) if not valid: raise ValidationError(_('Invalid Configuration')) return res diff --git a/product_configurator/views/product_view.xml b/product_configurator/views/product_view.xml index 144b5c9f..07db9410 100644 --- a/product_configurator/views/product_view.xml +++ b/product_configurator/views/product_view.xml @@ -63,6 +63,7 @@ options="{'no_create': True, 'no_create_edit': True}" context="{'show_attribute': False}"/> +