refactor!: drop naming series tool (#31183)

diff --git a/erpnext/buying/doctype/buying_settings/buying_settings.py b/erpnext/buying/doctype/buying_settings/buying_settings.py
index c52b59e..7b18cdb 100644
--- a/erpnext/buying/doctype/buying_settings/buying_settings.py
+++ b/erpnext/buying/doctype/buying_settings/buying_settings.py
@@ -18,7 +18,7 @@
 		for key in ["supplier_group", "supp_master_name", "maintain_same_rate", "buying_price_list"]:
 			frappe.db.set_default(key, self.get(key, ""))
 
-		from erpnext.setup.doctype.naming_series.naming_series import set_by_naming_series
+		from erpnext.utilities.naming import set_by_naming_series
 
 		set_by_naming_series(
 			"Supplier",
diff --git a/erpnext/e_commerce/doctype/website_item/website_item.py b/erpnext/e_commerce/doctype/website_item/website_item.py
index 02ec3bf..f6fea72 100644
--- a/erpnext/e_commerce/doctype/website_item/website_item.py
+++ b/erpnext/e_commerce/doctype/website_item/website_item.py
@@ -34,9 +34,7 @@
 
 	def autoname(self):
 		# use naming series to accomodate items with same name (different item code)
-		from frappe.model.naming import make_autoname
-
-		from erpnext.setup.doctype.naming_series.naming_series import get_default_naming_series
+		from frappe.model.naming import get_default_naming_series, make_autoname
 
 		naming_series = get_default_naming_series("Website Item")
 		if not self.name and naming_series:
diff --git a/erpnext/hr/doctype/hr_settings/hr_settings.py b/erpnext/hr/doctype/hr_settings/hr_settings.py
index 72a49e2..b56f3db 100644
--- a/erpnext/hr/doctype/hr_settings/hr_settings.py
+++ b/erpnext/hr/doctype/hr_settings/hr_settings.py
@@ -22,7 +22,7 @@
 		PROCEED_WITH_FREQUENCY_CHANGE = False
 
 	def set_naming_series(self):
-		from erpnext.setup.doctype.naming_series.naming_series import set_by_naming_series
+		from erpnext.utilities.naming import set_by_naming_series
 
 		set_by_naming_series(
 			"Employee",
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 8c0ebe7..785e2ba 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -372,3 +372,4 @@
 erpnext.patches.v14_0.delete_employee_transfer_property_doctype
 erpnext.patches.v13_0.create_accounting_dimensions_in_orders
 erpnext.patches.v13_0.set_per_billed_in_return_delivery_note
+execute:frappe.delete_doc("DocType", "Naming Series")
diff --git a/erpnext/patches/v13_0/item_naming_series_not_mandatory.py b/erpnext/patches/v13_0/item_naming_series_not_mandatory.py
index 33fb8f9..0235a62 100644
--- a/erpnext/patches/v13_0/item_naming_series_not_mandatory.py
+++ b/erpnext/patches/v13_0/item_naming_series_not_mandatory.py
@@ -1,6 +1,6 @@
 import frappe
 
-from erpnext.setup.doctype.naming_series.naming_series import set_by_naming_series
+from erpnext.utilities.naming import set_by_naming_series
 
 
 def execute():
diff --git a/erpnext/selling/doctype/selling_settings/selling_settings.py b/erpnext/selling/doctype/selling_settings/selling_settings.py
index 6c09894..d977807 100644
--- a/erpnext/selling/doctype/selling_settings/selling_settings.py
+++ b/erpnext/selling/doctype/selling_settings/selling_settings.py
@@ -27,7 +27,7 @@
 		]:
 			frappe.db.set_default(key, self.get(key, ""))
 
-		from erpnext.setup.doctype.naming_series.naming_series import set_by_naming_series
+		from erpnext.utilities.naming import set_by_naming_series
 
 		set_by_naming_series(
 			"Customer",
diff --git a/erpnext/setup/doctype/naming_series/README.md b/erpnext/setup/doctype/naming_series/README.md
deleted file mode 100644
index 5a9b8ca..0000000
--- a/erpnext/setup/doctype/naming_series/README.md
+++ /dev/null
@@ -1 +0,0 @@
-Tool to set numbering (naming) series for various DocTypes.
\ No newline at end of file
diff --git a/erpnext/setup/doctype/naming_series/__init__.py b/erpnext/setup/doctype/naming_series/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/setup/doctype/naming_series/__init__.py
+++ /dev/null
diff --git a/erpnext/setup/doctype/naming_series/naming_series.js b/erpnext/setup/doctype/naming_series/naming_series.js
deleted file mode 100644
index 0fb72ab..0000000
--- a/erpnext/setup/doctype/naming_series/naming_series.js
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and contributors
-// For license information, please see license.txt
-
-
-frappe.ui.form.on("Naming Series", {
-	onload: function(frm) {
-		frm.events.get_doc_and_prefix(frm);
-	},
-
-	refresh: function(frm) {
-		frm.disable_save();
-	},
-
-	get_doc_and_prefix: function(frm) {
-		frappe.call({
-			method: "get_transactions",
-			doc: frm.doc,
-			callback: function(r) {
-				frm.set_df_property("select_doc_for_series", "options", r.message.transactions);
-				frm.set_df_property("prefix", "options", r.message.prefixes);
-			}
-		});
-	},
-
-	select_doc_for_series: function(frm) {
-		frm.set_value("user_must_always_select", 0);
-		frappe.call({
-			method: "get_options",
-			doc: frm.doc,
-			callback: function(r) {
-				frm.set_value("set_options", r.message);
-				if(r.message && r.message.split('\n')[0]=='')
-					frm.set_value('user_must_always_select', 1);
-				frm.refresh();
-			}
-		});
-	},
-
-	prefix: function(frm) {
-		frappe.call({
-			method: "get_current",
-			doc: frm.doc,
-			callback: function(r) {
-				frm.refresh_field("current_value");
-			}
-		});
-	},
-
-	update: function(frm) {
-		frappe.call({
-			method: "update_series",
-			doc: frm.doc,
-			callback: function(r) {
-				frm.events.get_doc_and_prefix(frm);
-			}
-		});
-	},
-
-	naming_series_to_check(frm) {
-		frappe.call({
-			method: "preview_series",
-			doc: frm.doc,
-			callback: function(r) {
-				if (!r.exc) {
-					frm.set_value("preview", r.message);
-				} else {
-					frm.set_value("preview", __("Failed to generate preview of series"));
-				}
-			}
-		});
-	},
-
-	add_series(frm) {
-		const series = frm.doc.naming_series_to_check;
-
-		if (!series) {
-			frappe.show_alert(__("Please type a valid series."));
-			return;
-		}
-
-		if (!frm.doc.set_options.includes(series)) {
-			const current_series = frm.doc.set_options;
-			frm.set_value("set_options", `${current_series}\n${series}`);
-		} else {
-			frappe.show_alert(__("Series already added to transaction."));
-		}
-	},
-});
diff --git a/erpnext/setup/doctype/naming_series/naming_series.json b/erpnext/setup/doctype/naming_series/naming_series.json
deleted file mode 100644
index c65a6f0..0000000
--- a/erpnext/setup/doctype/naming_series/naming_series.json
+++ /dev/null
@@ -1,132 +0,0 @@
-{
- "actions": [],
- "creation": "2022-05-26 03:12:49.087648",
- "description": "Set prefix for numbering series on your transactions",
- "doctype": "DocType",
- "engine": "InnoDB",
- "field_order": [
-  "setup_series",
-  "select_doc_for_series",
-  "help_html",
-  "naming_series_to_check",
-  "preview",
-  "add_series",
-  "set_options",
-  "user_must_always_select",
-  "update",
-  "column_break_13",
-  "update_series",
-  "prefix",
-  "current_value",
-  "update_series_start"
- ],
- "fields": [
-  {
-   "description": "Set prefix for numbering series on your transactions",
-   "fieldname": "setup_series",
-   "fieldtype": "Section Break",
-   "label": "Setup Series"
-  },
-  {
-   "fieldname": "select_doc_for_series",
-   "fieldtype": "Select",
-   "label": "Select Transaction"
-  },
-  {
-   "depends_on": "select_doc_for_series",
-   "fieldname": "help_html",
-   "fieldtype": "HTML",
-   "label": "Help HTML",
-   "options": "<div class=\"well\">\n    Edit list of Series in the box below. Rules:\n    <ul>\n        <li>Each Series Prefix on a new line.</li>\n        <li>Allowed special characters are \"/\" and \"-\"</li>\n        <li>\n            Optionally, set the number of digits in the series using dot (.)\n            followed by hashes (#). For example, \".####\" means that the series\n            will have four digits. Default is five digits.\n        </li>\n        <li>\n            You can also use variables in the series name by putting them\n            between (.) dots\n            <br>\n            Support Variables:\n            <ul>\n                <li><code>.YYYY.</code> - Year in 4 digits</li>\n                <li><code>.YY.</code> - Year in 2 digits</li>\n                <li><code>.MM.</code> - Month</li>\n                <li><code>.DD.</code> - Day of month</li>\n                <li><code>.WW.</code> - Week of the year</li>\n                <li><code>.FY.</code> - Fiscal Year</li>\n                <li>\n                    <code>.{fieldname}.</code> - fieldname on the document e.g.\n                    <code>branch</code>\n                </li>\n            </ul>\n        </li>\n    </ul>\n    Examples:\n    <ul>\n        <li>INV-</li>\n        <li>INV-10-</li>\n        <li>INVK-</li>\n        <li>INV-.YYYY.-.{branch}.-.MM.-.####</li>\n    </ul>\n</div>\n<br>\n"
-  },
-  {
-   "depends_on": "select_doc_for_series",
-   "fieldname": "set_options",
-   "fieldtype": "Text",
-   "label": "Series List for this Transaction"
-  },
-  {
-   "default": "0",
-   "depends_on": "select_doc_for_series",
-   "description": "Check this if you want to force the user to select a series before saving. There will be no default if you check this.",
-   "fieldname": "user_must_always_select",
-   "fieldtype": "Check",
-   "label": "User must always select"
-  },
-  {
-   "depends_on": "select_doc_for_series",
-   "fieldname": "update",
-   "fieldtype": "Button",
-   "label": "Update"
-  },
-  {
-   "description": "Change the starting / current sequence number of an existing series.",
-   "fieldname": "update_series",
-   "fieldtype": "Section Break",
-   "label": "Update Series"
-  },
-  {
-   "fieldname": "prefix",
-   "fieldtype": "Select",
-   "label": "Prefix"
-  },
-  {
-   "description": "This is the number of the last created transaction with this prefix",
-   "fieldname": "current_value",
-   "fieldtype": "Int",
-   "label": "Current Value"
-  },
-  {
-   "fieldname": "update_series_start",
-   "fieldtype": "Button",
-   "label": "Update Series Number",
-   "options": "update_series_start"
-  },
-  {
-   "fieldname": "naming_series_to_check",
-   "fieldtype": "Data",
-   "label": "Try a naming Series"
-  },
-  {
-   "default": " ",
-   "fieldname": "preview",
-   "fieldtype": "Text",
-   "label": "Preview of generated names",
-   "read_only": 1
-  },
-  {
-   "fieldname": "column_break_13",
-   "fieldtype": "Column Break"
-  },
-  {
-   "fieldname": "add_series",
-   "fieldtype": "Button",
-   "label": "Add this Series"
-  }
- ],
- "hide_toolbar": 1,
- "icon": "fa fa-sort-by-order",
- "idx": 1,
- "issingle": 1,
- "links": [],
- "modified": "2022-05-26 06:06:42.109504",
- "modified_by": "Administrator",
- "module": "Setup",
- "name": "Naming Series",
- "owner": "Administrator",
- "permissions": [
-  {
-   "create": 1,
-   "email": 1,
-   "print": 1,
-   "read": 1,
-   "role": "System Manager",
-   "share": 1,
-   "write": 1
-  }
- ],
- "read_only": 1,
- "sort_field": "modified",
- "sort_order": "DESC",
- "states": []
-}
\ No newline at end of file
diff --git a/erpnext/setup/doctype/naming_series/naming_series.py b/erpnext/setup/doctype/naming_series/naming_series.py
deleted file mode 100644
index eafc264..0000000
--- a/erpnext/setup/doctype/naming_series/naming_series.py
+++ /dev/null
@@ -1,303 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-
-import frappe
-from frappe import _, msgprint, throw
-from frappe.core.doctype.doctype.doctype import validate_series
-from frappe.model.document import Document
-from frappe.model.naming import make_autoname, parse_naming_series
-from frappe.permissions import get_doctypes_with_read
-from frappe.utils import cint, cstr
-
-
-class NamingSeriesNotSetError(frappe.ValidationError):
-	pass
-
-
-class NamingSeries(Document):
-	@frappe.whitelist()
-	def get_transactions(self, arg=None):
-		doctypes = list(
-			set(
-				frappe.db.sql_list(
-					"""select parent
-				from `tabDocField` df where fieldname='naming_series'"""
-				)
-				+ frappe.db.sql_list(
-					"""select dt from `tabCustom Field`
-				where fieldname='naming_series'"""
-				)
-			)
-		)
-
-		doctypes = list(set(get_doctypes_with_read()).intersection(set(doctypes)))
-		prefixes = ""
-		for d in doctypes:
-			options = ""
-			try:
-				options = self.get_options(d)
-			except frappe.DoesNotExistError:
-				frappe.msgprint(_("Unable to find DocType {0}").format(d))
-				# frappe.pass_does_not_exist_error()
-				continue
-
-			if options:
-				prefixes = prefixes + "\n" + options
-		prefixes.replace("\n\n", "\n")
-		prefixes = prefixes.split("\n")
-
-		custom_prefixes = frappe.get_all(
-			"DocType",
-			fields=["autoname"],
-			filters={
-				"name": ("not in", doctypes),
-				"autoname": ("like", "%.#%"),
-				"module": ("not in", ["Core"]),
-			},
-		)
-		if custom_prefixes:
-			prefixes = prefixes + [d.autoname.rsplit(".", 1)[0] for d in custom_prefixes]
-
-		prefixes = "\n".join(sorted(prefixes))
-
-		return {"transactions": "\n".join([""] + sorted(doctypes)), "prefixes": prefixes}
-
-	def scrub_options_list(self, ol):
-		options = list(filter(lambda x: x, [cstr(n).strip() for n in ol]))
-		return options
-
-	@frappe.whitelist()
-	def update_series(self, arg=None):
-		"""update series list"""
-		self.validate_series_set()
-		self.check_duplicate()
-		series_list = self.set_options.split("\n")
-
-		# set in doctype
-		self.set_series_for(self.select_doc_for_series, series_list)
-
-		# create series
-		map(self.insert_series, [d.split(".")[0] for d in series_list if d.strip()])
-
-		msgprint(_("Series Updated"))
-
-		return self.get_transactions()
-
-	def validate_series_set(self):
-		if self.select_doc_for_series and not self.set_options:
-			frappe.throw(_("Please set the series to be used."))
-
-	def set_series_for(self, doctype, ol):
-		options = self.scrub_options_list(ol)
-
-		# validate names
-		for i in options:
-			self.validate_series_name(i)
-
-		if options and self.user_must_always_select:
-			options = [""] + options
-
-		default = options[0] if options else ""
-
-		# update in property setter
-		prop_dict = {"options": "\n".join(options), "default": default}
-
-		for prop in prop_dict:
-			ps_exists = frappe.db.get_value(
-				"Property Setter", {"field_name": "naming_series", "doc_type": doctype, "property": prop}
-			)
-
-			if ps_exists:
-				ps = frappe.get_doc("Property Setter", ps_exists)
-				ps.value = prop_dict[prop]
-				ps.save()
-			else:
-				ps = frappe.get_doc(
-					{
-						"doctype": "Property Setter",
-						"doctype_or_field": "DocField",
-						"doc_type": doctype,
-						"field_name": "naming_series",
-						"property": prop,
-						"value": prop_dict[prop],
-						"property_type": "Text",
-						"__islocal": 1,
-					}
-				)
-				ps.save()
-
-		self.set_options = "\n".join(options)
-
-		frappe.clear_cache(doctype=doctype)
-
-	def check_duplicate(self):
-		parent = list(
-			set(
-				frappe.db.sql_list(
-					"""select dt.name
-				from `tabDocField` df, `tabDocType` dt
-				where dt.name = df.parent and df.fieldname='naming_series' and dt.name != %s""",
-					self.select_doc_for_series,
-				)
-				+ frappe.db.sql_list(
-					"""select dt.name
-				from `tabCustom Field` df, `tabDocType` dt
-				where dt.name = df.dt and df.fieldname='naming_series' and dt.name != %s""",
-					self.select_doc_for_series,
-				)
-			)
-		)
-		sr = [[frappe.get_meta(p).get_field("naming_series").options, p] for p in parent]
-		dt = frappe.get_doc("DocType", self.select_doc_for_series)
-		options = self.scrub_options_list(self.set_options.split("\n"))
-		for series in options:
-			validate_series(dt, series)
-			for i in sr:
-				if i[0]:
-					existing_series = [d.split(".")[0] for d in i[0].split("\n")]
-					if series.split(".")[0] in existing_series:
-						frappe.throw(_("Series {0} already used in {1}").format(series, i[1]))
-
-	def validate_series_name(self, n):
-		import re
-
-		if not re.match(r"^[\w\- \/.#{}]+$", n, re.UNICODE):
-			throw(
-				_('Special Characters except "-", "#", ".", "/", "{" and "}" not allowed in naming series')
-			)
-
-	@frappe.whitelist()
-	def get_options(self, arg=None):
-		if frappe.get_meta(arg or self.select_doc_for_series).get_field("naming_series"):
-			return frappe.get_meta(arg or self.select_doc_for_series).get_field("naming_series").options
-
-	@frappe.whitelist()
-	def get_current(self, arg=None):
-		"""get series current"""
-		if self.prefix:
-			prefix = self.parse_naming_series()
-			self.current_value = frappe.db.get_value("Series", prefix, "current", order_by="name")
-
-	def insert_series(self, series):
-		"""insert series if missing"""
-		if frappe.db.get_value("Series", series, "name", order_by="name") == None:
-			frappe.db.sql("insert into tabSeries (name, current) values (%s, 0)", (series))
-
-	@frappe.whitelist()
-	def update_series_start(self):
-		if self.prefix:
-			prefix = self.parse_naming_series()
-			self.insert_series(prefix)
-			frappe.db.sql(
-				"update `tabSeries` set current = %s where name = %s", (cint(self.current_value), prefix)
-			)
-			msgprint(_("Series Updated Successfully"))
-		else:
-			msgprint(_("Please select prefix first"))
-
-	def parse_naming_series(self):
-		parts = self.prefix.split(".")
-
-		# Remove ### from the end of series
-		if parts[-1] == "#" * len(parts[-1]):
-			del parts[-1]
-
-		prefix = parse_naming_series(parts)
-		return prefix
-
-	@frappe.whitelist()
-	def preview_series(self) -> str:
-		"""Preview what the naming series will generate."""
-
-		generated_names = []
-		series = self.naming_series_to_check
-		if not series:
-			return ""
-
-		try:
-			doc = self._fetch_last_doc_if_available()
-			for _count in range(3):
-				generated_names.append(make_autoname(series, doc=doc))
-		except Exception as e:
-			if frappe.message_log:
-				frappe.message_log.pop()
-			return _("Failed to generate names from the series") + f"\n{str(e)}"
-
-		# Explcitly rollback in case any changes were made to series table.
-		frappe.db.rollback()  # nosemgrep
-		return "\n".join(generated_names)
-
-	def _fetch_last_doc_if_available(self):
-		"""Fetch last doc for evaluating naming series with fields."""
-		try:
-			return frappe.get_last_doc(self.select_doc_for_series)
-		except Exception:
-			return None
-
-
-def set_by_naming_series(
-	doctype, fieldname, naming_series, hide_name_field=True, make_mandatory=1
-):
-	from frappe.custom.doctype.property_setter.property_setter import make_property_setter
-
-	if naming_series:
-		make_property_setter(
-			doctype, "naming_series", "hidden", 0, "Check", validate_fields_for_doctype=False
-		)
-		make_property_setter(
-			doctype, "naming_series", "reqd", make_mandatory, "Check", validate_fields_for_doctype=False
-		)
-
-		# set values for mandatory
-		try:
-			frappe.db.sql(
-				"""update `tab{doctype}` set naming_series={s} where
-				ifnull(naming_series, '')=''""".format(
-					doctype=doctype, s="%s"
-				),
-				get_default_naming_series(doctype),
-			)
-		except NamingSeriesNotSetError:
-			pass
-
-		if hide_name_field:
-			make_property_setter(doctype, fieldname, "reqd", 0, "Check", validate_fields_for_doctype=False)
-			make_property_setter(
-				doctype, fieldname, "hidden", 1, "Check", validate_fields_for_doctype=False
-			)
-	else:
-		make_property_setter(
-			doctype, "naming_series", "reqd", 0, "Check", validate_fields_for_doctype=False
-		)
-		make_property_setter(
-			doctype, "naming_series", "hidden", 1, "Check", validate_fields_for_doctype=False
-		)
-
-		if hide_name_field:
-			make_property_setter(
-				doctype, fieldname, "hidden", 0, "Check", validate_fields_for_doctype=False
-			)
-			make_property_setter(doctype, fieldname, "reqd", 1, "Check", validate_fields_for_doctype=False)
-
-			# set values for mandatory
-			frappe.db.sql(
-				"""update `tab{doctype}` set `{fieldname}`=`name` where
-				ifnull({fieldname}, '')=''""".format(
-					doctype=doctype, fieldname=fieldname
-				)
-			)
-
-
-def get_default_naming_series(doctype):
-	naming_series = frappe.get_meta(doctype).get_field("naming_series").options or ""
-	naming_series = naming_series.split("\n")
-	out = naming_series[0] or (naming_series[1] if len(naming_series) > 1 else None)
-
-	if not out:
-		frappe.throw(
-			_("Please set Naming Series for {0} via Setup > Settings > Naming Series").format(doctype),
-			NamingSeriesNotSetError,
-		)
-	else:
-		return out
diff --git a/erpnext/setup/doctype/naming_series/test_naming_series.py b/erpnext/setup/doctype/naming_series/test_naming_series.py
deleted file mode 100644
index fce663e..0000000
--- a/erpnext/setup/doctype/naming_series/test_naming_series.py
+++ /dev/null
@@ -1,35 +0,0 @@
-# Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and Contributors
-# See license.txt
-
-import frappe
-from frappe.tests.utils import FrappeTestCase
-
-from erpnext.setup.doctype.naming_series.naming_series import NamingSeries
-
-
-class TestNamingSeries(FrappeTestCase):
-	def setUp(self):
-		self.ns: NamingSeries = frappe.get_doc("Naming Series")
-
-	def tearDown(self):
-		frappe.db.rollback()
-
-	def test_naming_preview(self):
-		self.ns.select_doc_for_series = "Sales Invoice"
-
-		self.ns.naming_series_to_check = "AXBZ.####"
-		serieses = self.ns.preview_series().split("\n")
-		self.assertEqual(["AXBZ0001", "AXBZ0002", "AXBZ0003"], serieses)
-
-		self.ns.naming_series_to_check = "AXBZ-.{currency}.-"
-		serieses = self.ns.preview_series().split("\n")
-
-	def test_get_transactions(self):
-
-		naming_info = self.ns.get_transactions()
-		self.assertIn("Sales Invoice", naming_info["transactions"])
-
-		existing_naming_series = frappe.get_meta("Sales Invoice").get_field("naming_series").options
-
-		for series in existing_naming_series.split("\n"):
-			self.assertIn(series, naming_info["prefixes"])
diff --git a/erpnext/stock/doctype/stock_settings/stock_settings.py b/erpnext/stock/doctype/stock_settings/stock_settings.py
index e592a4b..50807a9 100644
--- a/erpnext/stock/doctype/stock_settings/stock_settings.py
+++ b/erpnext/stock/doctype/stock_settings/stock_settings.py
@@ -26,7 +26,7 @@
 		]:
 			frappe.db.set_default(key, self.get(key, ""))
 
-		from erpnext.setup.doctype.naming_series.naming_series import set_by_naming_series
+		from erpnext.utilities.naming import set_by_naming_series
 
 		set_by_naming_series(
 			"Item",
diff --git a/erpnext/utilities/naming.py b/erpnext/utilities/naming.py
new file mode 100644
index 0000000..52bbade
--- /dev/null
+++ b/erpnext/utilities/naming.py
@@ -0,0 +1,60 @@
+import frappe
+from frappe.model.naming import get_default_naming_series
+
+
+class NamingSeriesNotSetError(frappe.ValidationError):
+	pass
+
+
+def set_by_naming_series(
+	doctype, fieldname, naming_series, hide_name_field=True, make_mandatory=1
+):
+	"""Change a doctype's naming to user naming series"""
+	from frappe.custom.doctype.property_setter.property_setter import make_property_setter
+
+	if naming_series:
+		make_property_setter(
+			doctype, "naming_series", "hidden", 0, "Check", validate_fields_for_doctype=False
+		)
+		make_property_setter(
+			doctype, "naming_series", "reqd", make_mandatory, "Check", validate_fields_for_doctype=False
+		)
+
+		# set values for mandatory
+		try:
+			frappe.db.sql(
+				"""update `tab{doctype}` set naming_series={s} where
+				ifnull(naming_series, '')=''""".format(
+					doctype=doctype, s="%s"
+				),
+				get_default_naming_series(doctype),
+			)
+		except NamingSeriesNotSetError:
+			pass
+
+		if hide_name_field:
+			make_property_setter(doctype, fieldname, "reqd", 0, "Check", validate_fields_for_doctype=False)
+			make_property_setter(
+				doctype, fieldname, "hidden", 1, "Check", validate_fields_for_doctype=False
+			)
+	else:
+		make_property_setter(
+			doctype, "naming_series", "reqd", 0, "Check", validate_fields_for_doctype=False
+		)
+		make_property_setter(
+			doctype, "naming_series", "hidden", 1, "Check", validate_fields_for_doctype=False
+		)
+
+		if hide_name_field:
+			make_property_setter(
+				doctype, fieldname, "hidden", 0, "Check", validate_fields_for_doctype=False
+			)
+			make_property_setter(doctype, fieldname, "reqd", 1, "Check", validate_fields_for_doctype=False)
+
+			# set values for mandatory
+			frappe.db.sql(
+				"""update `tab{doctype}` set `{fieldname}`=`name` where
+				ifnull({fieldname}, '')=''""".format(
+					doctype=doctype, fieldname=fieldname
+				)
+			)