Merge branch 'develop' of https://github.com/frappe/erpnext into develop
diff --git a/erpnext/accounts/doctype/account/account.py b/erpnext/accounts/doctype/account/account.py
index 1407d5f..d5a36b8 100644
--- a/erpnext/accounts/doctype/account/account.py
+++ b/erpnext/accounts/doctype/account/account.py
@@ -108,9 +108,9 @@
parent_acc_name_map = {}
parent_acc_name, parent_acc_number = frappe.db.get_value('Account', self.parent_account, \
["account_name", "account_number"])
- filters = {
+ filters = {
"company": ["in", descendants],
- "account_name": parent_acc_name,
+ "account_name": parent_acc_name,
}
if parent_acc_number:
filters["account_number"] = parent_acc_number
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 40a97ae..0b7cff3 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
@@ -17,17 +17,60 @@
if (frm.page && frm.page.show_import_button) {
create_import_button(frm);
}
+ },
- // show download template button when company is properly selected
- if(frm.doc.company) {
- // download the csv template file
- frm.add_custom_button(__("Download template"), function () {
- let get_template_url = 'erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.download_template';
- open_url_post(frappe.request.url, { cmd: get_template_url, doctype: frm.doc.doctype });
- });
- } else {
- frm.set_value("import_file", "");
- }
+ download_template: function(frm) {
+ var d = new frappe.ui.Dialog({
+ title: __("Download Template"),
+ fields: [
+ {
+ label : "File Type",
+ fieldname: "file_type",
+ fieldtype: "Select",
+ reqd: 1,
+ options: ["Excel", "CSV"]
+ },
+ {
+ label: "Template Type",
+ fieldname: "template_type",
+ fieldtype: "Select",
+ reqd: 1,
+ options: ["Sample Template", "Blank Template"],
+ change: () => {
+ let template_type = d.get_value('template_type');
+
+ if (template_type === "Sample Template") {
+ d.set_df_property('template_type', 'description',
+ `The Sample Template contains all the required accounts pre filled in the template.
+ You can add more accounts or change existing accounts in the template as per your choice.`);
+ } else {
+ d.set_df_property('template_type', 'description',
+ `The Blank Template contains just the account type and root type required to build the Chart
+ of Accounts. Please enter the account names and add more rows as per your requirement.`);
+ }
+ }
+ }
+ ],
+ primary_action: function() {
+ var data = d.get_values();
+
+ if (!data.template_type) {
+ frappe.throw(__('Please select <b>Template Type</b> to download template'));
+ }
+
+ open_url_post(
+ '/api/method/erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.download_template',
+ {
+ file_type: data.file_type,
+ template_type: data.template_type
+ }
+ );
+
+ d.hide();
+ },
+ primary_action_label: __('Download')
+ });
+ d.show();
},
import_file: function (frm) {
@@ -41,21 +84,24 @@
},
company: function (frm) {
- // validate that no Gl Entry record for the company exists.
- frappe.call({
- method: "erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.validate_company",
- args: {
- company: frm.doc.company
- },
- callback: function(r) {
- if(r.message===false) {
- frm.set_value("company", "");
- frappe.throw(__("Transactions against the company already exist! "));
- } else {
- frm.trigger("refresh");
+ if (frm.doc.company) {
+ // validate that no Gl Entry record for the company exists.
+ frappe.call({
+ method: "erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.validate_company",
+ args: {
+ company: frm.doc.company
+ },
+ callback: function(r) {
+ if(r.message===false) {
+ frm.set_value("company", "");
+ frappe.throw(__(`Transactions against the company already exist!
+ Chart Of accounts can be imported for company with no transactions`));
+ } else {
+ frm.trigger("refresh");
+ }
}
- }
- });
+ });
+ }
}
});
@@ -77,7 +123,7 @@
};
var create_import_button = function(frm) {
- frm.page.set_primary_action(__("Start Import"), function () {
+ frm.page.set_primary_action(__("Import"), function () {
frappe.call({
method: "erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.import_coa",
args: {
@@ -118,7 +164,8 @@
args: {
file_name: frm.doc.import_file,
parent: parent,
- doctype: 'Chart of Accounts Importer'
+ doctype: 'Chart of Accounts Importer',
+ file_type: frm.doc.file_type
},
onclick: function(node) {
parent = node.value;
diff --git a/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.json b/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.json
index d544e69..ee095ac 100644
--- a/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.json
+++ b/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.json
@@ -1,226 +1,71 @@
{
- "allow_copy": 1,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "beta": 0,
- "creation": "2019-02-01 12:24:34.761380",
- "custom": 0,
+ "actions": [],
+ "allow_copy": 1,
+ "creation": "2019-02-01 12:24:34.761380",
"description": "Import Chart of Accounts from a csv file",
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "Other",
- "editable_grid": 1,
- "engine": "InnoDB",
+ "doctype": "DocType",
+ "document_type": "Other",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "company",
+ "download_template",
+ "import_file",
+ "chart_preview",
+ "chart_tree"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "company",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Company",
- "length": 0,
- "no_copy": 0,
- "options": "Company",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "company",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Company",
+ "options": "Company"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "import_file_section",
- "fieldtype": "Section Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "depends_on": "",
+ "depends_on": "company",
"fieldname": "import_file",
"fieldtype": "Attach",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Attach custom Chart of Accounts file",
- "length": 0,
- "no_copy": 0,
- "options": "",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "label": "Attach custom Chart of Accounts file"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
"collapsible": 1,
- "columns": 0,
"fieldname": "chart_preview",
- "fieldtype": "Section Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Chart Preview",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldtype": "Section Break",
+ "label": "Chart Preview"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
"fieldname": "chart_tree",
"fieldtype": "HTML",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Chart Tree",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "label": "Chart Tree"
+ },
+ {
+ "depends_on": "company",
+ "fieldname": "download_template",
+ "fieldtype": "Button",
+ "label": "Download Template"
}
- ],
- "has_web_view": 0,
- "hide_heading": 1,
- "hide_toolbar": 1,
- "idx": 0,
- "image_view": 0,
- "in_create": 1,
- "is_submittable": 0,
- "issingle": 1,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2019-02-04 23:10:30.136807",
- "modified_by": "Administrator",
- "module": "Accounts",
- "name": "Chart of Accounts Importer",
- "name_case": "",
- "owner": "Administrator",
+ ],
+ "hide_toolbar": 1,
+ "in_create": 1,
+ "issingle": 1,
+ "links": [],
+ "modified": "2020-02-28 08:49:11.422846",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Chart of Accounts Importer",
+ "owner": "Administrator",
"permissions": [
{
- "amend": 0,
- "cancel": 0,
- "create": 1,
- "delete": 0,
- "email": 0,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 0,
- "read": 1,
- "report": 0,
- "role": "Accounts Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 0,
+ "create": 1,
+ "read": 1,
+ "role": "Accounts Manager",
+ "share": 1,
"write": 1
}
- ],
- "quick_entry": 1,
- "read_only": 1,
- "read_only_onload": 0,
- "show_name_in_global_search": 0,
- "sort_field": "",
- "sort_order": "DESC",
- "track_changes": 0,
- "track_seen": 0,
- "track_views": 0
+ ],
+ "quick_entry": 1,
+ "read_only": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC"
}
\ No newline at end of file
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 362efef..b6f5396 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
@@ -4,18 +4,28 @@
from __future__ import unicode_literals
from functools import reduce
-import frappe, csv
+import frappe, csv, os
from frappe import _
-from frappe.utils import cstr
+from frappe.utils import cstr, cint
from frappe.model.document import Document
from frappe.utils.csvutils import UnicodeWriter
from erpnext.accounts.doctype.account.chart_of_accounts.chart_of_accounts import create_charts, build_tree_from_json
+from frappe.utils.xlsxutils import read_xlsx_file_from_attached_file, read_xls_file_from_attached_file
class ChartofAccountsImporter(Document):
pass
@frappe.whitelist()
def validate_company(company):
+ parent_company, allow_account_creation_against_child_company = frappe.db.get_value('Company',
+ {'name': company}, ['parent_company',
+ 'allow_account_creation_against_child_company'])
+
+ if parent_company and (not allow_account_creation_against_child_company):
+ frappe.throw(_("""{0} is a child company. Please import accounts against parent company
+ or enable {1} in company master""").format(frappe.bold(company),
+ frappe.bold('Allow Account Creation Against Child Company')), title='Wrong Company')
+
if frappe.db.get_all('GL Entry', {"company": company}, "name", limit=1):
return False
@@ -25,42 +35,85 @@
unset_existing_data(company)
# create accounts
- forest = build_forest(generate_data_from_csv(file_name))
+ file_doc, extension = get_file(file_name)
+
+ if extension == 'csv':
+ data = generate_data_from_csv(file_doc)
+ else:
+ data = generate_data_from_excel(file_doc, extension)
+
+ forest = build_forest(data)
create_charts(company, custom_chart=forest)
# trigger on_update for company to reset default accounts
set_default_accounts(company)
-def generate_data_from_csv(file_name, as_dict=False):
- ''' read csv file and return the generated nested tree '''
- if not file_name.endswith('.csv'):
- frappe.throw("Only CSV files can be used to for importing data. Please check the file format you are trying to upload")
+def get_file(file_name):
+ file_doc = frappe.get_doc("File", {"file_url": file_name})
+ parts = file_doc.get_extension()
+ extension = parts[1]
+ extension = extension.lstrip(".")
- file_doc = frappe.get_doc('File', {"file_url": file_name})
+ if extension not in ('csv', 'xlsx', 'xls'):
+ frappe.throw("Only CSV and Excel files can be used to for importing data. Please check the file format you are trying to upload")
+
+ return file_doc, extension
+
+def generate_data_from_csv(file_doc, as_dict=False):
+ ''' read csv file and return the generated nested tree '''
+
file_path = file_doc.get_full_path()
data = []
with open(file_path, 'r') as in_file:
csv_reader = list(csv.reader(in_file))
- headers = csv_reader[1][1:]
- del csv_reader[0:2] # delete top row and headers row
+ headers = csv_reader[0]
+ del csv_reader[0] # delete top row and headers row
for row in csv_reader:
if as_dict:
- data.append({frappe.scrub(header): row[index+1] for index, header in enumerate(headers)})
+ data.append({frappe.scrub(header): row[index] for index, header in enumerate(headers)})
else:
- if not row[2]: row[2] = row[1]
- data.append(row[1:])
+ if not row[1]: row[1] = row[0]
+ data.append(row)
# convert csv data
return data
+def generate_data_from_excel(file_doc, extension, as_dict=False):
+ content = file_doc.get_content()
+
+ if extension == "xlsx":
+ rows = read_xlsx_file_from_attached_file(fcontent=content)
+ elif extension == "xls":
+ rows = read_xls_file_from_attached_file(content)
+
+ data = []
+ headers = rows[0]
+ del rows[0]
+
+ for row in rows:
+ if as_dict:
+ data.append({frappe.scrub(header): row[index] for index, header in enumerate(headers)})
+ else:
+ if not row[1]: row[1] = row[0]
+ data.append(row)
+
+ return data
+
@frappe.whitelist()
def get_coa(doctype, parent, is_root=False, file_name=None):
''' called by tree view (to fetch node's children) '''
+ file_doc, extension = get_file(file_name)
parent = None if parent==_('All Accounts') else parent
- forest = build_forest(generate_data_from_csv(file_name))
+
+ if extension == 'csv':
+ data = generate_data_from_csv(file_doc)
+ 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
# filter out to show data for the selected node only
@@ -91,6 +144,8 @@
# returns the path of any node in list format
def return_parent(data, child):
+ from frappe import _
+
for row in data:
account_name, parent_account = row[0:2]
if parent_account == account_name == child:
@@ -98,8 +153,9 @@
elif account_name == child:
parent_account_list = return_parent(data, parent_account)
if not parent_account_list:
- frappe.throw(_("The parent account {0} does not exists")
- .format(parent_account))
+ frappe.throw(_("The parent account {0} does not exists in the uploaded template").format(
+ frappe.bold(parent_account)))
+
return [child] + parent_account_list
charts_map, paths = {}, []
@@ -114,7 +170,7 @@
error_messages.append("Row {0}: Please enter Account Name".format(line_no))
charts_map[account_name] = {}
- if is_group == 1: charts_map[account_name]["is_group"] = is_group
+ if cint(is_group) == 1: charts_map[account_name]["is_group"] = is_group
if account_type: charts_map[account_name]["account_type"] = account_type
if root_type: charts_map[account_name]["root_type"] = root_type
if account_number: charts_map[account_name]["account_number"] = account_number
@@ -132,24 +188,94 @@
return out
+def build_response_as_excel(writer):
+ filename = frappe.generate_hash("", 10)
+ with open(filename, 'wb') as f:
+ f.write(cstr(writer.getvalue()).encode('utf-8'))
+ f = open(filename)
+ reader = csv.reader(f)
+
+ from frappe.utils.xlsxutils import make_xlsx
+ xlsx_file = make_xlsx(reader, "Chart Of Accounts Importer Template")
+
+ f.close()
+ os.remove(filename)
+
+ # write out response as a xlsx type
+ frappe.response['filename'] = 'coa_importer_template.xlsx'
+ frappe.response['filecontent'] = xlsx_file.getvalue()
+ frappe.response['type'] = 'binary'
+
@frappe.whitelist()
-def download_template():
+def download_template(file_type, template_type):
data = frappe._dict(frappe.local.form_dict)
+
+ writer = get_template(template_type)
+
+ if file_type == 'CSV':
+ # download csv file
+ frappe.response['result'] = cstr(writer.getvalue())
+ frappe.response['type'] = 'csv'
+ frappe.response['doctype'] = 'Chart of Accounts Importer'
+ else:
+ build_response_as_excel(writer)
+
+def get_template(template_type):
+
fields = ["Account Name", "Parent Account", "Account Number", "Is Group", "Account Type", "Root Type"]
writer = UnicodeWriter()
+ writer.writerow(fields)
- writer.writerow([_('Chart of Accounts Template')])
- writer.writerow([_("Column Labels : ")] + fields)
- writer.writerow([_("Start entering data from here : ")])
+ if template_type == 'Blank Template':
+ for root_type in get_root_types():
+ writer.writerow(['', '', '', 1, '', root_type])
- # download csv file
- frappe.response['result'] = cstr(writer.getvalue())
- frappe.response['type'] = 'csv'
- frappe.response['doctype'] = data.get('doctype')
+ for account in get_mandatory_group_accounts():
+ writer.writerow(['', '', '', 1, account, "Asset"])
+
+ for account_type in get_mandatory_account_types():
+ writer.writerow(['', '', '', 0, account_type.get('account_type'), account_type.get('root_type')])
+ else:
+ writer = get_sample_template(writer)
+
+ return writer
+
+def get_sample_template(writer):
+ template = [
+ ["Application Of Funds(Assets)", "", "", 1, "", "Asset"],
+ ["Sources Of Funds(Liabilities)", "", "", 1, "", "Liability"],
+ ["Equity", "", "", 1, "", "Equity"],
+ ["Expenses", "", "", 1, "", "Expense"],
+ ["Income", "", "", 1, "", "Income"],
+ ["Bank Accounts", "Application Of Funds(Assets)", "", 1, "Bank", "Asset"],
+ ["Cash In Hand", "Application Of Funds(Assets)", "", 1, "Cash", "Asset"],
+ ["Stock Assets", "Application Of Funds(Assets)", "", 1, "Stock", "Asset"],
+ ["Cost Of Goods Sold", "Expenses", "", 0, "Cost of Goods Sold", "Expense"],
+ ["Asset Depreciation", "Expenses", "", 0, "Depreciation", "Expense"],
+ ["Fixed Assets", "Application Of Funds(Assets)", "", 0, "Fixed Asset", "Asset"],
+ ["Accounts Payable", "Sources Of Funds(Liabilities)", "", 0, "Payable", "Liability"],
+ ["Accounts Receivable", "Application Of Funds(Assets)", "", 1, "Receivable", "Asset"],
+ ["Stock Expenses", "Expenses", "", 0, "Stock Adjustment", "Expense"],
+ ["Sample Bank", "Bank Accounts", "", 0, "Bank", "Asset"],
+ ["Cash", "Cash In Hand", "", 0, "Cash", "Asset"],
+ ["Stores", "Stock Assets", "", 0, "Stock", "Asset"],
+ ]
+
+ for row in template:
+ writer.writerow(row)
+
+ return writer
+
@frappe.whitelist()
def validate_accounts(file_name):
- accounts = generate_data_from_csv(file_name, as_dict=True)
+
+ file_doc, extension = get_file(file_name)
+
+ if extension == 'csv':
+ accounts = generate_data_from_csv(file_doc, as_dict=True)
+ else:
+ accounts = generate_data_from_excel(file_doc, extension, as_dict=True)
accounts_dict = {}
for account in accounts:
@@ -174,12 +300,38 @@
for account in roots:
if not account.get("root_type") and account.get("account_name"):
error_messages.append("Please enter Root Type for account- {0}".format(account.get("account_name")))
- elif account.get("root_type") not in ("Asset", "Liability", "Expense", "Income", "Equity") and account.get("account_name"):
+ 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")))
if error_messages:
return "<br>".join(error_messages)
+def get_root_types():
+ return ('Asset', 'Liability', 'Expense', 'Income', 'Equity')
+
+def get_report_type(root_type):
+ if root_type in ('Asset', 'Liability', 'Equity'):
+ return 'Balance Sheet'
+ else:
+ return 'Profit and Loss'
+
+def get_mandatory_group_accounts():
+ return ('Bank', 'Cash', 'Stock')
+
+def get_mandatory_account_types():
+ return [
+ {'account_type': 'Cost of Goods Sold', 'root_type': 'Expense'},
+ {'account_type': 'Depreciation', 'root_type': 'Expense'},
+ {'account_type': 'Fixed Asset', 'root_type': 'Asset'},
+ {'account_type': 'Payable', 'root_type': 'Liability'},
+ {'account_type': 'Receivable', 'root_type': 'Asset'},
+ {'account_type': 'Stock Adjustment', 'root_type': 'Expense'},
+ {'account_type': 'Bank', 'root_type': 'Asset'},
+ {'account_type': 'Cash', 'root_type': 'Asset'},
+ {'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]
diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py
index 4491f7a..2cbd40b 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry.py
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py
@@ -457,8 +457,7 @@
for d in self.get('accounts'):
if d.party_type in ['Customer', 'Supplier'] and d.party:
if not pay_to_recd_from:
- pay_to_recd_from = frappe.db.get_value(d.party_type, d.party,
- "customer_name" if d.party_type=="Customer" else "supplier_name")
+ pay_to_recd_from = d.party
if pay_to_recd_from and pay_to_recd_from == d.party:
party_amount += (d.debit_in_account_currency or d.credit_in_account_currency)
@@ -469,7 +468,8 @@
bank_account_currency = d.account_currency
if pay_to_recd_from:
- self.pay_to_recd_from = pay_to_recd_from
+ self.pay_to_recd_from = frappe.db.get_value(d.party_type, pay_to_recd_from,
+ "customer_name" if d.party_type=="Customer" else "supplier_name")
if bank_amount:
total_amount = bank_amount
currency = bank_account_currency
diff --git a/erpnext/accounts/doctype/payment_entry/test_payment_entry.py b/erpnext/accounts/doctype/payment_entry/test_payment_entry.py
index a7ab175..5303743 100644
--- a/erpnext/accounts/doctype/payment_entry/test_payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/test_payment_entry.py
@@ -149,6 +149,49 @@
outstanding_amount = flt(frappe.db.get_value("Sales Invoice", pi.name, "outstanding_amount"))
self.assertEqual(outstanding_amount, 0)
+
+ def test_payment_against_sales_invoice_to_check_status(self):
+ si = create_sales_invoice(customer="_Test Customer USD", debit_to="_Test Receivable USD - _TC",
+ currency="USD", conversion_rate=50)
+
+ pe = get_payment_entry("Sales Invoice", si.name, bank_account="_Test Bank USD - _TC")
+ pe.reference_no = "1"
+ pe.reference_date = "2016-01-01"
+ pe.target_exchange_rate = 50
+ pe.insert()
+ pe.submit()
+
+ outstanding_amount = flt(frappe.db.get_value("Sales Invoice", si.name, "outstanding_amount"))
+ self.assertEqual(outstanding_amount, 0)
+ self.assertEqual(si.status, 'Paid')
+
+ pe.cancel()
+
+ outstanding_amount = flt(frappe.db.get_value("Sales Invoice", si.name, "outstanding_amount"))
+ self.assertEqual(outstanding_amount, 100)
+ self.assertEqual(si.status, 'Unpaid')
+
+ def test_payment_against_purchase_invoice_to_check_status(self):
+ pi = make_purchase_invoice(supplier="_Test Supplier USD", debit_to="_Test Payable USD - _TC",
+ currency="USD", conversion_rate=50)
+
+ pe = get_payment_entry("Purchase Invoice", pi.name, bank_account="_Test Bank USD - _TC")
+ pe.reference_no = "1"
+ pe.reference_date = "2016-01-01"
+ pe.source_exchange_rate = 50
+ pe.insert()
+ pe.submit()
+
+ outstanding_amount = flt(frappe.db.get_value("Purchase Invoice", pi.name, "outstanding_amount"))
+ self.assertEqual(outstanding_amount, 0)
+ self.assertEqual(pi.status, 'Paid')
+
+ pe.cancel()
+
+ outstanding_amount = flt(frappe.db.get_value("Purchase Invoice", pi.name, "outstanding_amount"))
+ self.assertEqual(outstanding_amount, 100)
+ self.assertEqual(pi.status, 'Unpaid')
+
def test_payment_entry_against_ec(self):
payable = frappe.get_cached_value('Company', "_Test Company", 'default_payable_account')
@@ -566,4 +609,4 @@
self.assertEqual(expected_party_account_balance, party_account_balance)
accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
- accounts_settings.save()
+ accounts_settings.save()
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index 1ac6f50..cc992ce 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -136,15 +136,15 @@
args = [
self.name,
self.outstanding_amount,
- self.is_return,
- self.due_date,
+ self.is_return,
+ self.due_date,
self.docstatus,
precision
]
- status = get_status(args)
+ self.status = get_status(args)
if update:
- self.db_set('status', status, update_modified = update_modified)
+ self.db_set('status', self.status, update_modified = update_modified)
def set_missing_values(self, for_validate=False):
if not self.credit_to:
@@ -1053,7 +1053,7 @@
status = "Submitted"
else:
status = "Draft"
-
+
return status
def get_list_context(context=None):
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index 6eb307c..7f7938d 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -1228,16 +1228,16 @@
args = [
self.name,
self.outstanding_amount,
- self.is_discounted,
- self.is_return,
- self.due_date,
+ self.is_discounted,
+ self.is_return,
+ self.due_date,
self.docstatus,
precision,
]
- status = get_status(args)
+ self.status = get_status(args)
if update:
- self.db_set('status', status, update_modified = update_modified)
+ self.db_set('status', self.status, update_modified = update_modified)
def get_discounting_status(sales_invoice):
status = None
@@ -1261,7 +1261,7 @@
def get_status(*args):
sales_invoice, outstanding_amount, is_discounted, is_return, due_date, docstatus, precision = args[0]
-
+
discounting_status = None
if is_discounted:
discounting_status = get_discounting_status(sales_invoice)
@@ -1292,7 +1292,7 @@
status = "Submitted"
else:
status = "Draft"
-
+
return status
def validate_inter_company_party(doctype, party, company, inter_company_reference):
@@ -1465,7 +1465,7 @@
"party": party,
"company": company
}
-
+
def get_internal_party(parties, link_doctype, doc):
if len(parties) == 1:
party = parties[0].name
diff --git a/erpnext/accounts/report/accounts_payable/accounts_payable.js b/erpnext/accounts/report/accounts_payable/accounts_payable.js
index df700ec..4e09f99 100644
--- a/erpnext/accounts/report/accounts_payable/accounts_payable.js
+++ b/erpnext/accounts/report/accounts_payable/accounts_payable.js
@@ -12,17 +12,17 @@
"default": frappe.defaults.get_user_default("Company")
},
{
+ "fieldname":"report_date",
+ "label": __("Posting Date"),
+ "fieldtype": "Date",
+ "default": frappe.datetime.get_today()
+ },
+ {
"fieldname":"ageing_based_on",
"label": __("Ageing Based On"),
"fieldtype": "Select",
"options": 'Posting Date\nDue Date\nSupplier Invoice Date',
- "default": "Posting Date"
- },
- {
- "fieldname":"report_date",
- "label": __("As on Date"),
- "fieldtype": "Date",
- "default": frappe.datetime.get_today()
+ "default": "Due Date"
},
{
"fieldname":"range1",
diff --git a/erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js b/erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js
index 4a9f1b0..d5f18b0 100644
--- a/erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js
+++ b/erpnext/accounts/report/accounts_payable_summary/accounts_payable_summary.js
@@ -11,17 +11,17 @@
"default": frappe.defaults.get_user_default("Company")
},
{
+ "fieldname":"report_date",
+ "label": __("Posting Date"),
+ "fieldtype": "Date",
+ "default": frappe.datetime.get_today()
+ },
+ {
"fieldname":"ageing_based_on",
"label": __("Ageing Based On"),
"fieldtype": "Select",
"options": 'Posting Date\nDue Date',
- "default": "Posting Date"
- },
- {
- "fieldname":"report_date",
- "label": __("Date"),
- "fieldtype": "Date",
- "default": frappe.datetime.get_today()
+ "default": "Due Date"
},
{
"fieldname":"range1",
diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.js b/erpnext/accounts/report/accounts_receivable/accounts_receivable.js
index 5d0154f..6208eb6 100644
--- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.js
+++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.js
@@ -12,17 +12,17 @@
"default": frappe.defaults.get_user_default("Company")
},
{
+ "fieldname":"report_date",
+ "label": __("Posting Date"),
+ "fieldtype": "Date",
+ "default": frappe.datetime.get_today()
+ },
+ {
"fieldname":"ageing_based_on",
"label": __("Ageing Based On"),
"fieldtype": "Select",
"options": 'Posting Date\nDue Date',
- "default": "Posting Date"
- },
- {
- "fieldname":"report_date",
- "label": __("As on Date"),
- "fieldtype": "Date",
- "default": frappe.datetime.get_today()
+ "default": "Due Date"
},
{
"fieldname":"range1",
@@ -148,7 +148,7 @@
},
{
"fieldname":"show_delivery_notes",
- "label": __("Show Delivery Notes"),
+ "label": __("Show Linked Delivery Notes"),
"fieldtype": "Check",
},
{
diff --git a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js
index d54824b..b316f10 100644
--- a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js
+++ b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.js
@@ -11,17 +11,17 @@
"default": frappe.defaults.get_user_default("Company")
},
{
+ "fieldname":"report_date",
+ "label": __("Posting Date"),
+ "fieldtype": "Date",
+ "default": frappe.datetime.get_today()
+ },
+ {
"fieldname":"ageing_based_on",
"label": __("Ageing Based On"),
"fieldtype": "Select",
"options": 'Posting Date\nDue Date',
- "default": "Posting Date"
- },
- {
- "fieldname":"report_date",
- "label": __("Date"),
- "fieldtype": "Date",
- "default": frappe.datetime.get_today()
+ "default": "Due Date"
},
{
"fieldname":"range1",
diff --git a/erpnext/hr/doctype/employee_tax_exemption_proof_submission/employee_tax_exemption_proof_submission.json b/erpnext/hr/doctype/employee_tax_exemption_proof_submission/employee_tax_exemption_proof_submission.json
index 9792bd1..c170c16 100644
--- a/erpnext/hr/doctype/employee_tax_exemption_proof_submission/employee_tax_exemption_proof_submission.json
+++ b/erpnext/hr/doctype/employee_tax_exemption_proof_submission/employee_tax_exemption_proof_submission.json
@@ -1,720 +1,215 @@
{
- "allow_copy": 0,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
- "allow_import": 1,
- "allow_rename": 1,
- "autoname": "HR-TAX-PRF-.YYYY.-.#####",
- "beta": 0,
- "creation": "2018-04-13 17:24:11.456132",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
+ "actions": [],
+ "allow_import": 1,
+ "allow_rename": 1,
+ "autoname": "HR-TAX-PRF-.YYYY.-.#####",
+ "creation": "2018-04-13 17:24:11.456132",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "employee",
+ "employee_name",
+ "department",
+ "column_break_2",
+ "submission_date",
+ "payroll_period",
+ "company",
+ "section_break_5",
+ "tax_exemption_proofs",
+ "section_break_10",
+ "total_actual_amount",
+ "column_break_12",
+ "exemption_amount",
+ "other_incomes_section",
+ "income_from_other_sources",
+ "attachment_section",
+ "attachments",
+ "amended_from"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "employee",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Employee",
- "length": 0,
- "no_copy": 0,
- "options": "Employee",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "employee",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "in_standard_filter": 1,
+ "label": "Employee",
+ "options": "Employee",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_from": "employee.employee_name",
- "fetch_if_empty": 0,
- "fieldname": "employee_name",
- "fieldtype": "Data",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Employee Name",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fetch_from": "employee.employee_name",
+ "fieldname": "employee_name",
+ "fieldtype": "Data",
+ "label": "Employee Name",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_from": "employee.department",
- "fetch_if_empty": 0,
- "fieldname": "department",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Department",
- "length": 0,
- "no_copy": 0,
- "options": "Department",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fetch_from": "employee.department",
+ "fieldname": "department",
+ "fieldtype": "Link",
+ "label": "Department",
+ "options": "Department",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "column_break_2",
- "fieldtype": "Column Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "column_break_2",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "default": "Today",
- "fetch_if_empty": 0,
- "fieldname": "submission_date",
- "fieldtype": "Date",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Submission Date",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "default": "Today",
+ "fieldname": "submission_date",
+ "fieldtype": "Date",
+ "label": "Submission Date",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "payroll_period",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Payroll Period",
- "length": 0,
- "no_copy": 0,
- "options": "Payroll Period",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "payroll_period",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "in_standard_filter": 1,
+ "label": "Payroll Period",
+ "options": "Payroll Period",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_from": "employee.company",
- "fetch_if_empty": 0,
- "fieldname": "company",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Company",
- "length": 0,
- "no_copy": 0,
- "options": "Company",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fetch_from": "employee.company",
+ "fieldname": "company",
+ "fieldtype": "Link",
+ "label": "Company",
+ "options": "Company",
+ "read_only": 1,
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "section_break_5",
- "fieldtype": "Section Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "section_break_5",
+ "fieldtype": "Section Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "tax_exemption_proofs",
- "fieldtype": "Table",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Tax Exemption Proofs",
- "length": 0,
- "no_copy": 0,
- "options": "Employee Tax Exemption Proof Submission Detail",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "tax_exemption_proofs",
+ "fieldtype": "Table",
+ "label": "Tax Exemption Proofs",
+ "options": "Employee Tax Exemption Proof Submission Detail"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "section_break_10",
- "fieldtype": "Section Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "section_break_10",
+ "fieldtype": "Section Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "total_actual_amount",
- "fieldtype": "Currency",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Total Actual Amount",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "total_actual_amount",
+ "fieldtype": "Currency",
+ "label": "Total Actual Amount",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "column_break_12",
- "fieldtype": "Column Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "column_break_12",
+ "fieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "exemption_amount",
- "fieldtype": "Currency",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Total Exemption Amount",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "exemption_amount",
+ "fieldtype": "Currency",
+ "label": "Total Exemption Amount",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "other_incomes_section",
- "fieldtype": "Section Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Other Incomes",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "other_incomes_section",
+ "fieldtype": "Section Break",
+ "label": "Other Incomes"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "income_from_other_sources",
- "fieldtype": "Currency",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Income From Other Sources",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "income_from_other_sources",
+ "fieldtype": "Currency",
+ "label": "Income From Other Sources"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "attachment_section",
- "fieldtype": "Section Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "attachment_section",
+ "fieldtype": "Section Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "attachments",
- "fieldtype": "Attach",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Attachments",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "attachments",
+ "fieldtype": "Attach",
+ "label": "Attachments"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fetch_if_empty": 0,
- "fieldname": "amended_from",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Amended From",
- "length": 0,
- "no_copy": 1,
- "options": "Employee Tax Exemption Proof Submission",
- "permlevel": 0,
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "fieldname": "amended_from",
+ "fieldtype": "Link",
+ "label": "Amended From",
+ "no_copy": 1,
+ "options": "Employee Tax Exemption Proof Submission",
+ "print_hide": 1,
+ "read_only": 1
}
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 1,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2019-05-13 12:17:18.045171",
- "modified_by": "Administrator",
- "module": "HR",
- "name": "Employee Tax Exemption Proof Submission",
- "name_case": "",
- "owner": "Administrator",
+ ],
+ "is_submittable": 1,
+ "links": [],
+ "modified": "2020-03-02 19:02:15.398486",
+ "modified_by": "Administrator",
+ "module": "HR",
+ "name": "Employee Tax Exemption Proof Submission",
+ "owner": "Administrator",
"permissions": [
{
- "amend": 1,
- "cancel": 1,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "System Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 1,
+ "amend": 1,
+ "cancel": 1,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "System Manager",
+ "share": 1,
+ "submit": 1,
"write": 1
- },
+ },
{
- "amend": 1,
- "cancel": 1,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "HR Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 1,
+ "amend": 1,
+ "cancel": 1,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "HR Manager",
+ "share": 1,
+ "submit": 1,
"write": 1
- },
+ },
{
- "amend": 1,
- "cancel": 1,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "HR User",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 1,
+ "amend": 1,
+ "cancel": 1,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "HR User",
+ "share": 1,
+ "submit": 1,
"write": 1
- },
+ },
{
- "amend": 1,
- "cancel": 1,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Employee",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 1,
+ "amend": 1,
+ "cancel": 1,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "export": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Employee",
+ "share": 1,
+ "submit": 1,
"write": 1
}
- ],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0,
- "track_views": 0
+ ],
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/setup/doctype/sales_person/sales_person.js b/erpnext/setup/doctype/sales_person/sales_person.js
index 9ff37fa..89ca4a9 100644
--- a/erpnext/setup/doctype/sales_person/sales_person.js
+++ b/erpnext/setup/doctype/sales_person/sales_person.js
@@ -19,6 +19,11 @@
}
}
};
+
+ frm.make_methods = {
+ 'Sales Order': () => frappe.new_doc("Sales Order")
+ .then(() => frm.add_child("sales_team", {"sales_person": frm.doc.name}))
+ }
}
});