diff --git a/frappe/core/doctype/doctype/doctype.py b/frappe/core/doctype/doctype/doctype.py index 5eb3e55c4e..3d9a7ba938 100644 --- a/frappe/core/doctype/doctype/doctype.py +++ b/frappe/core/doctype/doctype/doctype.py @@ -1085,12 +1085,6 @@ def validate_series(dt, autoname=None, name=None): df.unique = 1 break - if autoname and autoname.startswith("format:"): - from frappe.model.naming import BRACED_PARAMS_HASH_PATTERN - - if len(BRACED_PARAMS_HASH_PATTERN.findall(autoname)) > 1: - frappe.throw(_("Only one set of {#} pattern is allowed in the format string")) - if ( autoname and (not autoname.startswith("field:")) diff --git a/frappe/model/naming.py b/frappe/model/naming.py index 1eae1e2b45..202a4e580a 100644 --- a/frappe/model/naming.py +++ b/frappe/model/naming.py @@ -24,8 +24,7 @@ if TYPE_CHECKING: NAMING_SERIES_PATTERN = re.compile(r"^[\w\- \/.#{}]+$", re.UNICODE) -BRACED_PARAMS_WORD_PATTERN = re.compile(r"(\{[\w]+\})") -BRACED_PARAMS_HASH_PATTERN = re.compile(r"(\{[#]+\})") +BRACED_PARAMS_PATTERN = re.compile(r"(\{[\w | #]+\})") # Types that can be using in naming series fields @@ -323,7 +322,6 @@ def parse_naming_series( doctype=None, doc: Optional["Document"] = None, number_generator: Callable[[str, int], str] | None = None, - key: str | None = None, ) -> str: """Parse the naming series and get next name. @@ -351,10 +349,7 @@ def parse_naming_series( if e.startswith("#"): if not series_set: digits = len(e) - if key: - part = number_generator(key, digits) - else: - part = number_generator(name, digits) + part = number_generator(name, digits) series_set = True elif e == "YY": part = today.strftime("%y") @@ -588,19 +583,11 @@ def _format_autoname(autoname: str, doc): first_colon_index = autoname.find(":") autoname_value = autoname[first_colon_index + 1 :] - def get_param_value_for_word_match(match): + def get_param_value_for_match(match): param = match.group() return parse_naming_series([param[1:-1]], doc=doc) - def get_param_value_for_hash_match(patterned_string: str): - def get_param_value(match): - param = match.group() - key = patterned_string[: patterned_string.find(param)] - - return parse_naming_series([param[1:-1]], doc=doc, key=key) - - return get_param_value - # Replace braced params with their parsed value - autoname_value = BRACED_PARAMS_WORD_PATTERN.sub(get_param_value_for_word_match, autoname_value) - return BRACED_PARAMS_HASH_PATTERN.sub(get_param_value_for_hash_match(autoname_value), autoname_value) + name = BRACED_PARAMS_PATTERN.sub(get_param_value_for_match, autoname_value) + + return name diff --git a/frappe/patches.txt b/frappe/patches.txt index 94c216bb2e..4d51a2ce96 100644 --- a/frappe/patches.txt +++ b/frappe/patches.txt @@ -242,4 +242,3 @@ execute:frappe.db.set_single_value("Workspace Settings", "workspace_setup_comple frappe.patches.v16_0.add_app_launcher_in_navbar_settings frappe.desk.doctype.workspace.patches.update_app frappe.patches.v16_0.move_role_desk_settings_to_user -frappe.patches.v16_0.update_expression_series diff --git a/frappe/patches/v16_0/update_expression_series.py b/frappe/patches/v16_0/update_expression_series.py deleted file mode 100644 index 73fd81d3d2..0000000000 --- a/frappe/patches/v16_0/update_expression_series.py +++ /dev/null @@ -1,69 +0,0 @@ -import frappe -from frappe.model.naming import ( - BRACED_PARAMS_WORD_PATTERN, - NAMING_SERIES_PART_TYPES, - determine_consecutive_week_number, - has_custom_parser, -) -from frappe.query_builder import DocType -from frappe.utils import cstr - - -def execute(): - Series = DocType("Series") - doctypes = frappe.get_all("DocType", filters={"naming_rule": "expression"}, fields=["name", "autoname"]) - uniq_exprs = set() - - def get_param_value_for_word_match(doc): - def get_param_value(match): - e = match.group()[1:-1] - creation = doc.creation - _sentinel = object() - part = "" - if e == "YY": - part = creation.strftime("%y") - elif e == "MM": - part = creation.strftime("%m") - elif e == "DD": - part = creation.strftime("%d") - elif e == "YYYY": - part = creation.strftime("%Y") - elif e == "WW": - part = determine_consecutive_week_number(creation) - elif e == "timestamp": - part = str(creation) - elif doc and (e.startswith("{") or doc.get(e, _sentinel) is not _sentinel): - e = e.replace("{", "").replace("}", "") - part = doc.get(e) - elif method := has_custom_parser(e): - part = frappe.get_attr(method[0])(doc, e) - else: - part = e - - if isinstance(part, NAMING_SERIES_PART_TYPES): - part = cstr(part).strip() - - return part - - return get_param_value - - for doctype in doctypes: - if "#" in doctype.autoname: - docs = frappe.get_all(doctype.name) - if docs: - for doc in docs: - _doc = frappe.get_doc(doctype.name, doc.name) - expr = doctype.autoname[7 : doctype.autoname.find("{#")] - key = BRACED_PARAMS_WORD_PATTERN.sub(get_param_value_for_word_match(_doc), expr) - uniq_exprs.add(key) - - current = (frappe.qb.from_(Series).select("*").where(Series.name == "")).run(as_dict=True) - if current: - current = current[0].get("current") - - for uniq_expr in uniq_exprs: - expr_exists = (frappe.qb.from_(Series).select("*").where(Series.name == uniq_expr)).run( - as_dict=True - ) - if not expr_exists: - (frappe.qb.into(Series).columns("name", "current").insert(uniq_expr, current + 1)).run() diff --git a/frappe/tests/test_naming.py b/frappe/tests/test_naming.py index b72aa2424f..365bcbfac2 100644 --- a/frappe/tests/test_naming.py +++ b/frappe/tests/test_naming.py @@ -102,8 +102,7 @@ class TestNaming(IntegrationTestCase): doc.some_fieldname = description doc.insert() - series = getseries(f"TODO-{now_datetime().strftime('%m')}-{description}-", 2) - + series = getseries("", 2) series = int(series) - 1 self.assertEqual(doc.name, f"TODO-{now_datetime().strftime('%m')}-{description}-{series:02}") @@ -117,7 +116,7 @@ class TestNaming(IntegrationTestCase): doc.field = field doc.insert() - series = getseries(f"TODO-{field}-", 2) + series = getseries("", 2) series = int(series) - 1 self.assertEqual(doc.name, f"TODO-{field}-{series:02}") @@ -138,13 +137,15 @@ class TestNaming(IntegrationTestCase): todo.description = description todo.insert() - week = determine_consecutive_week_number(now_datetime()) - series = getseries(f"TODO-{week}-", 2) + series = getseries("", 2) + series = str(int(series) - 1) if len(series) < 2: series = "0" + series + week = determine_consecutive_week_number(now_datetime()) + self.assertEqual(todo.name, f"TODO-{week}-{series}") def test_revert_series(self):