From 254ce645b1bfd5877da73643bbd44d2c4fcdab29 Mon Sep 17 00:00:00 2001 From: Zarrar Date: Thu, 28 Jun 2018 14:15:34 +0530 Subject: [PATCH] [ Enhance ] Setup Wizard - Chart of Accounts (#14698) * enable selection of coa for user Give user option to select coa that's been verified along with standard and standard with numbers. Also added a button that opens a dialog and renders the selected chart * read chart from file and make a tree render-able dict of it * tree method to return node data for coa setup wizard --- .../chart_of_accounts/chart_of_accounts.py | 27 +++++++ erpnext/accounts/utils.py | 16 +++++ erpnext/public/js/setup_wizard.js | 71 ++++++++++++++++--- 3 files changed, 106 insertions(+), 8 deletions(-) diff --git a/erpnext/accounts/doctype/account/chart_of_accounts/chart_of_accounts.py b/erpnext/accounts/doctype/account/chart_of_accounts/chart_of_accounts.py index 919f53bee2a..3f639cf48ef 100644 --- a/erpnext/accounts/doctype/account/chart_of_accounts/chart_of_accounts.py +++ b/erpnext/accounts/doctype/account/chart_of_accounts/chart_of_accounts.py @@ -198,3 +198,30 @@ def validate_bank_account(coa, bank_account): _get_account_names(chart) return (bank_account in accounts) + +@frappe.whitelist() +def build_tree_from_json(chart_template): + ''' get chart template from its folder and parse the json to be rendered as tree ''' + chart = get_chart(chart_template) + + # if no template selected, return as it is + if not chart: + return + + accounts = [] + def _import_accounts(children, parent): + ''' recursively called to form a parent-child based list of dict from chart template ''' + for account_name, child in iteritems(children): + account = {} + if account_name in ["account_number", "account_type",\ + "root_type", "is_group", "tax_rate"]: continue + + account['parent_account'] = parent + account['expandable'] = True if identify_is_group(child) else False + account['value'] = (child.get('account_number') + ' - ' + account_name) \ + if child.get('account_number') else account_name + accounts.append(account) + _import_accounts(child, account['value']) + + _import_accounts(chart, None) + return accounts diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py index e7ea7e166c7..f5df4c43108 100644 --- a/erpnext/accounts/utils.py +++ b/erpnext/accounts/utils.py @@ -814,3 +814,19 @@ def get_doc_name_autoname(field_value, doc_title, name, company): if cstr(field_value).strip(): parts.insert(0, cstr(field_value).strip()) return ' - '.join(parts) + +@frappe.whitelist() +def get_coa(doctype, parent, is_root, chart=None): + from erpnext.accounts.doctype.account.chart_of_accounts.chart_of_accounts import build_tree_from_json + + # add chart to flags to retrieve when called from expand all function + chart = chart if chart else frappe.flags.chart + frappe.flags.chart = chart + + parent = None if parent==_('All Accounts') else parent + accounts = build_tree_from_json(chart) # returns alist of dict in a tree render-able form + + # filter out to show data for the selected node only + accounts = [d for d in accounts if d['parent_account']==parent] + + return accounts diff --git a/erpnext/public/js/setup_wizard.js b/erpnext/public/js/setup_wizard.js index 2e4485796f1..29d00773153 100644 --- a/erpnext/public/js/setup_wizard.js +++ b/erpnext/public/js/setup_wizard.js @@ -123,6 +123,7 @@ erpnext.setup.slides_settings = [ fieldname: 'chart_of_accounts', label: __('Chart of Accounts'), options: "", fieldtype: 'Select' }, + { fieldname: 'view_coa', label: __('View Chart of Accounts'), fieldtype: 'Button' }, { fieldtype: "Section Break", label: __('Financial Year') }, { fieldname: 'fy_start_date', label: __('Start Date'), fieldtype: 'Date', reqd: 1 }, @@ -198,18 +199,11 @@ erpnext.setup.slides_settings = [ if (country) { frappe.call({ method: "erpnext.accounts.doctype.account.chart_of_accounts.chart_of_accounts.get_charts_for_country", - args: { "country": country }, + args: { "country": country, with_standard: true }, callback: function (r) { if (r.message) { slide.get_input("chart_of_accounts").empty() .add_options(r.message); - - if (r.message.length === 1) { - var field = slide.get_field("chart_of_accounts"); - field.set_value(r.message[0]); - field.df.hidden = 1; - field.refresh(); - } } } }) @@ -217,12 +211,73 @@ erpnext.setup.slides_settings = [ }, bind_events: function (slide) { + let me = this; slide.get_input("fy_start_date").on("change", function () { var start_date = slide.form.fields_dict.fy_start_date.get_value(); var year_end_date = frappe.datetime.add_days(frappe.datetime.add_months(start_date, 12), -1); slide.form.fields_dict.fy_end_date.set_value(year_end_date); }); + + slide.get_input("view_coa").on("click", function() { + let chart_template = slide.form.fields_dict.chart_of_accounts.get_value(); + if(!chart_template) return; + + me.charts_modal(slide, chart_template); + }); + }, + + charts_modal: function(slide, chart_template) { + let parent = __('All Accounts'); + + var dialog = new frappe.ui.Dialog({ + title: chart_template, + fields: [ + {'fieldname': 'expand_all', 'label': __('Expand All'), 'fieldtype': 'Button', + click: function() { + // expand all nodes on button click + coa_tree.load_children(coa_tree.root_node, true); + } + }, + {'fieldname': 'collapse_all', 'label': __('Collapse All'), 'fieldtype': 'Button', + click: function() { + // collapse all nodes + coa_tree.get_all_nodes(coa_tree.root_node.data.value, coa_tree.root_node.is_root) + .then(data_list => { + data_list.map(d => { coa_tree.toggle_node(coa_tree.nodes[d.parent]); }); + }); + } + } + ] + }); + + // render tree structure in the dialog modal + let coa_tree = new frappe.ui.Tree({ + parent: $(dialog.body), + label: parent, + expandable: true, + method: 'erpnext.accounts.utils.get_coa', + args: { + chart: chart_template, + parent: parent, + doctype: 'Account' + }, + onclick: function(node) { + parent = node.value; + } + }); + + // add class to show buttons side by side + $('.modal-content .form-column').addClass('row'); + $('div[data-fieldname="collapse_all"]') + .addClass('col-sm-2 col-xs-3') + .css({"width": "auto"}); + $('div[data-fieldname="expand_all"]') + .addClass('col-sm-2 col-xs-3') + .css({"width": "auto"}); + + dialog.show(); + coa_tree.load_children(coa_tree.root_node, true); // expand all node trigger } } ];