Skip to content

Commit

Permalink
Merge pull request #37 from vjFaLk/parsimony-production-v13
Browse files Browse the repository at this point in the history
  • Loading branch information
vjFaLk authored Oct 6, 2021
2 parents 8220e61 + 0db3f06 commit b9e244c
Show file tree
Hide file tree
Showing 140 changed files with 2,633 additions and 5,134 deletions.
6 changes: 3 additions & 3 deletions .github/helper/documentation.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ def docs_link_exists(body):

if response.ok:
payload = response.json()
title = payload.get("title", "").lower().strip()
head_sha = payload.get("head", {}).get("sha")
body = payload.get("body", "").lower()
title = (payload.get("title") or "").lower().strip()
head_sha = (payload.get("head") or {}).get("sha")
body = (payload.get("body") or "").lower()

if (title.startswith("feat")
and head_sha
Expand Down
8 changes: 0 additions & 8 deletions .snyk

This file was deleted.

2 changes: 1 addition & 1 deletion cypress/integration/test_organizational_chart_desktop.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ context('Organizational Chart', () => {

it('navigates to org chart', () => {
cy.visit('/app');
cy.awesomebar('Organizational Chart');
cy.visit('/app/organizational-chart');
cy.url().should('include', '/organizational-chart');

cy.window().its('frappe.csrf_token').then(csrf_token => {
Expand Down
2 changes: 1 addition & 1 deletion cypress/integration/test_organizational_chart_mobile.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ context('Organizational Chart Mobile', () => {
it('navigates to org chart', () => {
cy.viewport(375, 667);
cy.visit('/app');
cy.awesomebar('Organizational Chart');
cy.visit('/app/organizational-chart');
cy.url().should('include', '/organizational-chart');

cy.window().its('frappe.csrf_token').then(csrf_token => {
Expand Down
2 changes: 1 addition & 1 deletion erpnext/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

from erpnext.hooks import regional_overrides

__version__ = '13.11.1'
__version__ = '13.12.0'

def get_default_company(user=None):
'''Get default company for user'''
Expand Down
15 changes: 9 additions & 6 deletions erpnext/accounts/deferred_revenue.py
Original file line number Diff line number Diff line change
Expand Up @@ -374,12 +374,15 @@ def make_gl_entries(doc, credit_account, debit_account, against,
try:
make_gl_entries(gl_entries, cancel=(doc.docstatus == 2), merge_entries=True)
frappe.db.commit()
except Exception:
frappe.db.rollback()
traceback = frappe.get_traceback()
frappe.log_error(message=traceback)

frappe.flags.deferred_accounting_error = True
except Exception as e:
if frappe.flags.in_test:
raise e
else:
frappe.db.rollback()
traceback = frappe.get_traceback()
frappe.log_error(message=traceback)

frappe.flags.deferred_accounting_error = True

def send_mail(deferred_process):
title = _("Error while processing deferred accounting for {0}").format(deferred_process)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,17 @@ frappe.ui.form.on('Chart of Accounts Importer', {
// make company mandatory
frm.set_df_property('company', 'reqd', frm.doc.company ? 0 : 1);
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);
if (frm.doc.import_file) {
frappe.run_serially([
() => generate_tree_preview(frm),
() => create_import_button(frm),
() => frm.set_df_property('chart_preview', 'hidden', 0)
]);
}

frm.set_df_property('chart_preview', 'hidden',
$(frm.fields_dict['chart_tree'].wrapper).html()!="" ? 0 : 1);
},

download_template: function(frm) {
Expand Down Expand Up @@ -77,9 +81,6 @@ frappe.ui.form.on('Chart of Accounts Importer', {
if (!frm.doc.import_file) {
frm.page.set_indicator("");
$(frm.fields_dict['chart_tree'].wrapper).empty(); // empty wrapper on removing file
} else {
generate_tree_preview(frm);
validate_csv_data(frm);
}
},

Expand All @@ -104,26 +105,9 @@ frappe.ui.form.on('Chart of Accounts Importer', {
}
});

var validate_csv_data = function(frm) {
frappe.call({
method: "erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.validate_accounts",
args: {file_name: frm.doc.import_file},
callback: function(r) {
if(r.message && r.message[0]===true) {
frm.page["show_import_button"] = true;
frm.page["total_accounts"] = r.message[1];
frm.trigger("refresh");
} else {
frm.page.set_indicator(__('Resolve error and upload again.'), 'orange');
frappe.throw(__(r.message));
}
}
});
};

var create_import_button = function(frm) {
frm.page.set_primary_action(__("Import"), function () {
frappe.call({
return frappe.call({
method: "erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.import_coa",
args: {
file_name: frm.doc.import_file,
Expand All @@ -132,7 +116,7 @@ var create_import_button = function(frm) {
freeze: true,
freeze_message: __("Creating Accounts..."),
callback: function(r) {
if(!r.exc) {
if (!r.exc) {
clearInterval(frm.page["interval"]);
frm.page.set_indicator(__('Import Successful'), 'blue');
create_reset_button(frm);
Expand All @@ -150,12 +134,33 @@ var create_reset_button = function(frm) {
}).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) {
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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,18 @@

class ChartofAccountsImporter(Document):
def validate(self):
validate_accounts(self.import_file)
if self.import_file:
get_coa('Chart of Accounts Importer', 'All Accounts', file_name=self.import_file, for_validate=1)

def validate_columns(data):
if not data:
frappe.throw(_('No data found. Seems like you uploaded a blank file'))

no_of_columns = max([len(d) for d in data])

if no_of_columns > 7:
frappe.throw(_('More columns found than expected. Please compare the uploaded file with standard template'),
title=(_("Wrong Template")))

@frappe.whitelist()
def validate_company(company):
Expand Down Expand Up @@ -55,6 +66,7 @@ def import_coa(file_name, company):
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)

Expand Down Expand Up @@ -119,7 +131,7 @@ def generate_data_from_excel(file_doc, extension, as_dict=False):
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)
Expand All @@ -130,13 +142,21 @@ def get_coa(doctype, parent, is_root=False, file_name=None):
else:
data = generate_data_from_excel(file_doc, extension)

forest = build_forest(data)
accounts = build_tree_from_json("", chart_data=forest) # returns alist of dict in a tree render-able form
validate_columns(data)
validate_accounts(file_doc, extension)

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

# filter out to show data for the selected node only
accounts = [d for d in accounts if d['parent_account']==parent]
# filter out to show data for the selected node only
accounts = [d for d in accounts if d['parent_account']==parent]

return accounts
return accounts
else:
return {
'show_import_button': 1
}


def build_forest(data):
Expand Down Expand Up @@ -307,10 +327,7 @@ def get_sample_template(writer):


@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:
Expand All @@ -329,15 +346,10 @@ def validate_accounts(file_name):

validate_root(accounts_dict)

validate_account_types(accounts_dict)

return [True, len(accounts)]

def validate_root(accounts):
roots = [accounts[d] for d in accounts if not accounts[d].get('parent_account')]
if len(roots) < 4:
frappe.throw(_("Number of root accounts cannot be less than 4"))

error_messages = []

for account in roots:
Expand All @@ -346,9 +358,19 @@ def validate_root(accounts):
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')

Expand All @@ -374,23 +396,6 @@ def get_mandatory_account_types():
{'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 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)))

account_types_for_group = ["Bank", "Cash", "Stock"]
# fix logic bug
account_groups = [accounts[d]["account_type"] for d in accounts if accounts[d]['is_group'] == 1]

missing = list(set(account_types_for_group) - set(account_groups))
if missing:
frappe.throw(_("Please identify/create Account (Group) 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)
Expand Down
Loading

0 comments on commit b9e244c

Please sign in to comment.