[ Fixes ] v11 Tree based doctype testing (#14419)

* location tree fixes
validate if child present while deleting, filter lists down only group enabled node

* department tree fixes
Adding child fix if added from rootnode with company filter applied. Rename consistency added. Validation added in on_trash

* Company tree fix
Check if child exist while deleting a node validation added.

* Supplier Group tree fixes
on_trash validation added if child node present

* Cost Center tree fixes
Adding child to root node throws error because parent_cost_center picks up root name
diff --git a/erpnext/accounts/doctype/cost_center/cost_center_tree.js b/erpnext/accounts/doctype/cost_center/cost_center_tree.js
index 5043669..2d989f7 100644
--- a/erpnext/accounts/doctype/cost_center/cost_center_tree.js
+++ b/erpnext/accounts/doctype/cost_center/cost_center_tree.js
@@ -47,11 +47,6 @@
 			frappe.set_route('query-report', 'Budget Variance Report', {company: get_company()});
 		}, __('Budget'));
 
-	},
-	onrender: function(node) {
-		if(node.is_root){
-			node.hide_add = true;
-		}
 	}
 
 }
\ No newline at end of file
diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py
index 8e23975..cd63518 100644
--- a/erpnext/accounts/utils.py
+++ b/erpnext/accounts/utils.py
@@ -273,6 +273,10 @@
 	args.doctype = "Cost Center"
 	args = make_tree_args(**args)
 
+	if args.parent_cost_center == args.company:
+		args.parent_cost_center = "{0} - {1}".format(args.parent_cost_center,
+			frappe.db.get_value('Company', args.company, 'abbr'))
+
 	cc = frappe.new_doc("Cost Center")
 	cc.update(args)
 
diff --git a/erpnext/assets/doctype/location/location.py b/erpnext/assets/doctype/location/location.py
index 9d05720..86542cb 100644
--- a/erpnext/assets/doctype/location/location.py
+++ b/erpnext/assets/doctype/location/location.py
@@ -8,13 +8,13 @@
 from frappe.utils.nestedset import NestedSet
 
 class Location(NestedSet):
+	nsm_parent_field = 'parent_location'
+
 	def on_update(self):
-		self.update_nsm_model()
+		NestedSet.on_update(self)
 
 	def on_trash(self):
-		self.update_nsm_model()
-
-	def update_nsm_model(self):
+		NestedSet.validate_if_child_exists(self)
 		frappe.utils.nestedset.update_nsm(self)
 
 @frappe.whitelist()
diff --git a/erpnext/assets/doctype/location/location_tree.js b/erpnext/assets/doctype/location/location_tree.js
index 523dd63..cbd8f10 100644
--- a/erpnext/assets/doctype/location/location_tree.js
+++ b/erpnext/assets/doctype/location/location_tree.js
@@ -7,7 +7,12 @@
 			fieldname: "location",
 			fieldtype:"Link",
 			options: "Location",
-			label: __("Location")
+			label: __("Location"),
+			get_query: function() {
+				return {
+					filters: [["Location", "is_group", "=", 1]]
+				};
+			}
 		},
 	],
 	breadcrumb: "Assets",
diff --git a/erpnext/hr/doctype/department/department.py b/erpnext/hr/doctype/department/department.py
index 09cd6d3..8c6a764 100644
--- a/erpnext/hr/doctype/department/department.py
+++ b/erpnext/hr/doctype/department/department.py
@@ -13,8 +13,7 @@
 	def autoname(self):
 		root = get_root_of("Department")
 		if root and self.department_name != root:
-			abbr = frappe.db.get_value('Company', self.company, 'abbr')
-			self.name = '{0} - {1}'.format(self.department_name, abbr)
+			self.name = get_abbreviated_name(self.department_name, self.company)
 		else:
 			self.name = self.department_name
 
@@ -24,11 +23,15 @@
 			if root:
 				self.parent_department = root
 
-	def update_nsm_model(self):
-		frappe.utils.nestedset.update_nsm(self)
+	def before_rename(self, old, new, merge=False):
+		# renaming consistency with abbreviation
+		if not frappe.db.get_value('Company', self.company, 'abbr') in new:
+			new = get_abbreviated_name(new, self.company)
+
+		return new
 
 	def on_update(self):
-		self.update_nsm_model()
+		NestedSet.on_update(self)
 
 	def on_trash(self):
 		super(Department, self).on_trash()
@@ -37,11 +40,16 @@
 def on_doctype_update():
 	frappe.db.add_index("Department", ["lft", "rgt"])
 
+def get_abbreviated_name(name, company):
+	abbr = frappe.db.get_value('Company', company, 'abbr')
+	new_name = '{0} - {1}'.format(name, abbr)
+	return new_name
+
 @frappe.whitelist()
 def get_children(doctype, parent=None, company=None, is_root=False):
 	condition = ''
 	if company == parent:
-		condition = "name='%s'".format(get_root_of("Department"))
+		condition = "name='{0}'".format(get_root_of("Department"))
 	elif company:
 		condition = "parent_department='{0}' and company='{1}'".format(parent, company)
 	else:
@@ -55,3 +63,14 @@
 		where
 			{condition}
 		order by name""".format(doctype=doctype, condition=condition), as_dict=1)
+
+@frappe.whitelist()
+def add_node():
+	from frappe.desk.treeview import make_tree_args
+	args = frappe.form_dict
+	args = make_tree_args(**args)
+
+	if args.parent_department == args.company:
+		args.parent_department = None
+
+	frappe.get_doc(args).insert()
diff --git a/erpnext/hr/doctype/department/department_tree.js b/erpnext/hr/doctype/department/department_tree.js
index 1f891fd..52d864b 100644
--- a/erpnext/hr/doctype/department/department_tree.js
+++ b/erpnext/hr/doctype/department/department_tree.js
@@ -1,6 +1,7 @@
 frappe.treeview_settings["Department"] = {
 	ignore_fields:["parent_department"],
 	get_tree_nodes: 'erpnext.hr.doctype.department.department.get_children',
+	add_tree_node: 'erpnext.hr.doctype.department.department.add_node',
 	filters: [
 		{
 			fieldname: "company",
diff --git a/erpnext/setup/doctype/company/company.py b/erpnext/setup/doctype/company/company.py
index aebd2ee..430617f 100644
--- a/erpnext/setup/doctype/company/company.py
+++ b/erpnext/setup/doctype/company/company.py
@@ -82,7 +82,7 @@
 				frappe.throw(_("Cannot change company's default currency, because there are existing transactions. Transactions must be cancelled to change the default currency."))
 
 	def on_update(self):
-		self.update_nsm_model()
+		NestedSet.on_update(self)
 		if not frappe.db.sql("""select name from tabAccount
 				where company=%s and docstatus<2 limit 1""", self.name):
 			if not frappe.local.flags.ignore_chart_of_accounts:
@@ -284,14 +284,12 @@
 	def abbreviate(self):
 		self.abbr = ''.join([c[0].upper() for c in self.company_name.split()])
 
-	def update_nsm_model(self):
-		frappe.utils.nestedset.update_nsm(self)
-
 	def on_trash(self):
 		"""
 			Trash accounts and cost centers for this company if no gl entry exists
 		"""
-		self.update_nsm_model()
+		NestedSet.validate_if_child_exists(self)
+		frappe.utils.nestedset.update_nsm(self)
 
 		rec = frappe.db.sql("SELECT name from `tabGL Entry` where company = %s", self.name)
 		if not rec:
diff --git a/erpnext/setup/doctype/supplier_group/supplier_group.py b/erpnext/setup/doctype/supplier_group/supplier_group.py
index fa265d4..9d84f90 100644
--- a/erpnext/setup/doctype/supplier_group/supplier_group.py
+++ b/erpnext/setup/doctype/supplier_group/supplier_group.py
@@ -7,17 +7,16 @@
 from frappe.utils.nestedset import NestedSet, get_root_of
 
 class SupplierGroup(NestedSet):
-	nsm_parent_field = 'parent_supplier_group';
+	nsm_parent_field = 'parent_supplier_group'
+
 	def validate(self):
 		if not self.parent_supplier_group:
 			self.parent_supplier_group = get_root_of("Supplier Group")
 
-	def update_nsm_model(self):
-		frappe.utils.nestedset.update_nsm(self)
-
 	def on_update(self):
-		self.update_nsm_model()
+		NestedSet.on_update(self)
 		self.validate_one_root()
 
 	def on_trash(self):
-		self.update_nsm_model()
+		NestedSet.validate_if_child_exists(self)
+		frappe.utils.nestedset.update_nsm(self)