Merge pull request #4402 from nabinhait/allow_root_accounts

[feature] Allowed custom root accounts in Chart of Accounts
diff --git a/erpnext/accounts/doctype/account/account.py b/erpnext/accounts/doctype/account/account.py
index 8544b17..5c6aecd 100644
--- a/erpnext/accounts/doctype/account/account.py
+++ b/erpnext/accounts/doctype/account/account.py
@@ -65,12 +65,19 @@
 				if self.root_type != db_value.root_type:
 					frappe.db.sql("update `tabAccount` set root_type=%s where lft > %s and rgt < %s",
 						(self.root_type, self.lft, self.rgt))
+						
+		if self.root_type and not self.report_type:
+			self.report_type = "Balance Sheet" \
+				if self.root_type in ("Asset", "Liability", "Equity") else "Profit and Loss"
 
 	def validate_root_details(self):
 		# does not exists parent
 		if frappe.db.exists("Account", self.name):
 			if not frappe.db.get_value("Account", self.name, "parent_account"):
 				throw(_("Root cannot be edited."), RootNotEditable)
+				
+		if not self.parent_account and not self.is_group:
+			frappe.throw(_("Root Account must be a group"))
 
 	def validate_frozen_accounts_modifier(self):
 		old_value = frappe.db.get_value("Account", self.name, "freeze_account")
@@ -127,11 +134,11 @@
 			and docstatus != 2""", self.name)
 
 	def validate_mandatory(self):
-		if not self.report_type:
-			throw(_("Report Type is mandatory"))
-
 		if not self.root_type:
 			throw(_("Root Type is mandatory"))
+			
+		if not self.report_type:
+			throw(_("Report Type is mandatory"))
 
 	def validate_warehouse_account(self):
 		if not cint(frappe.defaults.get_global_default("auto_accounting_for_stock")):
diff --git a/erpnext/accounts/page/accounts_browser/accounts_browser.js b/erpnext/accounts/page/accounts_browser/accounts_browser.js
index b172ae0..6a2a831 100644
--- a/erpnext/accounts/page/accounts_browser/accounts_browser.js
+++ b/erpnext/accounts/page/accounts_browser/accounts_browser.js
@@ -117,7 +117,7 @@
 					}
 				},
 				{
-					condition: function(node) { return !node.root && node.expandable; },
+					condition: function(node) { return node.expandable; },
 					label: __("Add Child"),
 					click: function() {
 						me.make_new()
@@ -208,6 +208,9 @@
 					description: __("Name of new Account. Note: Please don't create accounts for Customers and Suppliers")},
 				{fieldtype:'Check', fieldname:'is_group', label:__('Is Group'),
 					description: __('Further accounts can be made under Groups, but entries can be made against non-Groups')},
+				{fieldtype:'Select', fieldname:'root_type', label:__('Root Type'),
+					options: ['Asset', 'Liability', 'Equity', 'Income', 'Expense'].join('\n'),
+				},
 				{fieldtype:'Select', fieldname:'account_type', label:__('Account Type'),
 					options: ['', 'Bank', 'Cash', 'Warehouse', 'Tax', 'Chargeable'].join('\n'),
 					description: __("Optional. This setting will be used to filter in various transactions.") },
@@ -237,6 +240,9 @@
 			$(fd.tax_rate.wrapper).toggle(fd.account_type.get_value()==='Tax');
 			$(fd.warehouse.wrapper).toggle(fd.account_type.get_value()==='Warehouse');
 		})
+		
+		// root type if root
+		$(fd.root_type.wrapper).toggle(node.root);
 
 		// create
 		d.set_primary_action(__("Create New"), function() {
@@ -252,6 +258,14 @@
 			var node = me.tree.get_selected_node();
 			v.parent_account = node.label;
 			v.company = me.company;
+			
+			if(node.root) {
+				v.is_root = true;
+				v.parent_account = null;
+			} else {
+				v.is_root = false;
+				v.root_type = null;
+			}
 
 			return frappe.call({
 				args: v,
diff --git a/erpnext/accounts/report/financial_statements.py b/erpnext/accounts/report/financial_statements.py
index be2e968..15e0553 100644
--- a/erpnext/accounts/report/financial_statements.py
+++ b/erpnext/accounts/report/financial_statements.py
@@ -80,8 +80,13 @@
 		return None
 
 	accounts, accounts_by_name = filter_accounts(accounts)
-	gl_entries_by_account = get_gl_entries(company, period_list[0]["from_date"], period_list[-1]["to_date"],
-		accounts[0].lft, accounts[0].rgt, ignore_closing_entries=ignore_closing_entries)
+	
+	gl_entries_by_account = {}
+	for root in frappe.db.sql("""select lft, rgt from tabAccount 
+			where root_type=%s and ifnull(parent_account, '') = ''""", root_type, as_dict=1):
+		set_gl_entries_by_account(company, period_list[0]["from_date"], 
+			period_list[-1]["to_date"],root.lft, root.rgt, gl_entries_by_account, 
+			ignore_closing_entries=ignore_closing_entries)
 
 	calculate_values(accounts_by_name, gl_entries_by_account, period_list)
 	accumulate_values_into_parents(accounts, accounts_by_name, period_list)
@@ -101,7 +106,6 @@
 				if entry.posting_date <= period.to_date:
 					d[period.key] = d.get(period.key, 0.0) + flt(entry.debit) - flt(entry.credit)
 
-
 def accumulate_values_into_parents(accounts, accounts_by_name, period_list):
 	"""accumulate children's values in parent accounts"""
 	for d in reversed(accounts):
@@ -143,15 +147,20 @@
 	return out
 
 def add_total_row(out, balance_must_be, period_list):
-	row = {
+	total_row = {
 		"account_name": "'" + _("Total ({0})").format(balance_must_be) + "'",
 		"account": None
 	}
-	for period in period_list:
-		row[period.key] = out[0].get(period.key, 0.0)
-		out[0][period.key] = ""
+	
+	for row in out:
+		if not row.get("parent_account"):
+			for period in period_list:
+				total_row.setdefault(period.key, 0.0)
+				total_row[period.key] += row.get(period.key, 0.0)
 
-	out.append(row)
+			row[period.key] = ""
+
+	out.append(total_row)
 
 	# blank row after Total
 	out.append({})
@@ -200,7 +209,8 @@
 
 	roots.sort(compare_roots)
 
-def get_gl_entries(company, from_date, to_date, root_lft, root_rgt, ignore_closing_entries=False):
+def set_gl_entries_by_account(company, from_date, to_date, root_lft, root_rgt, gl_entries_by_account, 
+		ignore_closing_entries=False):
 	"""Returns a dict like { "account": [gl entries], ... }"""
 	additional_conditions = []
 
@@ -226,7 +236,6 @@
 		},
 		as_dict=True)
 
-	gl_entries_by_account = {}
 	for entry in gl_entries:
 		gl_entries_by_account.setdefault(entry.account, []).append(entry)
 
diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py
index 05b771a..25ae482 100644
--- a/erpnext/accounts/utils.py
+++ b/erpnext/accounts/utils.py
@@ -134,6 +134,8 @@
 	ac.update(args)
 	ac.old_parent = ""
 	ac.freeze_account = "No"
+	if ac.get("is_root"):
+		ac.flags.ignore_mandatory = True
 	ac.insert()
 
 	return ac.name