Merge branch 'develop' into accounting-dimension-mapping
diff --git a/erpnext/accounts/doctype/account/account.js b/erpnext/accounts/doctype/account/account.js
index 7a1d735..320e1ca 100644
--- a/erpnext/accounts/doctype/account/account.js
+++ b/erpnext/accounts/doctype/account/account.js
@@ -43,12 +43,12 @@
 				frm.trigger('add_toolbar_buttons');
 			}
 			if (frm.has_perm('write')) {
-				frm.add_custom_button(__('Update Account Name / Number'), function () {
-					frm.trigger("update_account_number");
-				});
 				frm.add_custom_button(__('Merge Account'), function () {
 					frm.trigger("merge_account");
-				});
+				}, __('Actions'));
+				frm.add_custom_button(__('Update Account Name / Number'), function () {
+					frm.trigger("update_account_number");
+				}, __('Actions'));
 			}
 		}
 	},
@@ -59,11 +59,12 @@
 		}
 	},
 	add_toolbar_buttons: function(frm) {
-		frm.add_custom_button(__('Chart of Accounts'),
-			function () { frappe.set_route("Tree", "Account"); });
+		frm.add_custom_button(__('Chart of Accounts'), () => {
+			frappe.set_route("Tree", "Account");
+		}, __('View'));
 
 		if (frm.doc.is_group == 1) {
-			frm.add_custom_button(__('Group to Non-Group'), function () {
+			frm.add_custom_button(__('Convert to Non-Group'), function () {
 				return frappe.call({
 					doc: frm.doc,
 					method: 'convert_group_to_ledger',
@@ -71,10 +72,11 @@
 						frm.refresh();
 					}
 				});
-			});
+			}, __('Actions'));
+
 		} else if (cint(frm.doc.is_group) == 0
 			&& frappe.boot.user.can_read.indexOf("GL Entry") !== -1) {
-			frm.add_custom_button(__('Ledger'), function () {
+			frm.add_custom_button(__('General Ledger'), function () {
 				frappe.route_options = {
 					"account": frm.doc.name,
 					"from_date": frappe.sys_defaults.year_start_date,
@@ -82,9 +84,9 @@
 					"company": frm.doc.company
 				};
 				frappe.set_route("query-report", "General Ledger");
-			});
+			}, __('View'));
 
-			frm.add_custom_button(__('Non-Group to Group'), function () {
+			frm.add_custom_button(__('Convert to Group'), function () {
 				return frappe.call({
 					doc: frm.doc,
 					method: 'convert_ledger_to_group',
@@ -92,7 +94,7 @@
 						frm.refresh();
 					}
 				});
-			});
+			}, __('Actions'));
 		}
 	},
 
diff --git a/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.json b/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.json
index bc92418..daee8f8 100644
--- a/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.json
+++ b/erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.json
@@ -75,7 +75,7 @@
  ],
  "hide_toolbar": 1,
  "issingle": 1,
- "modified": "2019-07-25 14:57:33.187689",
+ "modified": "2022-01-04 15:25:06.053187",
  "modified_by": "Administrator",
  "module": "Accounts",
  "name": "Opening Invoice Creation Tool",
diff --git a/erpnext/regional/doctype/uae_vat_settings/uae_vat_settings.js b/erpnext/regional/doctype/uae_vat_settings/uae_vat_settings.js
index 07a9301..6653141 100644
--- a/erpnext/regional/doctype/uae_vat_settings/uae_vat_settings.js
+++ b/erpnext/regional/doctype/uae_vat_settings/uae_vat_settings.js
@@ -2,7 +2,13 @@
 // For license information, please see license.txt
 
 frappe.ui.form.on('UAE VAT Settings', {
-	// refresh: function(frm) {
-
-	// }
+	onload: function(frm) {
+		frm.set_query('account', 'uae_vat_accounts', function() {
+			return {
+				filters: {
+					'company': frm.doc.company
+				}
+			};
+		});
+	}
 });
diff --git a/erpnext/selling/page/point_of_sale/pos_controller.js b/erpnext/selling/page/point_of_sale/pos_controller.js
index e61a634..ce74f6d 100644
--- a/erpnext/selling/page/point_of_sale/pos_controller.js
+++ b/erpnext/selling/page/point_of_sale/pos_controller.js
@@ -643,7 +643,7 @@
 				message: __('Item Code: {0} is not available under warehouse {1}.', [bold_item_code, bold_warehouse])
 			})
 		} else if (available_qty < qty_needed) {
-			frappe.show_alert({
+			frappe.throw({
 				message: __('Stock quantity not enough for Item Code: {0} under warehouse {1}. Available quantity {2}.', [bold_item_code, bold_warehouse, bold_available_qty]),
 				indicator: 'orange'
 			});
diff --git a/erpnext/selling/page/point_of_sale/pos_item_selector.js b/erpnext/selling/page/point_of_sale/pos_item_selector.js
index 4963852..a30bcd7 100644
--- a/erpnext/selling/page/point_of_sale/pos_item_selector.js
+++ b/erpnext/selling/page/point_of_sale/pos_item_selector.js
@@ -113,7 +113,7 @@
 			`<div class="item-wrapper"
 				data-item-code="${escape(item.item_code)}" data-serial-no="${escape(serial_no)}"
 				data-batch-no="${escape(batch_no)}" data-uom="${escape(stock_uom)}"
-				data-rate="${escape(price_list_rate)}"
+				data-rate="${escape(price_list_rate || 0)}"
 				title="${item.item_name}">
 
 				${get_item_image_html()}
diff --git a/erpnext/setup/doctype/company/company.js b/erpnext/setup/doctype/company/company.js
index 91f60fb..45e8dcc 100644
--- a/erpnext/setup/doctype/company/company.js
+++ b/erpnext/setup/doctype/company/company.js
@@ -79,14 +79,11 @@
 	},
 
 	refresh: function(frm) {
-		if(!frm.doc.__islocal) {
-			frm.doc.abbr && frm.set_df_property("abbr", "read_only", 1);
-			frm.set_df_property("parent_company", "read_only", 1);
-			disbale_coa_fields(frm);
-		}
+		frm.toggle_display('address_html', !frm.is_new());
 
-		frm.toggle_display('address_html', !frm.doc.__islocal);
-		if(!frm.doc.__islocal) {
+		if (!frm.is_new()) {
+			frm.doc.abbr && frm.set_df_property("abbr", "read_only", 1);
+			disbale_coa_fields(frm);
 			frappe.contacts.render_address_and_contact(frm);
 
 			frappe.dynamic_link = {doc: frm.doc, fieldname: 'name', doctype: 'Company'}
diff --git a/erpnext/setup/doctype/company/company.py b/erpnext/setup/doctype/company/company.py
index e739739..0a02bcd 100644
--- a/erpnext/setup/doctype/company/company.py
+++ b/erpnext/setup/doctype/company/company.py
@@ -47,6 +47,7 @@
 		self.validate_perpetual_inventory()
 		self.validate_perpetual_inventory_for_non_stock_items()
 		self.check_country_change()
+		self.check_parent_changed()
 		self.set_chart_of_accounts()
 		self.validate_parent_company()
 
@@ -130,6 +131,10 @@
 			self.name in frappe.local.enable_perpetual_inventory:
 			frappe.local.enable_perpetual_inventory[self.name] = self.enable_perpetual_inventory
 
+		if frappe.flags.parent_company_changed:
+			from frappe.utils.nestedset import rebuild_tree
+			rebuild_tree("Company", "parent_company")
+
 		frappe.clear_cache()
 
 	def create_default_warehouses(self):
@@ -191,7 +196,7 @@
 	def check_country_change(self):
 		frappe.flags.country_change = False
 
-		if not self.get('__islocal') and \
+		if not self.is_new() and \
 			self.country != frappe.get_cached_value('Company',  self.name,  'country'):
 			frappe.flags.country_change = True
 
@@ -396,6 +401,13 @@
 		if not frappe.db.get_value('GL Entry', {'company': self.name}):
 			frappe.db.sql("delete from `tabProcess Deferred Accounting` where company=%s", self.name)
 
+	def check_parent_changed(self):
+		frappe.flags.parent_company_changed = False
+
+		if not self.is_new() and \
+			self.parent_company != frappe.db.get_value("Company",  self.name,  "parent_company"):
+			frappe.flags.parent_company_changed = True
+
 def get_name_with_abbr(name, company):
 	company_abbr = frappe.get_cached_value('Company',  company,  "abbr")
 	parts = name.split(" - ")
diff --git a/erpnext/setup/doctype/company/test_company.py b/erpnext/setup/doctype/company/test_company.py
index 4ee9492..e175c54 100644
--- a/erpnext/setup/doctype/company/test_company.py
+++ b/erpnext/setup/doctype/company/test_company.py
@@ -93,6 +93,61 @@
 		frappe.db.sql(""" delete from `tabMode of Payment Account`
 			where company =%s """, (company))
 
+	def test_basic_tree(self, records=None):
+		min_lft = 1
+		max_rgt = frappe.db.sql("select max(rgt) from `tabCompany`")[0][0]
+
+		if not records:
+			records = test_records[2:]
+
+		for company in records:
+			lft, rgt, parent_company = frappe.db.get_value("Company", company["company_name"],
+				["lft", "rgt", "parent_company"])
+
+			if parent_company:
+				parent_lft, parent_rgt = frappe.db.get_value("Company", parent_company,
+					["lft", "rgt"])
+			else:
+				# root
+				parent_lft = min_lft - 1
+				parent_rgt = max_rgt + 1
+
+			self.assertTrue(lft)
+			self.assertTrue(rgt)
+			self.assertTrue(lft < rgt)
+			self.assertTrue(parent_lft < parent_rgt)
+			self.assertTrue(lft > parent_lft)
+			self.assertTrue(rgt < parent_rgt)
+			self.assertTrue(lft >= min_lft)
+			self.assertTrue(rgt <= max_rgt)
+
+	def get_no_of_children(self, company):
+		def get_no_of_children(companies, no_of_children):
+			children = []
+			for company in companies:
+				children += frappe.db.sql_list("""select name from `tabCompany`
+				where ifnull(parent_company, '')=%s""", company or '')
+
+			if len(children):
+				return get_no_of_children(children, no_of_children + len(children))
+			else:
+				return no_of_children
+
+		return get_no_of_children([company], 0)
+
+	def test_change_parent_company(self):
+		child_company = frappe.get_doc("Company", "_Test Company 5")
+
+		# changing parent of company
+		child_company.parent_company = "_Test Company 3"
+		child_company.save()
+		self.test_basic_tree()
+
+		# move it back
+		child_company.parent_company = "_Test Company 4"
+		child_company.save()
+		self.test_basic_tree()
+
 def create_company_communication(doctype, docname):
 	comm = frappe.get_doc({
 			"doctype": "Communication",