From eb5b7a77c9edda21d474bf1bbfd3fe4d64ae78b7 Mon Sep 17 00:00:00 2001 From: Prateeksha Singh Date: Mon, 3 Sep 2018 10:58:56 +0530 Subject: [PATCH] [Feature] Format Autoname (#6017) * [Feature] Format Autoname - Generate autoname by replacing all instances of braced params - Independent of remaining string or separators. - Remove autoname Concatenate option * [autoname] add test for format autoname --- frappe/core/doctype/doctype/doctype.json | 129 +++++++++++++++++------ frappe/model/naming.py | 36 ++++--- frappe/tests/test_naming.py | 34 ++++++ 3 files changed, 148 insertions(+), 51 deletions(-) diff --git a/frappe/core/doctype/doctype/doctype.json b/frappe/core/doctype/doctype/doctype.json index f23ba5ef78..aa984d52b4 100644 --- a/frappe/core/doctype/doctype/doctype.json +++ b/frappe/core/doctype/doctype/doctype.json @@ -16,6 +16,7 @@ "fields": [ { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -47,6 +48,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -80,6 +82,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -113,6 +116,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -147,6 +151,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -180,6 +185,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -209,6 +215,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -242,6 +249,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -275,6 +283,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -305,6 +314,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -333,41 +343,43 @@ "set_only_once": 0, "translatable": 0, "unique": 0 - }, + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "0", - "fieldname": "track_views", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Track Views", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "default": "0", + "fieldname": "track_views", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Track Views", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -401,6 +413,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -431,6 +444,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -462,6 +476,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -495,6 +510,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -525,11 +541,12 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, - "description": "Naming Options:\n
  1. field:[fieldname] - By Field
  2. naming_series: - By Naming Series (field called naming_series must be present
  3. Prompt - Prompt user for a name
  4. [series] - Series by prefix (separated by a dot); for example PRE.#####
  5. \n
  6. concatenate:[fieldname1],[fieldname2],...[fieldnameX] - By fieldname concatenation (you can concatenate as many fields as you like. Series option also works)
", + "description": "Naming Options:\n
  1. field:[fieldname] - By Field
  2. naming_series: - By Naming Series (field called naming_series must be present
  3. Prompt - Prompt user for a name
  4. [series] - Series by prefix (separated by a dot); for example PRE.#####
  5. \n
  6. format:EXAMPLE-{MM}morewords{fieldname1}-{fieldname2}-{#####} - Replace all braced words (fieldnames, date words (DD, MM, YY), series) with their value. Outside braces, any characters can be used.
", "fieldname": "autoname", "fieldtype": "Data", "hidden": 0, @@ -558,6 +575,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -591,6 +609,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -621,6 +640,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -653,6 +673,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -684,6 +705,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -716,6 +738,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -749,6 +772,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -781,6 +805,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -814,6 +839,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -844,6 +870,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -878,6 +905,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -910,6 +938,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -940,6 +969,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -971,6 +1001,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1002,6 +1033,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1034,6 +1066,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1066,6 +1099,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1098,6 +1132,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1130,6 +1165,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1161,6 +1197,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1192,6 +1229,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1226,6 +1264,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1256,6 +1295,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1286,6 +1326,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1316,6 +1357,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1347,6 +1389,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1379,6 +1422,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1409,6 +1453,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1441,6 +1486,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1471,6 +1517,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1502,6 +1549,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1535,6 +1583,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1568,6 +1617,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1598,6 +1648,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1630,6 +1681,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1662,6 +1714,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1693,6 +1746,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1725,6 +1779,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1758,6 +1813,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1788,6 +1844,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1820,6 +1877,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1853,6 +1911,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 1, @@ -1884,6 +1943,7 @@ }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -1928,7 +1988,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2018-04-27 09:27:59.444089", + "modified": "2018-08-28 01:14:38.862469", "modified_by": "Administrator", "module": "Core", "name": "DocType", @@ -1981,5 +2041,6 @@ "sort_field": "modified", "sort_order": "DESC", "track_changes": 1, - "track_seen": 0 -} \ No newline at end of file + "track_seen": 0, + "track_views": 0 +} diff --git a/frappe/model/naming.py b/frappe/model/naming.py index 281e24d681..1708e8f98a 100644 --- a/frappe/model/naming.py +++ b/frappe/model/naming.py @@ -70,9 +70,9 @@ def set_name_from_naming_options(autoname, doc): elif _autoname.startswith('naming_series:'): set_name_by_naming_series(doc) elif _autoname.startswith('prompt'): - doc.name = _prompt_autoname(autoname, doc) - elif _autoname.startswith('concatenate:'): - doc.name = _concatenate_autoname(autoname, doc) + _prompt_autoname(autoname, doc) + elif _autoname.startswith('format:'): + doc.name = _format_autoname(autoname, doc) elif '#' in autoname: doc.name = make_autoname(autoname, doc=doc) @@ -271,22 +271,24 @@ def _prompt_autoname(autoname, doc): if not doc.name: frappe.throw(_("Name not set via prompt")) - -def _concatenate_autoname(autoname, doc): +def _format_autoname(autoname, doc): """ - Generate a name by concatenating as many fields as required. This is - called when the doctype's `autoname` field starts with 'concatenate:'. The - field names are separated by a comma. It is also aware of autoname '.####' - format. + Generate autoname by replacing all instances of braced params (fields, date params ('DD', 'MM', 'YY'), series) + Independent of remaining string or separators. + + Example pattern: 'format:LOG-{MM}-{fieldname1}-{fieldname2}-{#####}' """ - fieldname = autoname[12:] - fieldnames = [] + first_colon_index = autoname.find(':') + autoname_value = autoname[first_colon_index + 1:] + + def get_param_value_for_match(match): + param = match.group() + # trim braces + trimmed_param = param[1:-1] + return parse_naming_series([trimmed_param], doc=doc) + + # Replace braced params with their parsed value + name = re.sub(r'(\{[\w | #]+\})', get_param_value_for_match, autoname_value) - for part in fieldname.split(','): - if '.#' in part: - fieldnames.append(make_autoname(part, doc)) - else: - fieldnames.append(_field_autoname(part, doc, skip_slicing=True)) - name = '-'.join(fieldnames) return name diff --git a/frappe/tests/test_naming.py b/frappe/tests/test_naming.py index 487223734a..4ca8c4f586 100644 --- a/frappe/tests/test_naming.py +++ b/frappe/tests/test_naming.py @@ -4,10 +4,18 @@ from __future__ import unicode_literals import unittest import frappe +from frappe.utils import now_datetime +from frappe.model.naming import getseries from frappe.model.naming import append_number_if_name_exists class TestNaming(unittest.TestCase): + def tearDown(self): + # Reset ToDo autoname to hash + todo_doctype = frappe.get_doc('DocType', 'ToDo') + todo_doctype.autoname = 'hash' + todo_doctype.save() + def test_append_number_if_name_exists(self): ''' Append number to name based on existing values @@ -26,3 +34,29 @@ class TestNaming(unittest.TestCase): title2 = append_number_if_name_exists('Note', 'Test', 'title', '_') self.assertEqual(title2, 'Test_1') + + def test_format_autoname(self): + ''' + Test if braced params are replaced in format autoname + ''' + doctype = 'ToDo' + + todo_doctype = frappe.get_doc('DocType', doctype) + todo_doctype.autoname = 'format:TODO-{MM}-{status}-{##}' + todo_doctype.save() + + description = 'Format' + + todo = frappe.new_doc(doctype) + todo.description = description + todo.insert() + + series = getseries('', 2, doctype) + + series = str(int(series)-1) + + if len(series) < 2: + series = '0' + series + + self.assertEqual(todo.name, 'TODO-{month}-{status}-{series}'.format( + month=now_datetime().strftime('%m'), status=todo.status, series=series))