Merge pull request #27751 from frappe/mergify/bp/develop/pr-27748
fix: Chart Of Accounts import button not visible (backport #27748)
diff --git a/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.js b/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.js
index f67c59c..66a269e 100644
--- a/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.js
+++ b/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.js
@@ -12,11 +12,6 @@
frm.set_df_property('import_file_section', 'hidden', frm.doc.company ? 0 : 1);
frm.set_df_property('chart_preview', 'hidden',
$(frm.fields_dict['chart_tree'].wrapper).html()!="" ? 0 : 1);
-
- // Show import button when file is successfully attached
- if (frm.page && frm.page.show_import_button) {
- create_import_button(frm);
- }
},
download_template: function(frm) {
@@ -78,7 +73,12 @@
frm.page.set_indicator("");
$(frm.fields_dict['chart_tree'].wrapper).empty(); // empty wrapper on removing file
} else {
- generate_tree_preview(frm);
+ frappe.run_serially([
+ () => validate_coa(frm),
+ () => generate_tree_preview(frm),
+ () => create_import_button(frm),
+ () => frm.set_df_property('chart_preview', 'hidden', 0),
+ ]);
}
},
@@ -104,24 +104,26 @@
});
var create_import_button = function(frm) {
- frm.page.set_primary_action(__("Import"), function () {
- frappe.call({
- method: "erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.import_coa",
- args: {
- file_name: frm.doc.import_file,
- company: frm.doc.company
- },
- freeze: true,
- freeze_message: __("Creating Accounts..."),
- callback: function(r) {
- if(!r.exc) {
- clearInterval(frm.page["interval"]);
- frm.page.set_indicator(__('Import Successful'), 'blue');
- create_reset_button(frm);
+ if (frm.page.show_import_button) {
+ frm.page.set_primary_action(__("Import"), function () {
+ return frappe.call({
+ method: "erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.import_coa",
+ args: {
+ file_name: frm.doc.import_file,
+ company: frm.doc.company
+ },
+ freeze: true,
+ freeze_message: __("Creating Accounts..."),
+ callback: function(r) {
+ if (!r.exc) {
+ clearInterval(frm.page["interval"]);
+ frm.page.set_indicator(__('Import Successful'), 'blue');
+ create_reset_button(frm);
+ }
}
- }
- });
- }).addClass('btn btn-primary');
+ });
+ }).addClass('btn btn-primary');
+ }
};
var create_reset_button = function(frm) {
@@ -132,13 +134,35 @@
}).addClass('btn btn-primary');
};
+var validate_coa = function(frm) {
+ if (frm.doc.import_file) {
+ let parent = __('All Accounts');
+
+ return frappe.call({
+ 'method': 'erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.get_coa',
+ 'args': {
+ file_name: frm.doc.import_file,
+ parent: parent,
+ doctype: 'Chart of Accounts Importer',
+ file_type: frm.doc.file_type,
+ for_validate: 1
+ },
+ callback: function(r) {
+ if (r.message['show_import_button']) {
+ frm.page['show_import_button'] = Boolean(r.message['show_import_button']);
+ }
+ }
+ });
+ }
+};
+
var generate_tree_preview = function(frm) {
if (frm.doc.import_file) {
let parent = __('All Accounts');
$(frm.fields_dict['chart_tree'].wrapper).empty(); // empty wrapper to load new data
// generate tree structure based on the csv data
- new frappe.ui.Tree({
+ return new frappe.ui.Tree({
parent: $(frm.fields_dict['chart_tree'].wrapper),
label: parent,
expandable: true,
diff --git a/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.py b/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.py
index 9a0234a..bd2a6f1 100644
--- a/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.py
+++ b/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.py
@@ -64,6 +64,7 @@
else:
data = generate_data_from_excel(file_doc, extension)
+ frappe.local.flags.ignore_root_company_validation = True
forest = build_forest(data)
create_charts(company, custom_chart=forest)
@@ -128,7 +129,7 @@
return data
@frappe.whitelist()
-def get_coa(doctype, parent, is_root=False, file_name=None):
+def get_coa(doctype, parent, is_root=False, file_name=None, for_validate=0):
''' called by tree view (to fetch node's children) '''
file_doc, extension = get_file(file_name)
@@ -140,14 +141,20 @@
data = generate_data_from_excel(file_doc, extension)
validate_columns(data)
- validate_accounts(data)
- forest = build_forest(data)
- accounts = build_tree_from_json("", chart_data=forest) # returns alist of dict in a tree render-able form
+ validate_accounts(file_doc, extension)
- # filter out to show data for the selected node only
- accounts = [d for d in accounts if d['parent_account']==parent]
+ if not for_validate:
+ forest = build_forest(data)
+ accounts = build_tree_from_json("", chart_data=forest) # returns a list of dict in a tree render-able form
- return accounts
+ # filter out to show data for the selected node only
+ accounts = [d for d in accounts if d['parent_account']==parent]
+
+ return accounts
+ else:
+ return {
+ 'show_import_button': 1
+ }
def build_forest(data):
'''
@@ -304,10 +311,7 @@
@frappe.whitelist()
-def validate_accounts(file_name):
-
- file_doc, extension = get_file(file_name)
-
+def validate_accounts(file_doc, extension):
if extension == 'csv':
accounts = generate_data_from_csv(file_doc, as_dict=True)
else:
@@ -326,8 +330,6 @@
validate_root(accounts_dict)
- validate_account_types(accounts_dict)
-
return [True, len(accounts)]
def validate_root(accounts):
@@ -340,9 +342,19 @@
elif account.get("root_type") not in get_root_types() and account.get("account_name"):
error_messages.append(_("Root Type for {0} must be one of the Asset, Liability, Income, Expense and Equity").format(account.get("account_name")))
+ validate_missing_roots(roots)
+
if error_messages:
frappe.throw("<br>".join(error_messages))
+def validate_missing_roots(roots):
+ root_types_added = set(d.get('root_type') for d in roots)
+
+ missing = list(set(get_root_types()) - root_types_added)
+
+ if missing:
+ frappe.throw(_("Please add Root Account for - {0}").format(' , '.join(missing)))
+
def get_root_types():
return ('Asset', 'Liability', 'Expense', 'Income', 'Equity')
@@ -368,15 +380,6 @@
{'account_type': 'Stock', 'root_type': 'Asset'}
]
-
-def validate_account_types(accounts):
- account_types_for_ledger = ["Cost of Goods Sold", "Depreciation", "Fixed Asset", "Payable", "Receivable", "Stock Adjustment"]
- account_types = [accounts[d]["account_type"] for d in accounts if not cint(accounts[d]['is_group']) == 1]
-
- missing = list(set(account_types_for_ledger) - set(account_types))
- if missing:
- frappe.throw(_("Please identify/create Account (Ledger) for type - {0}").format(' , '.join(missing)))
-
def unset_existing_data(company):
linked = frappe.db.sql('''select fieldname from tabDocField
where fieldtype="Link" and options="Account" and parent="Company"''', as_dict=True)