diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py index 3c325037e5..2c342c0d69 100644 --- a/erpnext/manufacturing/doctype/bom/bom.py +++ b/erpnext/manufacturing/doctype/bom/bom.py @@ -2,6 +2,7 @@ # License: GNU General Public License v3. See license.txt import functools +import re from collections import deque from operator import itemgetter from typing import List @@ -103,27 +104,34 @@ class BOM(WebsiteGenerator): ) def autoname(self): - names = frappe.db.sql_list("""select name from `tabBOM` where item=%s""", self.item) + existing_boms = frappe.get_all("BOM", filters={"item": self.item}) + if existing_boms: + existing_bom_names = [bom.name for bom in existing_boms] - if names: - # name can be BOM/ITEM/001, BOM/ITEM/001-1, BOM-ITEM-001, BOM-ITEM-001-1 + # split by "/" and "-" + delimiters = ["/", "-"] + pattern = "|".join(map(re.escape, delimiters)) + bom_parts = [re.split(pattern, bom_name) for bom_name in existing_bom_names] - # split by item - names = [name.split(self.item, 1) for name in names] - names = [d[-1][1:] for d in filter(lambda x: len(x) > 1 and x[-1], names)] + # filter out BOMs that do not follow the following formats: + # - BOM/ITEM/001 + # - BOM/ITEM/001-1 + # - BOM-ITEM-001 + # - BOM-ITEM-001-1 + valid_bom_parts = list(filter(lambda x: len(x) > 1 and x[-1], bom_parts)) - # split by (-) if cancelled - if names: - names = [cint(name.split('-')[-1]) for name in names] - idx = max(names) + 1 + # extract the current index from the BOM parts + if valid_bom_parts: + indexes = [cint(part[-1]) for part in valid_bom_parts] + index = max(indexes) + 1 else: - idx = 1 + index = 1 else: - idx = 1 + index = 1 prefix = self.doctype - suffix = "%.3i" % idx - bom_name = prefix + "-" + self.item + "-" + suffix + suffix = "%.3i" % index # convert index to string (1 -> "001") + bom_name = f"{prefix}-{self.item}-{suffix}" if len(bom_name) <= 140: name = bom_name @@ -134,7 +142,7 @@ class BOM(WebsiteGenerator): truncated_item_name = self.item[:truncated_length] # if a partial word is found after truncate, remove the extra characters truncated_item_name = truncated_item_name.rsplit(" ", 1)[0] - name = prefix + "-" + truncated_item_name + "-" + suffix + name = f"{prefix}-{truncated_item_name}-{suffix}" if frappe.db.exists("BOM", name): conflicting_bom = frappe.get_doc("BOM", name)