From 0d389cbebfc7db0b9fddc41c613dfc5d235757aa Mon Sep 17 00:00:00 2001 From: Francois Poizat Date: Thu, 7 Mar 2024 17:09:07 +0100 Subject: [PATCH] ADD Refactoring getting bom date from bom and input line --- mrp_bom_configurable/models/input_line.py | 86 ++---------------- mrp_bom_configurable/models/mrp_bom.py | 15 +++- .../models/mrp_bom_configured.py | 13 ++- mrp_bom_configurable/models/mrp_bom_line.py | 87 ++++++++++--------- 4 files changed, 71 insertions(+), 130 deletions(-) diff --git a/mrp_bom_configurable/models/input_line.py b/mrp_bom_configurable/models/input_line.py index 9c20c9d7aef..69f342ee912 100644 --- a/mrp_bom_configurable/models/input_line.py +++ b/mrp_bom_configurable/models/input_line.py @@ -31,86 +31,19 @@ def ui_clone(self): vals = {"name": "%s copy" % self.name} self.copy(vals) - def _get_filtered_components_from_values(self): + def _get_input_line_values(self): elements = dict() - conf_names = dict() for elm in self._get_config_elements(): if self._fields[elm].type == "many2one": - value = self[elm].id + value = self[elm].display_name else: value = self[elm] elements[elm] = value - conf_names[self._fields[elm].string] = value - lines = self.bom_id.check_domain(elements) - return lines, conf_names - - def get_values_with_field_desc(self): - self.ensure_one() - values = [ - { - "name": "name", - "string": "Name", - "value": self.name, - } - ] - for field in self._get_config_elements(): - field_vals = { - "name": field, - "string": self._fields[field].string, - "type": self._fields[field].type, - } - - if self._fields[field].type == "many2one": - fieldinfo = self._fields[field] - field_vals["value"] = self[field].id - field_vals["display_name"] = self[field].display_name - field_vals["model"] = fieldinfo.comodel_name - if isinstance(fieldinfo.domain, list) or fieldinfo.domain is None: - field_vals["domain"] = fieldinfo.domain - else: - field_vals["domain"] = fieldinfo.domain(self) - else: - field_vals["value"] = self[field] - - if self._fields[field].type == "selection": - if self._fields[field].related: - field_vals["possible_values"] = self._fields[field].selection(self) - else: - field_vals["possible_values"] = self._fields[field].selection - - values.append(field_vals) - - return values + return elements def check_one_data(self): pass - def _create_report_dict_from_line(self, line): - return { - "id": line.id, - "component": line.product_id.display_name, - "quantity": line.product_qty, - "unit": line.product_uom_id.display_name, - } - - def _create_bom_data_preview(self): - self.ensure_one() - lines, conf_names = self._get_filtered_components_from_values() - return { - "config_data": [ - {"name": key, "display_name": conf_names[key]} for key in conf_names - ], - "data": [self._create_report_dict_from_line(line) for line in lines], - } - - def populate_bom_data_preview(self): - self.bom_data_preview = self._create_bom_data_preview() - - def get_json(self): - self.ensure_one() - self.populate_bom_data_preview() - return self.bom_data_preview - def open_form_pop_up(self): self.ensure_one() return { @@ -124,19 +57,14 @@ def open_form_pop_up(self): def create_bom_line_data(self): self.ensure_one() - components, _ = self._get_filtered_components_from_values() + components = self.bom_id.get_bom_configured_data(self) bom_lines_data = [] for comp in components: - quantity = ( - comp.compute_qty_from_formula(self) - if comp.use_formula_compute_qty - else comp.product_qty - ) bom_line_data = { - "product_tmpl_id": comp.product_tmpl_id, - "product_id": comp.product_id, - "product_qty": quantity, + "product_tmpl_id": comp["line"].product_tmpl_id, + "product_id": comp["line"].product_id, + "product_qty": comp["product_qty"], } bom_lines_data.append(bom_line_data) diff --git a/mrp_bom_configurable/models/mrp_bom.py b/mrp_bom_configurable/models/mrp_bom.py index 17df59ce33e..7b1333118bb 100644 --- a/mrp_bom_configurable/models/mrp_bom.py +++ b/mrp_bom_configurable/models/mrp_bom.py @@ -14,13 +14,22 @@ class MrpBom(models.Model): required=True, ) - def check_domain(self, values): + def get_bom_configured_data(self, input_line, quantity=1.0): result = [] + values = input_line._get_input_line_values() for line in self.bom_line_ids.filtered(lambda s: s.execute(values)): + line_quantity = ( + line.compute_qty_from_formula(input_line) + if line.use_formula_compute_qty + else line.product_qty + ) * quantity if line.child_bom_id: - result = result + line.child_bom_id.check_domain(values) + result = result + line.child_bom_id.get_bom_configured_data(input_line, line_quantity) else: - result.append(line) + result.append({ + "line": line, + "product_qty": line_quantity, + }) return result diff --git a/mrp_bom_configurable/models/mrp_bom_configured.py b/mrp_bom_configurable/models/mrp_bom_configured.py index af899379f3c..82de3018fea 100644 --- a/mrp_bom_configurable/models/mrp_bom_configured.py +++ b/mrp_bom_configurable/models/mrp_bom_configured.py @@ -36,21 +36,18 @@ def _default_product_id(self): def _default_line_ids(self): input_line_id = self.env["input.line"].browse(self.env.context.get("active_id")) - components, _ = input_line_id._get_filtered_components_from_values() + components = input_line_id.create_bom_line_data() lines = [] + # TODO(franz): since quantity is tree dependent _get_filtered_components_from_values + # should take this into account to allow for proper quantity computation for comp in components: - quantity = ( - comp.compute_qty_from_formula(input_line_id) - if comp.use_formula_compute_qty - else comp.product_qty - ) # price += quantity * comp.product_id.lst_price lines.append( self.env["mrp.bom.line.configured"] .create( { - "product_id": comp.product_id.id, - "product_qty": quantity, + "product_id": comp["product_id"].id, + "product_qty": comp["product_qty"], } ) .id diff --git a/mrp_bom_configurable/models/mrp_bom_line.py b/mrp_bom_configurable/models/mrp_bom_line.py index c46bd51a9a0..fe19e65ba06 100644 --- a/mrp_bom_configurable/models/mrp_bom_line.py +++ b/mrp_bom_configurable/models/mrp_bom_line.py @@ -6,6 +6,52 @@ logger = logging.getLogger(__name__) +def check_domain(domain, values, current_name, parent_name): + domain = domain.replace("'", '"') + domain = domain.replace('"="', '"=="') + domain = domain.replace('"&", ', "") + domain = domain.replace('"&",', "") + domain = safe_eval(domain.replace("!==", "!=")) + + return execute_domain(domain, values, current_name, parent_name) + + +def execute_domain_element(element, values, current_name, parent_name): + # TODO support len(element) == 1, because element can be '&' and '|' + if len(element) != 3: + logger.warning("Domain element %s" % element) + param, operator, value = element + if param not in values: + raise UserError( + f"Wrong param name ({param}) for domain {current_name}" + + f"in {parent_name}" + ) + code = f"{repr(values[param])} {operator} {repr(value)}" + + result = None + + result = safe_eval(code) + + return result + + +def execute_domain(domain, values, current_name, parent_name): + if len(domain) == 0: + return True + if domain[0] == "OR": + return any( + execute_domain(domain_elm, values, current_name, parent_name) for domain_elm in domain[1:] + ) + elif isinstance(domain, list): + return all(execute_domain(domain_elm, values, current_name, parent_name) for domain_elm in domain) + else: + try: + return execute_domain_element(domain, values, current_name, parent_name) + except SyntaxError: + raise exceptions.ValidationError( + f"Domain {domain} is incorrect on {current_name}" + ) from None + class MrpBomLine(models.Model): _inherit = "mrp.bom.line" @@ -58,51 +104,12 @@ def goto_configurable_bom_report(self): "target": "new", } - def execute_domain_element(self, element, values): - # TODO support len(element) == 1, because element can be '&' and '|' - if len(element) != 3: - logger.warning("Domain element %s" % element) - param, operator, value = element - if param not in values: - raise UserError( - f"Wrong param name ({param}) in domain {self.product_tmpl_id.name}" - + f"in BoM {self.bom_id.product_tmpl_id.name}" - ) - code = f"{repr(values[param])} {operator} {repr(value)}" - - result = None - - try: - result = safe_eval(code) - except SyntaxError: - raise exceptions.ValidationError( - f"Domain {self.domain} is incorrect on {self.product_id.name}" - ) from None - - return result - - def execute_domain(self, domain, values): - if domain[0] == "OR": - return any( - self.execute_domain(domain_elm, values) for domain_elm in domain[1:] - ) - elif isinstance(domain, list): - return all(self.execute_domain(domain_elm, values) for domain_elm in domain) - else: - return self.execute_domain_element(domain, values) - def execute(self, values): self.ensure_one() if not self.domain: return True else: - # TODO clean to support '&' and '|' in domain - domain = self.domain.replace("'", '"') - domain = domain.replace('"="', '"=="') - domain = domain.replace('"&", ', "") - domain = domain.replace('"&",', "") - domain = safe_eval(domain.replace("!==", "!=")) - return self.execute_domain(domain, values) + return check_domain(self.domain, values, self.product_id.name, self.bom_id.product_id.name) def ui_update_domain(self): self.ensure_one()