diff --git a/erpnext/accounts/doctype/account/account.py b/erpnext/accounts/doctype/account/account.py index 8544b178c9..5c6aecd31f 100644 --- a/erpnext/accounts/doctype/account/account.py +++ b/erpnext/accounts/doctype/account/account.py @@ -65,12 +65,19 @@ class Account(Document): 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 @@ class Account(Document): 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 b172ae0db2..6a2a8312f2 100644 --- a/erpnext/accounts/page/accounts_browser/accounts_browser.js +++ b/erpnext/accounts/page/accounts_browser/accounts_browser.js @@ -117,7 +117,7 @@ erpnext.AccountsChart = Class.extend({ } }, { - 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 @@ erpnext.AccountsChart = Class.extend({ 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 @@ erpnext.AccountsChart = Class.extend({ $(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 @@ erpnext.AccountsChart = Class.extend({ 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 be2e968b63..15e0553b0b 100644 --- a/erpnext/accounts/report/financial_statements.py +++ b/erpnext/accounts/report/financial_statements.py @@ -80,8 +80,13 @@ def get_data(company, root_type, balance_must_be, period_list, ignore_closing_en 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 @@ def calculate_values(accounts_by_name, gl_entries_by_account, period_list): 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 @@ def prepare_data(accounts, balance_must_be, period_list): 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 @@ def sort_root_accounts(roots): 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 @@ def get_gl_entries(company, from_date, to_date, root_lft, root_rgt, ignore_closi }, 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 05b771a22a..25ae4822ba 100644 --- a/erpnext/accounts/utils.py +++ b/erpnext/accounts/utils.py @@ -134,6 +134,8 @@ def add_ac(args=None): 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