From 1435e30ad5856d30e410426ebfe308165f88424e Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Thu, 9 May 2019 14:16:49 +0530 Subject: [PATCH 01/32] fix: Show "Merge Account" button only to users with write access --- erpnext/accounts/doctype/account/account.js | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/erpnext/accounts/doctype/account/account.js b/erpnext/accounts/doctype/account/account.js index bb059f673cd..f7f1a5fb15a 100644 --- a/erpnext/accounts/doctype/account/account.js +++ b/erpnext/accounts/doctype/account/account.js @@ -42,15 +42,14 @@ frappe.ui.form.on('Account', { // show / hide convert buttons frm.trigger('add_toolbar_buttons'); } - frm.add_custom_button(__('Update Account Name / Number'), function () { - frm.trigger("update_account_number"); - }); - } - - if(!frm.doc.__islocal) { - frm.add_custom_button(__('Merge Account'), function () { - frm.trigger("merge_account"); - }); + if (frm.has_perm('write')) { + frm.add_custom_button(__('Update Account Name / Number'), function () { + frm.trigger("update_account_number"); + }); + frm.add_custom_button(__('Merge Account'), function () { + frm.trigger("merge_account"); + }); + } } }, account_type: function (frm) { From c7062d8be77bd2cdb417a5d083a1bcb1059174b6 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Thu, 9 May 2019 14:18:41 +0530 Subject: [PATCH 02/32] fix: Check permissions before renaming the account --- erpnext/accounts/doctype/account/account.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/account/account.py b/erpnext/accounts/doctype/account/account.py index ecf67dd1dbd..68efe377190 100644 --- a/erpnext/accounts/doctype/account/account.py +++ b/erpnext/accounts/doctype/account/account.py @@ -268,7 +268,7 @@ def update_account_number(name, account_name, account_number=None): new_name = get_account_autoname(account_number, account_name, account.company) if name != new_name: - frappe.rename_doc("Account", name, new_name, ignore_permissions=1) + frappe.rename_doc("Account", name, new_name, force=1) return new_name @frappe.whitelist() @@ -287,7 +287,7 @@ def merge_account(old, new, is_group, root_type, company): frappe.db.set_value("Account", new, "parent_account", frappe.db.get_value("Account", old, "parent_account")) - frappe.rename_doc("Account", old, new, merge=1, ignore_permissions=1) + frappe.rename_doc("Account", old, new, merge=1, force=1) return new From dac7ede911a0fdb837a0e87238522d01783a2b79 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Thu, 9 May 2019 19:50:00 +0530 Subject: [PATCH 03/32] fix: incorrect payment amount in the payment terms if the sales invoice has the advance amount --- erpnext/controllers/accounts_controller.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 6d767edbdcb..90dc0cd60bf 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -763,6 +763,9 @@ class AccountsController(TransactionBase): if self.doctype in ("Sales Invoice", "Purchase Invoice"): grand_total = grand_total - flt(self.write_off_amount) + if self.get("total_advance"): + grand_total -= self.get("total_advance") + if not self.get("payment_schedule"): if self.get("payment_terms_template"): data = get_payment_terms(self.payment_terms_template, posting_date, grand_total) @@ -808,6 +811,9 @@ class AccountsController(TransactionBase): total = flt(total, self.precision("grand_total")) grand_total = flt(self.get("rounded_total") or self.grand_total, self.precision('grand_total')) + if self.get("total_advance"): + grand_total -= self.get("total_advance") + if self.doctype in ("Sales Invoice", "Purchase Invoice"): grand_total = grand_total - flt(self.write_off_amount) if total != grand_total: From 1637f0aeafca743d42cb25765ae3d7e8a98de70b Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Fri, 10 May 2019 13:42:38 +0530 Subject: [PATCH 04/32] fix: test cases --- .../doctype/purchase_invoice/test_purchase_invoice.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py index dde12d79c7a..b4d584fbdef 100644 --- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py @@ -402,9 +402,9 @@ class TestPurchaseInvoice(unittest.TestCase): pi.save() pi.submit() - self.assertEqual(pi.payment_schedule[0].payment_amount, 756.15) + self.assertEqual(pi.payment_schedule[0].payment_amount, 606.15) self.assertEqual(pi.payment_schedule[0].due_date, pi.posting_date) - self.assertEqual(pi.payment_schedule[1].payment_amount, 756.15) + self.assertEqual(pi.payment_schedule[1].payment_amount, 606.15) self.assertEqual(pi.payment_schedule[1].due_date, add_days(pi.posting_date, 30)) pi.load_from_db() From 43f05d1de1ffa35a76c6e64a2e99eb90016ea58d Mon Sep 17 00:00:00 2001 From: Rohan Bansal Date: Fri, 10 May 2019 15:48:14 +0530 Subject: [PATCH 05/32] feat(crm): Allow leads to be imported without person name --- erpnext/crm/doctype/lead/lead.js | 52 +++++++++++++++--------------- erpnext/crm/doctype/lead/lead.json | 6 ++-- erpnext/crm/doctype/lead/lead.py | 8 +++-- 3 files changed, 35 insertions(+), 31 deletions(-) diff --git a/erpnext/crm/doctype/lead/lead.js b/erpnext/crm/doctype/lead/lead.js index 1af45504d42..8df7dab6f7d 100644 --- a/erpnext/crm/doctype/lead/lead.js +++ b/erpnext/crm/doctype/lead/lead.js @@ -5,79 +5,79 @@ frappe.provide("erpnext"); cur_frm.email_field = "email_id"; erpnext.LeadController = frappe.ui.form.Controller.extend({ - setup: function() { - this.frm.fields_dict.customer.get_query = function(doc, cdt, cdn) { - return { query: "erpnext.controllers.queries.customer_query" } } + setup: function () { + this.frm.fields_dict.customer.get_query = function (doc, cdt, cdn) { + return { query: "erpnext.controllers.queries.customer_query" } + } + + this.frm.toggle_reqd("lead_name", !this.frm.doc.organization_lead); }, - onload: function() { - - if(cur_frm.fields_dict.lead_owner.df.options.match(/^User/)) { - cur_frm.fields_dict.lead_owner.get_query = function(doc, cdt, cdn) { + onload: function () { + if (cur_frm.fields_dict.lead_owner.df.options.match(/^User/)) { + cur_frm.fields_dict.lead_owner.get_query = function (doc, cdt, cdn) { return { query: "frappe.core.doctype.user.user.user_query" } } } - if(cur_frm.fields_dict.contact_by.df.options.match(/^User/)) { - cur_frm.fields_dict.contact_by.get_query = function(doc, cdt, cdn) { - return { query: "frappe.core.doctype.user.user.user_query" } } + if (cur_frm.fields_dict.contact_by.df.options.match(/^User/)) { + cur_frm.fields_dict.contact_by.get_query = function (doc, cdt, cdn) { + return { query: "frappe.core.doctype.user.user.user_query" } + } } }, - refresh: function() { + refresh: function () { var doc = this.frm.doc; erpnext.toggle_naming_series(); - frappe.dynamic_link = {doc: doc, fieldname: 'name', doctype: 'Lead'} + frappe.dynamic_link = { doc: doc, fieldname: 'name', doctype: 'Lead' } - if(!doc.__islocal && doc.__onload && !doc.__onload.is_customer) { + if (!doc.__islocal && doc.__onload && !doc.__onload.is_customer) { this.frm.add_custom_button(__("Customer"), this.create_customer, __("Make")); this.frm.add_custom_button(__("Opportunity"), this.create_opportunity, __("Make")); this.frm.add_custom_button(__("Quotation"), this.make_quotation, __("Make")); } - if(!this.frm.doc.__islocal) { + if (!this.frm.doc.__islocal) { frappe.contacts.render_address_and_contact(cur_frm); } else { frappe.contacts.clear_address_and_contact(cur_frm); } }, - create_customer: function() { + create_customer: function () { frappe.model.open_mapped_doc({ method: "erpnext.crm.doctype.lead.lead.make_customer", frm: cur_frm }) }, - create_opportunity: function() { + create_opportunity: function () { frappe.model.open_mapped_doc({ method: "erpnext.crm.doctype.lead.lead.make_opportunity", frm: cur_frm }) }, - make_quotation: function() { + make_quotation: function () { frappe.model.open_mapped_doc({ method: "erpnext.crm.doctype.lead.lead.make_quotation", frm: cur_frm }) }, - organization_lead: function() { - if (this.frm.doc.organization_lead == 1) { - this.frm.set_df_property('company_name', 'reqd', 1); - } else { - this.frm.set_df_property('company_name', 'reqd', 0); - } + organization_lead: function () { + this.frm.toggle_reqd("lead_name", !this.frm.doc.organization_lead); + this.frm.toggle_reqd("company_name", this.frm.doc.organization_lead); }, - company_name: function() { + company_name: function () { if (this.frm.doc.organization_lead == 1) { this.frm.set_value("lead_name", this.frm.doc.company_name); } }, - contact_date: function() { + contact_date: function () { if (this.frm.doc.contact_date) { let d = moment(this.frm.doc.contact_date); d.add(1, "hours"); @@ -86,4 +86,4 @@ erpnext.LeadController = frappe.ui.form.Controller.extend({ } }); -$.extend(cur_frm.cscript, new erpnext.LeadController({frm: cur_frm})); +$.extend(cur_frm.cscript, new erpnext.LeadController({ frm: cur_frm })); diff --git a/erpnext/crm/doctype/lead/lead.json b/erpnext/crm/doctype/lead/lead.json index b0be2a9f485..f263eb35d50 100644 --- a/erpnext/crm/doctype/lead/lead.json +++ b/erpnext/crm/doctype/lead/lead.json @@ -141,7 +141,7 @@ "read_only": 0, "remember_last_selected_value": 0, "report_hide": 0, - "reqd": 1, + "reqd": 0, "search_index": 1, "set_only_once": 0, "translatable": 0, @@ -499,7 +499,7 @@ "ignore_xss_filter": 0, "in_filter": 0, "in_global_search": 0, - "in_list_view": 0, + "in_list_view": 1, "in_standard_filter": 0, "label": "Lead Owner", "length": 0, @@ -1389,7 +1389,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2018-10-02 09:12:23.415379", + "modified": "2019-05-10 03:22:57.283628", "modified_by": "Administrator", "module": "CRM", "name": "Lead", diff --git a/erpnext/crm/doctype/lead/lead.py b/erpnext/crm/doctype/lead/lead.py index d3d31b8e702..d99084c7910 100644 --- a/erpnext/crm/doctype/lead/lead.py +++ b/erpnext/crm/doctype/lead/lead.py @@ -109,7 +109,11 @@ class Lead(SellingController): def set_lead_name(self): if not self.lead_name: - frappe.db.set_value("Lead", self.name, "lead_name", self.company_name) + # Check for leads being created through data import + if not self.company_name: + frappe.throw(_("A Lead requires either a person's name or an organization's name")) + + self.lead_name = self.company_name @frappe.whitelist() def make_customer(source_name, target_doc=None): @@ -225,4 +229,4 @@ def make_lead_from_communication(communication, ignore_communication_links=False lead_name = lead.name link_communication_to_document(doc, "Lead", lead_name, ignore_communication_links) - return lead_name \ No newline at end of file + return lead_name From 6be1475882da803823b05fcca9550ba8d37faa8f Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Fri, 10 May 2019 17:19:50 +0530 Subject: [PATCH 06/32] fix: incorrect stock balance showing in the warehouse tree view --- erpnext/stock/doctype/warehouse/warehouse.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/stock/doctype/warehouse/warehouse.py b/erpnext/stock/doctype/warehouse/warehouse.py index da97bc61a90..cfa552cb539 100644 --- a/erpnext/stock/doctype/warehouse/warehouse.py +++ b/erpnext/stock/doctype/warehouse/warehouse.py @@ -3,7 +3,7 @@ from __future__ import unicode_literals import frappe, erpnext -from frappe.utils import cint +from frappe.utils import cint, nowdate from frappe import throw, _ from frappe.utils.nestedset import NestedSet from erpnext.stock import get_warehouse_account @@ -140,7 +140,7 @@ class Warehouse(NestedSet): @frappe.whitelist() def get_children(doctype, parent=None, company=None, is_root=False): - from erpnext.stock.utils import get_stock_value_from_bin + from erpnext.stock.utils import get_stock_value_on if is_root: parent = "" @@ -156,7 +156,7 @@ def get_children(doctype, parent=None, company=None, is_root=False): # return warehouses for wh in warehouses: - wh["balance"] = get_stock_value_from_bin(warehouse=wh.value) + wh["balance"] = get_stock_value_on(warehouse=wh.value, posting_date=nowdate()) if company: wh["company_currency"] = frappe.db.get_value('Company', company, 'default_currency') return warehouses From c5c4de885b97d137bf3337ff6b99ba82b79ae0f6 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Fri, 10 May 2019 19:08:41 +0530 Subject: [PATCH 07/32] fix: bank reconciliation not showing as Settled instead of Reconciled --- .../doctype/bank_transaction/bank_transaction.py | 4 ++++ .../bank_reconciliation/bank_reconciliation.py | 2 ++ erpnext/patches.txt | 3 ++- .../v11_1/update_bank_transaction_status.py | 15 +++++++++++++++ 4 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 erpnext/patches/v11_1/update_bank_transaction_status.py diff --git a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py index dcf6d44105c..f943b345810 100644 --- a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py +++ b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py @@ -36,6 +36,10 @@ class BankTransaction(StatusUpdater): frappe.db.set_value(self.doctype, self.name, "allocated_amount", 0) frappe.db.set_value(self.doctype, self.name, "unallocated_amount", abs(flt(self.credit) - flt(self.debit))) + amount = self.debit or self.credit + if amount == self.allocated_amount: + frappe.db.set_value(self.doctype, self.name, "status", "Reconciled") + self.reload() def clear_linked_payment_entries(self): diff --git a/erpnext/accounts/page/bank_reconciliation/bank_reconciliation.py b/erpnext/accounts/page/bank_reconciliation/bank_reconciliation.py index f25c809a672..e9093847644 100644 --- a/erpnext/accounts/page/bank_reconciliation/bank_reconciliation.py +++ b/erpnext/accounts/page/bank_reconciliation/bank_reconciliation.py @@ -39,7 +39,9 @@ def add_payment_to_transaction(transaction, payment_entry, gl_entry): "payment_entry": payment_entry.name, "allocated_amount": allocated_amount }) + transaction.save() + transaction.update_allocations() @frappe.whitelist() def get_linked_payments(bank_transaction): diff --git a/erpnext/patches.txt b/erpnext/patches.txt index c060264a937..c6c3ae38b92 100755 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -598,4 +598,5 @@ erpnext.patches.v11_1.set_salary_details_submittable erpnext.patches.v11_1.rename_depends_on_lwp erpnext.patches.v11_1.set_missing_title_for_quotation execute:frappe.delete_doc("Report", "Inactive Items") -erpnext.patches.v11_1.delete_scheduling_tool \ No newline at end of file +erpnext.patches.v11_1.delete_scheduling_tool +erpnext.patches.v11_1.update_bank_transaction_status \ No newline at end of file diff --git a/erpnext/patches/v11_1/update_bank_transaction_status.py b/erpnext/patches/v11_1/update_bank_transaction_status.py new file mode 100644 index 00000000000..1acdfcccf9f --- /dev/null +++ b/erpnext/patches/v11_1/update_bank_transaction_status.py @@ -0,0 +1,15 @@ +# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals +import frappe + +def execute(): + frappe.reload_doc("accounts", "doctype", "bank_transaction") + + frappe.db.sql(""" UPDATE `tabBank Transaction` + SET status = 'Reconciled' + WHERE + status = 'Settled' and (debit = allocated_amount or credit = allocated_amount) + and ifnull(allocated_amount, 0) > 0 + """) \ No newline at end of file From 80b696ce25134b60d86922a8ce8044e4a19f3635 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Sat, 11 May 2019 14:55:34 +0530 Subject: [PATCH 08/32] fix: wrong journal entries are showing in the reconcilliation section --- .../bank_transaction/bank_transaction.json | 4 +-- .../bank_reconciliation.py | 32 +++++++++++++++---- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/erpnext/accounts/doctype/bank_transaction/bank_transaction.json b/erpnext/accounts/doctype/bank_transaction/bank_transaction.json index b9cef288fb3..39937bb3645 100644 --- a/erpnext/accounts/doctype/bank_transaction/bank_transaction.json +++ b/erpnext/accounts/doctype/bank_transaction/bank_transaction.json @@ -121,7 +121,7 @@ "bold": 0, "collapsible": 0, "columns": 0, - "default": "Settled", + "default": "Pending", "fetch_if_empty": 0, "fieldname": "status", "fieldtype": "Select", @@ -755,7 +755,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2019-04-26 14:32:16.437813", + "modified": "2019-05-11 05:27:55.244721", "modified_by": "Administrator", "module": "Accounts", "name": "Bank Transaction", diff --git a/erpnext/accounts/page/bank_reconciliation/bank_reconciliation.py b/erpnext/accounts/page/bank_reconciliation/bank_reconciliation.py index e9093847644..bc642212793 100644 --- a/erpnext/accounts/page/bank_reconciliation/bank_reconciliation.py +++ b/erpnext/accounts/page/bank_reconciliation/bank_reconciliation.py @@ -58,7 +58,11 @@ def get_linked_payments(bank_transaction): return check_amount_vs_description(amount_matching, description_matching) elif description_matching: - return sorted(description_matching, key = lambda x: x["posting_date"], reverse=True) + description_matching = filter(lambda x: not x.get('clearance_date'), description_matching) + if not description_matching: + return [] + + return sorted(list(description_matching), key = lambda x: x["posting_date"], reverse=True) else: return [] @@ -99,7 +103,8 @@ def check_matching_amount(bank_account, company, transaction): journal_entries = frappe.db.sql(""" SELECT 'Journal Entry' as doctype, je.name, je.posting_date, je.cheque_no as reference_no, - je.pay_to_recd_from as party, je.cheque_date as reference_date, jea.credit_in_account_currency as paid_amount + jea.account_currency as currency, je.pay_to_recd_from as party, je.cheque_date as reference_date, + jea.credit_in_account_currency as paid_amount FROM `tabJournal Entry Account` as jea JOIN @@ -109,12 +114,17 @@ def check_matching_amount(bank_account, company, transaction): WHERE (je.clearance_date is null or je.clearance_date='0000-00-00') AND - jea.account = %s + jea.account = %(bank_account)s AND - jea.credit_in_account_currency like %s + jea.credit_in_account_currency like %(txt)s AND je.docstatus = 1 - """, (bank_account, amount), as_dict=True) + """, { + 'bank_account': bank_account, + 'txt': '%%%s%%' % amount + }, as_dict=True, debug=1) + + frappe.errprint(journal_entries) if transaction.credit > 0: sales_invoices = frappe.db.sql(""" @@ -215,9 +225,14 @@ def get_matching_descriptions_data(company, transaction): company_currency = get_company_currency(company) for key, value in iteritems(links): if key == "Payment Entry": - data.extend(frappe.get_all("Payment Entry", filters=[["name", "in", value]], fields=["'Payment Entry' as doctype", "posting_date", "party", "reference_no", "reference_date", "paid_amount", "paid_to_account_currency as currency"])) + data.extend(frappe.get_all("Payment Entry", filters=[["name", "in", value]], + fields=["'Payment Entry' as doctype", "posting_date", "party", "reference_no", + "reference_date", "paid_amount", "paid_to_account_currency as currency", "clearance_date"])) if key == "Journal Entry": - journal_entries = frappe.get_all("Journal Entry", filters=[["name", "in", value]], fields=["name", "'Journal Entry' as doctype", "posting_date", "pay_to_recd_from as party", "cheque_no as reference_no", "cheque_date as reference_date", "total_credit as paid_amount"]) + journal_entries = frappe.get_all("Journal Entry", filters=[["name", "in", value]], + fields=["name", "'Journal Entry' as doctype", "posting_date", + "pay_to_recd_from as party", "cheque_no as reference_no", "cheque_date as reference_date", + "total_credit as paid_amount", "clearance_date"]) for journal_entry in journal_entries: journal_entry_accounts = frappe.get_all("Journal Entry Account", filters={"parenttype": journal_entry["doctype"], "parent": journal_entry["name"]}, fields=["account_currency"]) journal_entry["currency"] = journal_entry_accounts[0]["account_currency"] if journal_entry_accounts else company_currency @@ -238,6 +253,9 @@ def check_amount_vs_description(amount_matching, description_matching): if description_matching: for am_match in amount_matching: for des_match in description_matching: + if des_match.get("clearance_date"): + continue + if am_match["party"] == des_match["party"]: if am_match not in result: result.append(am_match) From 569815b5ad1a51abe21dd71ea25c887f1e780dc3 Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Sat, 11 May 2019 20:09:29 +0530 Subject: [PATCH 09/32] fix: Standard filter and dashboard fixes in quotation and opportunity --- erpnext/crm/doctype/lead/lead_dashboard.py | 4 ++-- erpnext/crm/doctype/opportunity/opportunity.json | 4 ++-- erpnext/crm/doctype/opportunity/opportunity_list.js | 8 ++++++++ .../selling/doctype/customer/customer_dashboard.py | 4 ++-- erpnext/selling/doctype/quotation/quotation.json | 6 +++--- erpnext/selling/doctype/quotation/quotation_list.js | 11 +++++++++++ 6 files changed, 28 insertions(+), 9 deletions(-) diff --git a/erpnext/crm/doctype/lead/lead_dashboard.py b/erpnext/crm/doctype/lead/lead_dashboard.py index d58527e00cd..b33f12f5089 100644 --- a/erpnext/crm/doctype/lead/lead_dashboard.py +++ b/erpnext/crm/doctype/lead/lead_dashboard.py @@ -5,8 +5,8 @@ def get_data(): return { 'fieldname': 'lead', 'non_standard_fieldnames': { - 'Quotation': 'party_name', - 'Opportunity': 'party_name' + 'Quotation': 'customer_name', + 'Opportunity': 'customer_name' }, 'transactions': [ { diff --git a/erpnext/crm/doctype/opportunity/opportunity.json b/erpnext/crm/doctype/opportunity/opportunity.json index e3f43f40fd3..dc0d0bb6c2d 100644 --- a/erpnext/crm/doctype/opportunity/opportunity.json +++ b/erpnext/crm/doctype/opportunity/opportunity.json @@ -136,7 +136,7 @@ "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 1, - "label": "Customer/Lead", + "label": "Party", "length": 0, "no_copy": 0, "oldfieldname": "customer", @@ -1468,7 +1468,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2019-04-25 18:55:43.874656", + "modified": "2019-05-11 19:22:33.533487", "modified_by": "Administrator", "module": "CRM", "name": "Opportunity", diff --git a/erpnext/crm/doctype/opportunity/opportunity_list.js b/erpnext/crm/doctype/opportunity/opportunity_list.js index 9712fb04c56..af53bf7fbf1 100644 --- a/erpnext/crm/doctype/opportunity/opportunity_list.js +++ b/erpnext/crm/doctype/opportunity/opportunity_list.js @@ -17,5 +17,13 @@ frappe.listview_settings['Opportunity'] = { listview.page.add_menu_item(__("Set as Closed"), function() { listview.call_for_selected_items(method, {"status": "Closed"}); }); + + listview.page.fields_dict.opportunity_from.get_query = function() { + return { + "filters": { + "name": ["in", ["Customer", "Lead"]], + } + }; + }; } }; diff --git a/erpnext/selling/doctype/customer/customer_dashboard.py b/erpnext/selling/doctype/customer/customer_dashboard.py index 6d6c86fbefd..67c69339ea9 100644 --- a/erpnext/selling/doctype/customer/customer_dashboard.py +++ b/erpnext/selling/doctype/customer/customer_dashboard.py @@ -7,8 +7,8 @@ def get_data(): 'heatmap_message': _('This is based on transactions against this Customer. See timeline below for details'), 'fieldname': 'customer', 'non_standard_fieldnames': { - 'Quotation': 'party_name', - 'Opportunity': 'party_name' + 'Quotation': 'customer_name', + 'Opportunity': 'customer_name' }, 'transactions': [ { diff --git a/erpnext/selling/doctype/quotation/quotation.json b/erpnext/selling/doctype/quotation/quotation.json index 4083b8e6d0b..33fc4dbeb04 100644 --- a/erpnext/selling/doctype/quotation/quotation.json +++ b/erpnext/selling/doctype/quotation/quotation.json @@ -133,7 +133,7 @@ "in_filter": 0, "in_global_search": 0, "in_list_view": 0, - "in_standard_filter": 0, + "in_standard_filter": 1, "label": "Quotation To", "length": 0, "no_copy": 0, @@ -169,7 +169,7 @@ "in_filter": 0, "in_global_search": 1, "in_list_view": 0, - "in_standard_filter": 0, + "in_standard_filter": 1, "label": "Party", "length": 0, "no_copy": 0, @@ -3224,7 +3224,7 @@ "istable": 0, "max_attachments": 1, "menu_index": 0, - "modified": "2019-05-07 14:29:22.565474", + "modified": "2019-05-11 19:26:50.735628", "modified_by": "Administrator", "module": "Selling", "name": "Quotation", diff --git a/erpnext/selling/doctype/quotation/quotation_list.js b/erpnext/selling/doctype/quotation/quotation_list.js index 8baf9b2518c..61a8bc1cab3 100644 --- a/erpnext/selling/doctype/quotation/quotation_list.js +++ b/erpnext/selling/doctype/quotation/quotation_list.js @@ -1,6 +1,17 @@ frappe.listview_settings['Quotation'] = { add_fields: ["customer_name", "base_grand_total", "status", "company", "currency", 'valid_till'], + + onload: function(listview) { + listview.page.fields_dict.quotation_to.get_query = function() { + return { + "filters": { + "name": ["in", ["Customer", "Lead"]], + } + }; + }; + }, + get_indicator: function(doc) { if(doc.status==="Submitted") { if (doc.valid_till && doc.valid_till < frappe.datetime.nowdate()) { From aca3772f7d2a5f0928f7bcca87da9995b11c917d Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Sat, 11 May 2019 21:12:51 +0530 Subject: [PATCH 10/32] fix: Show all territories and items in inactive sales item report --- .../inactive_sales_items.js | 6 +++ .../inactive_sales_items.py | 54 +++++++++++-------- 2 files changed, 37 insertions(+), 23 deletions(-) diff --git a/erpnext/accounts/report/inactive_sales_items/inactive_sales_items.js b/erpnext/accounts/report/inactive_sales_items/inactive_sales_items.js index ddf756263fc..a54a6c17fb7 100644 --- a/erpnext/accounts/report/inactive_sales_items/inactive_sales_items.js +++ b/erpnext/accounts/report/inactive_sales_items/inactive_sales_items.js @@ -4,6 +4,12 @@ frappe.query_reports["Inactive Sales Items"] = { "filters": [ + { + fieldname: "territory", + label: __("Territory"), + fieldtype: "Link", + options: "Territory" + }, { fieldname: "item", label: __("Item"), diff --git a/erpnext/accounts/report/inactive_sales_items/inactive_sales_items.py b/erpnext/accounts/report/inactive_sales_items/inactive_sales_items.py index fd169f8f70f..31e44711650 100644 --- a/erpnext/accounts/report/inactive_sales_items/inactive_sales_items.py +++ b/erpnext/accounts/report/inactive_sales_items/inactive_sales_items.py @@ -7,13 +7,11 @@ from frappe.utils import getdate, add_days, today, cint from frappe import _ def execute(filters=None): - columns = get_columns() data = get_data(filters) return columns, data def get_columns(): - columns = [ { "fieldname": "territory", @@ -74,36 +72,37 @@ def get_columns(): def get_data(filters): - data = [] items = get_items(filters) + territories = get_territories(filters) sales_invoice_data = get_sales_details(filters) - for item in items: - row = { - "item_group": item.item_group, - "item": item.name, - "item_name": item.item_name - } + for territory in territories: + for item in items: + row = { + "territory": territory.name, + "item_group": item.item_group, + "item": item.name, + "item_name": item.item_name + } - if sales_invoice_data.get(item.name): - item_obj = sales_invoice_data[item.name] - if item_obj.days_since_last_order > cint(filters['days']): - row.update({ - "territory": item_obj.territory, - "customer": item_obj.customer, - "last_order_date": item_obj.last_order_date, - "qty": item_obj.qty, - "days_since_last_order": item_obj.days_since_last_order - }) + if sales_invoice_data.get((territory.name,item.name)): + item_obj = sales_invoice_data[(territory.name,item.name)] + if item_obj.days_since_last_order > cint(filters['days']): + row.update({ + "territory": item_obj.territory, + "customer": item_obj.customer, + "last_order_date": item_obj.last_order_date, + "qty": item_obj.qty, + "days_since_last_order": item_obj.days_since_last_order + }) - data.append(row) + data.append(row) return data def get_sales_details(filters): - data = [] item_details_map = {} @@ -118,12 +117,21 @@ def get_sales_details(filters): .format(date_field = date_field, doctype = filters['based_on']), as_dict=1) for d in sales_data: - item_details_map.setdefault(d.item_name, d) + item_details_map.setdefault((d.territory,d.item_name), d) return item_details_map -def get_items(filters): +def get_territories(filters): + filter_dict = {} + if filters.get("territory"): + filter_dict.update({'name': filters['territory']}) + + territories = frappe.get_all("Territory", fields=["name"], filters=filter_dict) + + return territories + +def get_items(filters): filters_dict = { "disabled": 0, "is_stock_item": 1 From 0d1b022ea0690be1442d20c32a1e04b7d9d0bf6f Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Sat, 11 May 2019 23:30:52 +0530 Subject: [PATCH 11/32] feat(training-event): validate event period --- erpnext/hr/doctype/training_event/training_event.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/erpnext/hr/doctype/training_event/training_event.py b/erpnext/hr/doctype/training_event/training_event.py index 1b13b70f5bd..5064f033081 100644 --- a/erpnext/hr/doctype/training_event/training_event.py +++ b/erpnext/hr/doctype/training_event/training_event.py @@ -5,9 +5,19 @@ from __future__ import unicode_literals import frappe from frappe.model.document import Document +from frappe import _ +from frappe.utils import time_diff_in_seconds from erpnext.hr.doctype.employee.employee import get_employee_emails class TrainingEvent(Document): def validate(self): + self.set_employee_emails() + self.validate_period() + + def set_employee_emails(self): self.employee_emails = ', '.join(get_employee_emails([d.employee for d in self.employees])) + + def validate_period(self): + if time_diff_in_seconds(self.end_time, self.start_time) <= 0: + frappe.throw(_('End time cannot be before start time')) \ No newline at end of file From e23cfd22caea19a2ee75cd05ca73899dd7b4fe65 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Sun, 12 May 2019 16:20:31 +0530 Subject: [PATCH 12/32] fix(lead): Map lead name to quotation party_name --- erpnext/crm/doctype/lead/lead.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/crm/doctype/lead/lead.py b/erpnext/crm/doctype/lead/lead.py index d3d31b8e702..9e5139c178d 100644 --- a/erpnext/crm/doctype/lead/lead.py +++ b/erpnext/crm/doctype/lead/lead.py @@ -163,7 +163,7 @@ def make_quotation(source_name, target_doc=None): {"Lead": { "doctype": "Quotation", "field_map": { - "name": "lead" + "name": "party_name" } }}, target_doc) target_doc.quotation_to = "Lead" From e55dd7233d0feac3202c579e49448fdec97c5df7 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Sun, 12 May 2019 17:01:51 +0530 Subject: [PATCH 13/32] feat: delayed order summary report --- .../delayed_order_item_summary/__init__.py | 0 .../delayed_order_item_summary.js | 62 +++++++ .../delayed_order_item_summary.json | 37 ++++ .../delayed_order_item_summary.py | 168 ++++++++++++++++++ .../report/delayed_order_summary/__init__.py | 0 .../delayed_order_summary.js | 62 +++++++ .../delayed_order_summary.json | 37 ++++ .../delayed_order_summary.py | 83 +++++++++ 8 files changed, 449 insertions(+) create mode 100644 erpnext/stock/report/delayed_order_item_summary/__init__.py create mode 100644 erpnext/stock/report/delayed_order_item_summary/delayed_order_item_summary.js create mode 100644 erpnext/stock/report/delayed_order_item_summary/delayed_order_item_summary.json create mode 100644 erpnext/stock/report/delayed_order_item_summary/delayed_order_item_summary.py create mode 100644 erpnext/stock/report/delayed_order_summary/__init__.py create mode 100644 erpnext/stock/report/delayed_order_summary/delayed_order_summary.js create mode 100644 erpnext/stock/report/delayed_order_summary/delayed_order_summary.json create mode 100644 erpnext/stock/report/delayed_order_summary/delayed_order_summary.py diff --git a/erpnext/stock/report/delayed_order_item_summary/__init__.py b/erpnext/stock/report/delayed_order_item_summary/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/erpnext/stock/report/delayed_order_item_summary/delayed_order_item_summary.js b/erpnext/stock/report/delayed_order_item_summary/delayed_order_item_summary.js new file mode 100644 index 00000000000..41322544ede --- /dev/null +++ b/erpnext/stock/report/delayed_order_item_summary/delayed_order_item_summary.js @@ -0,0 +1,62 @@ +// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt +/* eslint-disable */ + +frappe.query_reports["Delayed Order Item Summary"] = { + "filters": [ + { + fieldname: "company", + label: __("Company"), + fieldtype: "Link", + options: "Company", + default: frappe.defaults.get_default("company"), + reqd: 1 + }, + { + fieldname:"from_date", + label: __("From Date"), + fieldtype: "Date", + default: frappe.datetime.month_start(), + reqd: 1 + }, + { + fieldname:"to_date", + label: __("To Date"), + fieldtype: "Date", + default: frappe.datetime.now_date(), + reqd: 1 + }, + { + fieldname:"sales_order", + label: __("Sales Order"), + fieldtype: "Link", + options: "Sales Order", + }, + { + fieldname:"customer", + label: __("Customer"), + fieldtype: "Link", + options: "Customer", + }, + { + fieldname:"customer_group", + label: __("Customer Group"), + fieldtype: "Link", + options: "Customer Group", + }, + { + fieldname:"item_group", + label: __("Item Group"), + fieldtype: "Link", + options: "Item Group", + }, + { + fieldname:"based_on", + label: __("Based On"), + fieldtype: "Select", + options: ["Delivery Note", "Sales Invoice"], + default: "Sales Invoice", + reqd: 1 + }, + ] +} diff --git a/erpnext/stock/report/delayed_order_item_summary/delayed_order_item_summary.json b/erpnext/stock/report/delayed_order_item_summary/delayed_order_item_summary.json new file mode 100644 index 00000000000..760be6f8bc6 --- /dev/null +++ b/erpnext/stock/report/delayed_order_item_summary/delayed_order_item_summary.json @@ -0,0 +1,37 @@ +{ + "add_total_row": 0, + "creation": "2019-05-12 13:05:39.162734", + "disable_prepared_report": 0, + "disabled": 0, + "docstatus": 0, + "doctype": "Report", + "idx": 0, + "is_standard": "Yes", + "letter_head": "Gadgets International", + "modified": "2019-05-12 13:05:39.162734", + "modified_by": "Administrator", + "module": "Stock", + "name": "Delayed Order Item Summary", + "owner": "Administrator", + "prepared_report": 0, + "ref_doctype": "Delivery Note", + "report_name": "Delayed Order Item Summary", + "report_type": "Script Report", + "roles": [ + { + "role": "Stock User" + }, + { + "role": "Sales Manager" + }, + { + "role": "Maintenance User" + }, + { + "role": "Accounts User" + }, + { + "role": "Sales User" + } + ] +} \ No newline at end of file diff --git a/erpnext/stock/report/delayed_order_item_summary/delayed_order_item_summary.py b/erpnext/stock/report/delayed_order_item_summary/delayed_order_item_summary.py new file mode 100644 index 00000000000..cc08d45429d --- /dev/null +++ b/erpnext/stock/report/delayed_order_item_summary/delayed_order_item_summary.py @@ -0,0 +1,168 @@ +# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +from __future__ import unicode_literals +import frappe +from frappe import _ +from frappe.utils import date_diff + +def execute(filters=None, consolidated = False): + data, columns = DelayedOrderItemSummary(filters).run() + + return data, columns + +class DelayedOrderItemSummary(object): + def __init__(self, filters=None): + self.filters = frappe._dict(filters or {}) + + def run(self): + return self.get_columns(), self.get_data() or [] + + def get_data(self, consolidated=False): + conditions = "" + + doctype = self.filters.get("based_on") + child_doc= "%s Item" % doctype + + if doctype == "Sales Invoice": + conditions = " and `tabSales Invoice`.update_stock = 1 and `tabSales Invoice`.is_pos = 0" + + if self.filters.get("item_group"): + conditions += " and `tab%s`.item_group = '%s'" % (child_doc, + frappe.db.escape(self.filters.get("item_group"))) + + for field in ["customer", "customer_group", "company"]: + if self.filters.get(field): + conditions += " and `tab%s`.%s = '%s'" % (doctype, + field, frappe.db.escape(self.filters.get(field))) + + sales_order_field = "against_sales_order" + if doctype == "Sales Invoice": + sales_order_field = "sales_order" + + if self.filters.get("sales_order"): + conditions = " and `tab%s`.%s = '%s'" %(child_doc, sales_order_field, self.filters.get("sales_order")) + + self.transactions = frappe.db.sql(""" SELECT `tab{child_doc}`.item_code, `tab{child_doc}`.item_name, + `tab{child_doc}`.item_group, `tab{child_doc}`.qty, `tab{child_doc}`.rate, `tab{child_doc}`.amount, + `tab{child_doc}`.so_detail, `tab{child_doc}`.{so_field} as sales_order, + `tab{doctype}`.customer, `tab{doctype}`.posting_date, `tab{doctype}`.name, `tab{doctype}`.grand_total + FROM `tab{child_doc}`, `tab{doctype}` + WHERE + `tab{child_doc}`.parent = `tab{doctype}`.name and `tab{doctype}`.docstatus = 1 and + `tab{doctype}`.posting_date between %(from_date)s and %(to_date)s and + `tab{child_doc}`.{so_field} is not null and `tab{child_doc}`.{so_field} != '' {cond} + """.format(cond=conditions, doctype=doctype, child_doc=child_doc, so_field=sales_order_field), { + 'from_date': self.filters.get('from_date'), + 'to_date': self.filters.get('to_date') + }, as_dict=1) + + if self.transactions: + self.filter_transactions_data(consolidated) + + return self.transactions + + def filter_transactions_data(self, consolidated=False): + sales_orders = [d.sales_order for d in self.transactions] + doctype = "Sales Order" + filters = {'name': ('in', sales_orders)} + + if not consolidated: + sales_order_items = [d.so_detail for d in self.transactions] + doctype = "Sales Order Item" + filters = {'parent': ('in', sales_orders), 'name': ('in', sales_order_items)} + + so_data = {} + for d in frappe.get_all(doctype, filters = filters, + fields = ["delivery_date", "parent", "name"]): + key = d.name if consolidated else (d.parent, d.name) + if key not in so_data: + so_data.setdefault(key, d.delivery_date) + + for row in self.transactions: + key = row.sales_order if consolidated else (row.sales_order, row.so_detail) + row.update({ + 'delivery_date': so_data.get(key), + 'delay_days': date_diff(row.posting_date, so_data.get(key)) + }) + + return self.transactions + + def get_columns(self): + based_on = self.filters.get("based_on") + + return [{ + "label": _(based_on), + "fieldname": "name", + "fieldtype": "Link", + "options": based_on, + "width": 100 + },{ + "label": _("Customer"), + "fieldname": "customer", + "fieldtype": "Link", + "options": "Customer", + "width": 100 + }, + { + "label": _("Expected Delivery Date"), + "fieldname": "delivery_date", + "fieldtype": "Date", + "width": 100 + }, + { + "label": _("Actual Delivery Date"), + "fieldname": "posting_date", + "fieldtype": "Date", + "width": 100 + }, + { + "label": _("Item Code"), + "fieldname": "item_code", + "fieldtype": "Link", + "options": "Item", + "width": 100 + }, + { + "label": _("Item Name"), + "fieldname": "item_name", + "fieldtype": "Data", + "width": 100 + }, + { + "label": _("Quantity"), + "fieldname": "qty", + "fieldtype": "Float", + "width": 100 + }, + { + "label": _("Rate"), + "fieldname": "rate", + "fieldtype": "Currency", + "width": 100 + }, + { + "label": _("Amount"), + "fieldname": "amount", + "fieldtype": "Currency", + "width": 100 + }, + { + "label": _("Delay Days"), + "fieldname": "delay_days", + "fieldtype": "Int", + "width": 100 + }, + { + "label": _("Sales Order"), + "fieldname": "sales_order", + "fieldtype": "Link", + "options": "Sales Order", + "width": 100 + }, + { + "label": _("Customer PO"), + "fieldname": "po_no", + "fieldtype": "Data", + "width": 100 + }] \ No newline at end of file diff --git a/erpnext/stock/report/delayed_order_summary/__init__.py b/erpnext/stock/report/delayed_order_summary/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/erpnext/stock/report/delayed_order_summary/delayed_order_summary.js b/erpnext/stock/report/delayed_order_summary/delayed_order_summary.js new file mode 100644 index 00000000000..a3e2d8eb7d6 --- /dev/null +++ b/erpnext/stock/report/delayed_order_summary/delayed_order_summary.js @@ -0,0 +1,62 @@ +// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt +/* eslint-disable */ + +frappe.query_reports["Delayed Order Summary"] = { + "filters": [ + { + fieldname: "company", + label: __("Company"), + fieldtype: "Link", + options: "Company", + default: frappe.defaults.get_default("company"), + reqd: 1 + }, + { + fieldname:"from_date", + label: __("From Date"), + fieldtype: "Date", + default: frappe.datetime.month_start(), + reqd: 1 + }, + { + fieldname:"to_date", + label: __("To Date"), + fieldtype: "Date", + default: frappe.datetime.now_date(), + reqd: 1 + }, + { + fieldname:"sales_order", + label: __("Sales Order"), + fieldtype: "Link", + options: "Sales Order", + }, + { + fieldname:"customer", + label: __("Customer"), + fieldtype: "Link", + options: "Customer", + }, + { + fieldname:"customer_group", + label: __("Customer Group"), + fieldtype: "Link", + options: "Customer Group", + }, + { + fieldname:"item_group", + label: __("Item Group"), + fieldtype: "Link", + options: "Item Group", + }, + { + fieldname:"based_on", + label: __("Based On"), + fieldtype: "Select", + options: ["Delivery Note", "Sales Invoice"], + default: "Sales Invoice", + reqd: 1 + }, + ] +} diff --git a/erpnext/stock/report/delayed_order_summary/delayed_order_summary.json b/erpnext/stock/report/delayed_order_summary/delayed_order_summary.json new file mode 100644 index 00000000000..0987a9c59ea --- /dev/null +++ b/erpnext/stock/report/delayed_order_summary/delayed_order_summary.json @@ -0,0 +1,37 @@ +{ + "add_total_row": 0, + "creation": "2019-05-12 12:38:44.907187", + "disable_prepared_report": 0, + "disabled": 0, + "docstatus": 0, + "doctype": "Report", + "idx": 0, + "is_standard": "Yes", + "letter_head": "Gadgets International", + "modified": "2019-05-12 12:39:16.378341", + "modified_by": "Administrator", + "module": "Stock", + "name": "Delayed Order Summary", + "owner": "Administrator", + "prepared_report": 0, + "ref_doctype": "Delivery Note", + "report_name": "Delayed Order Summary", + "report_type": "Script Report", + "roles": [ + { + "role": "Stock User" + }, + { + "role": "Sales Manager" + }, + { + "role": "Maintenance User" + }, + { + "role": "Accounts User" + }, + { + "role": "Sales User" + } + ] +} \ No newline at end of file diff --git a/erpnext/stock/report/delayed_order_summary/delayed_order_summary.py b/erpnext/stock/report/delayed_order_summary/delayed_order_summary.py new file mode 100644 index 00000000000..8827decde09 --- /dev/null +++ b/erpnext/stock/report/delayed_order_summary/delayed_order_summary.py @@ -0,0 +1,83 @@ +# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +from __future__ import unicode_literals +from frappe import _ +from erpnext.stock.report.delayed_order_item_summary.delayed_order_item_summary import DelayedOrderItemSummary + +def execute(filters=None): + columns, data = [], [] + + columns, data = DelayedOrderSummary(filters).run() + + return columns, data + +class DelayedOrderSummary(DelayedOrderItemSummary): + def run(self): + return self.get_columns(), self.get_data(consolidated=True) or [] + + def get_data(self, consolidated=False): + data = super(DelayedOrderSummary, self).get_data(consolidated) or [] + + so_list = [] + result = [] + for d in data: + if d.sales_order not in so_list: + so_list.append(d.sales_order) + result.append(d) + + return result + + def get_columns(self): + based_on = self.filters.get("based_on") + + return [{ + "label": _(based_on), + "fieldname": "name", + "fieldtype": "Link", + "options": based_on, + "width": 100 + },{ + "label": _("Customer"), + "fieldname": "customer", + "fieldtype": "Link", + "options": "Customer", + "width": 100 + }, + { + "label": _("Expected Delivery Date"), + "fieldname": "delivery_date", + "fieldtype": "Date", + "width": 100 + }, + { + "label": _("Actual Delivery Date"), + "fieldname": "posting_date", + "fieldtype": "Date", + "width": 100 + }, + { + "label": _("Amount"), + "fieldname": "grand_total", + "fieldtype": "Currency", + "width": 100 + }, + { + "label": _("Delay Days"), + "fieldname": "delay_days", + "fieldtype": "Int", + "width": 100 + }, + { + "label": _("Sales Order"), + "fieldname": "sales_order", + "fieldtype": "Link", + "options": "Sales Order", + "width": 100 + }, + { + "label": _("Customer PO"), + "fieldname": "po_no", + "fieldtype": "Data", + "width": 100 + }] \ No newline at end of file From 79b02db1566bfdcae45d5fb6ea8e45c08045cf97 Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Sun, 12 May 2019 18:27:52 +0530 Subject: [PATCH 14/32] fix: Indentation fixes --- .../report/inactive_sales_items/inactive_sales_items.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/report/inactive_sales_items/inactive_sales_items.py b/erpnext/accounts/report/inactive_sales_items/inactive_sales_items.py index 31e44711650..42761a58b95 100644 --- a/erpnext/accounts/report/inactive_sales_items/inactive_sales_items.py +++ b/erpnext/accounts/report/inactive_sales_items/inactive_sales_items.py @@ -80,10 +80,10 @@ def get_data(filters): for territory in territories: for item in items: row = { - "territory": territory.name, - "item_group": item.item_group, - "item": item.name, - "item_name": item.item_name + "territory": territory.name, + "item_group": item.item_group, + "item": item.name, + "item_name": item.item_name } if sales_invoice_data.get((territory.name,item.name)): From b32d96fc24bf9204ab03990e1109e1fac2ecfe93 Mon Sep 17 00:00:00 2001 From: Aditya Hase Date: Mon, 13 May 2019 10:21:41 +0530 Subject: [PATCH 15/32] fix(accounts): Add missing field (#17571) --- erpnext/setup/doctype/company/company.json | 5833 ++++++++++---------- 1 file changed, 2979 insertions(+), 2854 deletions(-) diff --git a/erpnext/setup/doctype/company/company.json b/erpnext/setup/doctype/company/company.json index d03cca050d2..7e5f80e858f 100644 --- a/erpnext/setup/doctype/company/company.json +++ b/erpnext/setup/doctype/company/company.json @@ -1,3153 +1,3278 @@ { - "allow_copy": 0, - "allow_events_in_timeline": 0, - "allow_guest_to_view": 0, - "allow_import": 1, - "allow_rename": 1, - "autoname": "field:company_name", - "beta": 0, - "creation": "2013-04-10 08:35:39", - "custom": 0, - "description": "Legal Entity / Subsidiary with a separate Chart of Accounts belonging to the Organization.", - "docstatus": 0, - "doctype": "DocType", - "document_type": "Setup", - "editable_grid": 0, - "engine": "InnoDB", + "allow_copy": 0, + "allow_events_in_timeline": 0, + "allow_guest_to_view": 0, + "allow_import": 1, + "allow_rename": 1, + "autoname": "field:company_name", + "beta": 0, + "creation": "2013-04-10 08:35:39", + "custom": 0, + "description": "Legal Entity / Subsidiary with a separate Chart of Accounts belonging to the Organization.", + "docstatus": 0, + "doctype": "DocType", + "document_type": "Setup", + "editable_grid": 0, + "engine": "InnoDB", "fields": [ { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "details", - "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, - "oldfieldtype": "Section Break", - "permlevel": 0, - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "details", + "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, + "oldfieldtype": "Section Break", + "permlevel": 0, + "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, - "fieldname": "company_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": "Company", - "length": 0, - "no_copy": 0, - "oldfieldname": "company_name", - "oldfieldtype": "Data", - "permlevel": 0, - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "company_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": "Company", + "length": 0, + "no_copy": 0, + "oldfieldname": "company_name", + "oldfieldtype": "Data", + "permlevel": 0, + "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": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "description": "", - "fieldname": "abbr", - "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": "Abbr", - "length": 0, - "no_copy": 0, - "oldfieldname": "abbr", - "oldfieldtype": "Data", - "permlevel": 0, - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "description": "", + "fetch_if_empty": 0, + "fieldname": "abbr", + "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": "Abbr", + "length": 0, + "no_copy": 0, + "oldfieldname": "abbr", + "oldfieldtype": "Data", + "permlevel": 0, + "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 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:!doc.__islocal && in_list(frappe.user_roles, \"System Manager\")", - "fieldname": "change_abbr", - "fieldtype": "Button", - "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": "Change Abbreviation", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "eval:!doc.__islocal && in_list(frappe.user_roles, \"System Manager\")", + "fetch_if_empty": 0, + "fieldname": "change_abbr", + "fieldtype": "Button", + "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": "Change Abbreviation", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "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": 1, - "collapsible": 0, - "columns": 0, - "fieldname": "is_group", - "fieldtype": "Check", - "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": "Is Group", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 1, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "is_group", + "fieldtype": "Check", + "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": "Is Group", + "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, - "fieldname": "default_finance_book", - "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": "Default Finance Book", - "length": 0, - "no_copy": 0, - "options": "Finance Book", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "default_finance_book", + "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": "Default Finance Book", + "length": 0, + "no_copy": 0, + "options": "Finance Book", + "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, - "fieldname": "cb0", - "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, - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "cb0", + "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, + "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, - "fieldname": "domain", - "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": "Domain", - "length": 0, - "no_copy": 0, - "options": "Domain", - "permlevel": 0, - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "domain", + "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": "Domain", + "length": 0, + "no_copy": 0, + "options": "Domain", + "permlevel": 0, + "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, - "fieldname": "parent_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": "Parent 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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "parent_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": "Parent 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 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "sb_about", - "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": "About the Company", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "sb_about", + "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": "About the Company", + "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, - "fieldname": "company_logo", - "fieldtype": "Attach Image", - "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 Logo", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "company_logo", + "fieldtype": "Attach Image", + "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 Logo", + "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, - "fieldname": "company_description", - "fieldtype": "Text Editor", - "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 Description", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "company_description", + "fieldtype": "Text Editor", + "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 Description", + "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, - "fieldname": "sales_settings", - "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": "Sales", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "sales_settings", + "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": "Sales", + "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, - "fieldname": "sales_monthly_history", - "fieldtype": "Small Text", - "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Sales Monthly History", - "length": 0, - "no_copy": 1, - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "sales_monthly_history", + "fieldtype": "Small Text", + "hidden": 1, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Sales Monthly History", + "length": 0, + "no_copy": 1, + "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 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "transactions_annual_history", - "fieldtype": "Code", - "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Transactions Annual History", - "length": 0, - "no_copy": 1, - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "transactions_annual_history", + "fieldtype": "Code", + "hidden": 1, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Transactions Annual History", + "length": 0, + "no_copy": 1, + "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 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "monthly_sales_target", - "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": "Monthly Sales Target", - "length": 0, - "no_copy": 0, - "options": "default_currency", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "monthly_sales_target", + "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": "Monthly Sales Target", + "length": 0, + "no_copy": 0, + "options": "default_currency", + "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, - "fieldname": "column_break_goals", - "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, + "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_goals", + "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 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "total_monthly_sales", - "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 Monthly Sales", - "length": 0, - "no_copy": 1, - "options": "default_currency", - "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, + "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_monthly_sales", + "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 Monthly Sales", + "length": 0, + "no_copy": 1, + "options": "default_currency", + "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 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "charts_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": "Default Values", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "charts_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": "Default Values", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "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, - "fieldname": "default_currency", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 1, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Default Currency", - "length": 0, - "no_copy": 0, - "options": "Currency", - "permlevel": 0, - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "default_currency", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 1, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Default Currency", + "length": 0, + "no_copy": 0, + "options": "Currency", + "permlevel": 0, + "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 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "default_letter_head", - "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": "Default Letter Head", - "length": 0, - "no_copy": 0, - "options": "Letter Head", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "default_letter_head", + "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": "Default Letter Head", + "length": 0, + "no_copy": 0, + "options": "Letter Head", + "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, - "fieldname": "default_holiday_list", - "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": "Default Holiday List", - "length": 0, - "no_copy": 0, - "options": "Holiday List", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "default_holiday_list", + "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": "Default Holiday List", + "length": 0, + "no_copy": 0, + "options": "Holiday List", + "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, - "fieldname": "standard_working_hours", - "fieldtype": "Float", - "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": "Standard Working Hours", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "standard_working_hours", + "fieldtype": "Float", + "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": "Standard Working Hours", + "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, - "fieldname": "default_terms", - "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": "Default Terms", - "length": 0, - "no_copy": 0, - "options": "Terms and Conditions", - "permlevel": 0, - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "default_terms", + "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": "Default Terms", + "length": 0, + "no_copy": 0, + "options": "Terms and Conditions", + "permlevel": 0, + "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, - "fieldname": "default_warehouse_for_sales_return", - "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": "Default warehouse for Sales Return", - "length": 0, - "no_copy": 0, - "options": "Warehouse", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "default_warehouse_for_sales_return", + "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": "Default warehouse for Sales Return", + "length": 0, + "no_copy": 0, + "options": "Warehouse", + "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, - "fieldname": "column_break_10", - "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, + "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_10", + "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 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "country", - "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": "Country", - "length": 0, - "no_copy": 0, - "options": "Country", - "permlevel": 0, - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "country", + "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": "Country", + "length": 0, + "no_copy": 0, + "options": "Country", + "permlevel": 0, + "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 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "create_chart_of_accounts_based_on", - "fieldtype": "Select", - "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": "Create Chart Of Accounts Based On", - "length": 0, - "no_copy": 0, - "options": "\nStandard Template\nExisting 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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "create_chart_of_accounts_based_on", + "fieldtype": "Select", + "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": "Create Chart Of Accounts Based On", + "length": 0, + "no_copy": 0, + "options": "\nStandard Template\nExisting 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 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:doc.create_chart_of_accounts_based_on===\"Standard Template\"", - "fieldname": "chart_of_accounts", - "fieldtype": "Select", - "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 Of Accounts Template", - "length": 0, - "no_copy": 1, - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "eval:doc.create_chart_of_accounts_based_on===\"Standard Template\"", + "fetch_if_empty": 0, + "fieldname": "chart_of_accounts", + "fieldtype": "Select", + "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 Of Accounts Template", + "length": 0, + "no_copy": 1, + "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 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:doc.create_chart_of_accounts_based_on===\"Existing Company\"", - "fieldname": "existing_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": "Existing Company ", - "length": 0, - "no_copy": 1, - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "eval:doc.create_chart_of_accounts_based_on===\"Existing Company\"", + "fetch_if_empty": 0, + "fieldname": "existing_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": "Existing Company ", + "length": 0, + "no_copy": 1, + "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 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "tax_id", - "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": "Tax ID", - "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, + "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_id", + "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": "Tax ID", + "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, - "fieldname": "date_of_establishment", - "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": "Date of Establishment", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "date_of_establishment", + "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": "Date of Establishment", + "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, - "fieldname": "default_settings", - "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": "Accounts Settings", - "length": 0, - "no_copy": 0, - "oldfieldtype": "Section Break", - "permlevel": 0, - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "default_settings", + "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": "Accounts Settings", + "length": 0, + "no_copy": 0, + "oldfieldtype": "Section Break", + "permlevel": 0, + "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": "eval:!doc.__islocal", - "fieldname": "default_bank_account", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 1, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Default Bank Account", - "length": 0, - "no_copy": 1, - "oldfieldname": "default_bank_account", - "oldfieldtype": "Link", - "options": "Account", - "permlevel": 0, - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "eval:!doc.__islocal", + "fetch_if_empty": 0, + "fieldname": "default_bank_account", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 1, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Default Bank Account", + "length": 0, + "no_copy": 1, + "oldfieldname": "default_bank_account", + "oldfieldtype": "Link", + "options": "Account", + "permlevel": 0, + "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": "eval:!doc.__islocal", - "fieldname": "default_cash_account", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 1, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Default Cash Account", - "length": 0, - "no_copy": 1, - "options": "Account", - "permlevel": 0, - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "eval:!doc.__islocal", + "fetch_if_empty": 0, + "fieldname": "default_cash_account", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 1, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Default Cash Account", + "length": 0, + "no_copy": 1, + "options": "Account", + "permlevel": 0, + "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": "eval:!doc.__islocal", - "fieldname": "default_receivable_account", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 1, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Default Receivable Account", - "length": 0, - "no_copy": 1, - "oldfieldname": "receivables_group", - "oldfieldtype": "Link", - "options": "Account", - "permlevel": 0, - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "eval:!doc.__islocal", + "fetch_if_empty": 0, + "fieldname": "default_receivable_account", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 1, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Default Receivable Account", + "length": 0, + "no_copy": 1, + "oldfieldname": "receivables_group", + "oldfieldtype": "Link", + "options": "Account", + "permlevel": 0, + "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, - "fieldname": "round_off_account", - "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": "Round Off Account", - "length": 0, - "no_copy": 0, - "options": "Account", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "round_off_account", + "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": "Round Off Account", + "length": 0, + "no_copy": 0, + "options": "Account", + "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, - "fieldname": "round_off_cost_center", - "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": "Round Off Cost Center", - "length": 0, - "no_copy": 0, - "options": "Cost Center", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "round_off_cost_center", + "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": "Round Off Cost Center", + "length": 0, + "no_copy": 0, + "options": "Cost Center", + "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, - "fieldname": "write_off_account", - "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": "Write Off Account", - "length": 0, - "no_copy": 0, - "options": "Account", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "write_off_account", + "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": "Write Off Account", + "length": 0, + "no_copy": 0, + "options": "Account", + "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, - "fieldname": "discount_allowed_account", - "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": "Discount Allowed Account", - "length": 0, - "no_copy": 0, - "options": "Account", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "discount_allowed_account", + "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": "Discount Allowed Account", + "length": 0, + "no_copy": 0, + "options": "Account", + "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, - "fieldname": "discount_received_account", - "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": "Discount Received Account", - "length": 0, - "no_copy": 0, - "options": "Account", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "discount_received_account", + "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": "Discount Received Account", + "length": 0, + "no_copy": 0, + "options": "Account", + "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, - "fieldname": "exchange_gain_loss_account", - "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": "Exchange Gain / Loss Account", - "length": 0, - "no_copy": 0, - "options": "Account", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "exchange_gain_loss_account", + "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": "Exchange Gain / Loss Account", + "length": 0, + "no_copy": 0, + "options": "Account", + "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, - "fieldname": "unrealized_exchange_gain_loss_account", - "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": "Unrealized Exchange Gain/Loss Account", - "length": 0, - "no_copy": 0, - "options": "Account", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "unrealized_exchange_gain_loss_account", + "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": "Unrealized Exchange Gain/Loss Account", + "length": 0, + "no_copy": 0, + "options": "Account", + "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, - "fieldname": "column_break0", - "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, - "oldfieldtype": "Column Break", - "permlevel": 0, - "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, + "fetch_if_empty": 0, + "fieldname": "column_break0", + "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, + "oldfieldtype": "Column Break", + "permlevel": 0, + "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, "width": "50%" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:!doc.__islocal", - "fieldname": "default_payable_account", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 1, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Default Payable Account", - "length": 0, - "no_copy": 1, - "oldfieldname": "payables_group", - "oldfieldtype": "Link", - "options": "Account", - "permlevel": 0, - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "eval:doc.parent_company", + "fetch_if_empty": 0, + "fieldname": "allow_account_creation_against_child_company", + "fieldtype": "Check", + "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": "Allow Account Creation Against Child Company", + "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, - "fieldname": "default_employee_advance_account", - "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": "Default Employee Advance Account", - "length": 0, - "no_copy": 1, - "options": "Account", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "eval:!doc.__islocal", + "fetch_if_empty": 0, + "fieldname": "default_payable_account", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 1, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Default Payable Account", + "length": 0, + "no_copy": 1, + "oldfieldname": "payables_group", + "oldfieldtype": "Link", + "options": "Account", + "permlevel": 0, + "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": "eval:!doc.__islocal", - "fieldname": "default_expense_account", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 1, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Default Cost of Goods Sold Account", - "length": 0, - "no_copy": 1, - "options": "Account", - "permlevel": 0, - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "default_employee_advance_account", + "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": "Default Employee Advance Account", + "length": 0, + "no_copy": 1, + "options": "Account", + "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": "eval:!doc.__islocal", - "fieldname": "default_income_account", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 1, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Default Income Account", - "length": 0, - "no_copy": 1, - "options": "Account", - "permlevel": 0, - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "eval:!doc.__islocal", + "fetch_if_empty": 0, + "fieldname": "default_expense_account", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 1, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Default Cost of Goods Sold Account", + "length": 0, + "no_copy": 1, + "options": "Account", + "permlevel": 0, + "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": "eval:!doc.__islocal", - "fieldname": "default_deferred_revenue_account", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 1, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Default Deferred Revenue Account", - "length": 0, - "no_copy": 1, - "options": "Account", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "eval:!doc.__islocal", + "fetch_if_empty": 0, + "fieldname": "default_income_account", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 1, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Default Income Account", + "length": 0, + "no_copy": 1, + "options": "Account", + "permlevel": 0, + "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": "eval:!doc.__islocal", - "fieldname": "default_deferred_expense_account", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 1, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Default Deferred Expense Account", - "length": 0, - "no_copy": 1, - "options": "Account", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "eval:!doc.__islocal", + "fetch_if_empty": 0, + "fieldname": "default_deferred_revenue_account", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 1, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Default Deferred Revenue Account", + "length": 0, + "no_copy": 1, + "options": "Account", + "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": "eval:!doc.__islocal", - "fieldname": "default_payroll_payable_account", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 1, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Default Payroll Payable Account", - "length": 0, - "no_copy": 1, - "options": "Account", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "eval:!doc.__islocal", + "fetch_if_empty": 0, + "fieldname": "default_deferred_expense_account", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 1, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Default Deferred Expense Account", + "length": 0, + "no_copy": 1, + "options": "Account", + "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": "eval:!doc.__islocal", - "fieldname": "default_expense_claim_payable_account", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 1, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Default Expense Claim Payable Account", - "length": 0, - "no_copy": 1, - "options": "Account", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "eval:!doc.__islocal", + "fetch_if_empty": 0, + "fieldname": "default_payroll_payable_account", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 1, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Default Payroll Payable Account", + "length": 0, + "no_copy": 1, + "options": "Account", + "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, - "fieldname": "section_break_22", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "eval:!doc.__islocal", + "fetch_if_empty": 0, + "fieldname": "default_expense_claim_payable_account", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 1, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Default Expense Claim Payable Account", + "length": 0, + "no_copy": 1, + "options": "Account", + "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": "eval:!doc.__islocal", - "fieldname": "cost_center", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 1, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Default Cost Center", - "length": 0, - "no_copy": 1, - "options": "Cost Center", - "permlevel": 0, - "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, + "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_22", + "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, - "fieldname": "column_break_26", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "eval:!doc.__islocal", + "fetch_if_empty": 0, + "fieldname": "cost_center", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 1, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Default Cost Center", + "length": 0, + "no_copy": 1, + "options": "Cost Center", + "permlevel": 0, + "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": "eval:!doc.__islocal", - "fieldname": "credit_limit", - "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": "Credit Limit", - "length": 0, - "no_copy": 0, - "oldfieldname": "credit_limit", - "oldfieldtype": "Currency", - "options": "default_currency", - "permlevel": 0, - "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, + "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_26", + "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 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "", - "fieldname": "payment_terms", - "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": "Default Payment Terms Template", - "length": 0, - "no_copy": 0, - "options": "Payment Terms Template", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "eval:!doc.__islocal", + "fetch_if_empty": 0, + "fieldname": "credit_limit", + "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": "Credit Limit", + "length": 0, + "no_copy": 0, + "oldfieldname": "credit_limit", + "oldfieldtype": "Currency", + "options": "default_currency", + "permlevel": 0, + "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": "eval:!doc.__islocal", - "fieldname": "auto_accounting_for_stock_settings", - "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": "Stock Settings", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "", + "fetch_if_empty": 0, + "fieldname": "payment_terms", + "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": "Default Payment Terms Template", + "length": 0, + "no_copy": 0, + "options": "Payment Terms Template", + "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, - "default": "1", - "fieldname": "enable_perpetual_inventory", - "fieldtype": "Check", - "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": "Enable Perpetual Inventory", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "eval:!doc.__islocal", + "fetch_if_empty": 0, + "fieldname": "auto_accounting_for_stock_settings", + "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": "Stock Settings", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "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, - "fieldname": "default_inventory_account", - "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": "Default Inventory Account", - "length": 0, - "no_copy": 0, - "options": "Account", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "default": "1", + "fetch_if_empty": 0, + "fieldname": "enable_perpetual_inventory", + "fieldtype": "Check", + "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": "Enable Perpetual Inventory", + "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, - "fieldname": "stock_adjustment_account", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 1, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Stock Adjustment Account", - "length": 0, - "no_copy": 1, - "options": "Account", - "permlevel": 0, - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "default_inventory_account", + "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": "Default Inventory Account", + "length": 0, + "no_copy": 0, + "options": "Account", + "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, - "fieldname": "column_break_32", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "stock_adjustment_account", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 1, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Stock Adjustment Account", + "length": 0, + "no_copy": 1, + "options": "Account", + "permlevel": 0, + "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, - "fieldname": "stock_received_but_not_billed", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 1, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Stock Received But Not Billed", - "length": 0, - "no_copy": 1, - "options": "Account", - "permlevel": 0, - "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, + "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_32", + "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 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "expenses_included_in_valuation", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 1, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Expenses Included In Valuation", - "length": 0, - "no_copy": 1, - "options": "Account", - "permlevel": 0, - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "stock_received_but_not_billed", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 1, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Stock Received But Not Billed", + "length": 0, + "no_copy": 1, + "options": "Account", + "permlevel": 0, + "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, - "fieldname": "fixed_asset_depreciation_settings", - "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": "Fixed Asset Depreciation Settings", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "expenses_included_in_valuation", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 1, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Expenses Included In Valuation", + "length": 0, + "no_copy": 1, + "options": "Account", + "permlevel": 0, + "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, - "fieldname": "accumulated_depreciation_account", - "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": "Accumulated Depreciation Account", - "length": 0, - "no_copy": 1, - "options": "Account", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "fixed_asset_depreciation_settings", + "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": "Fixed Asset Depreciation Settings", + "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, - "fieldname": "depreciation_expense_account", - "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": "Depreciation Expense Account", - "length": 0, - "no_copy": 1, - "options": "Account", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "accumulated_depreciation_account", + "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": "Accumulated Depreciation Account", + "length": 0, + "no_copy": 1, + "options": "Account", + "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, - "fieldname": "series_for_depreciation_entry", - "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": "Series for Asset Depreciation Entry (Journal Entry)", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "depreciation_expense_account", + "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": "Depreciation Expense Account", + "length": 0, + "no_copy": 1, + "options": "Account", + "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, - "fieldname": "expenses_included_in_asset_valuation", - "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": "Expenses Included In Asset Valuation", - "length": 0, - "no_copy": 0, - "options": "Account", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "series_for_depreciation_entry", + "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": "Series for Asset Depreciation Entry (Journal Entry)", + "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, - "fieldname": "column_break_40", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "expenses_included_in_asset_valuation", + "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": "Expenses Included In Asset Valuation", + "length": 0, + "no_copy": 0, + "options": "Account", + "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, - "fieldname": "disposal_account", - "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": "Gain/Loss Account on Asset Disposal", - "length": 0, - "no_copy": 1, - "options": "Account", - "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, + "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_40", + "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 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "depreciation_cost_center", - "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": "Asset Depreciation Cost Center", - "length": 0, - "no_copy": 1, - "options": "Cost Center", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "disposal_account", + "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": "Gain/Loss Account on Asset Disposal", + "length": 0, + "no_copy": 1, + "options": "Account", + "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, - "fieldname": "capital_work_in_progress_account", - "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": "Capital Work In Progress Account", - "length": 0, - "no_copy": 0, - "options": "Account", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "depreciation_cost_center", + "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": "Asset Depreciation Cost Center", + "length": 0, + "no_copy": 1, + "options": "Cost Center", + "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, - "fieldname": "asset_received_but_not_billed", - "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": "Asset Received But Not Billed", - "length": 0, - "no_copy": 0, - "options": "Account", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "capital_work_in_progress_account", + "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": "Capital Work In Progress Account", + "length": 0, + "no_copy": 0, + "options": "Account", + "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": 1, - "columns": 0, - "fieldname": "budget_detail", - "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": "Budget Detail", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "asset_received_but_not_billed", + "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": "Asset Received But Not Billed", + "length": 0, + "no_copy": 0, + "options": "Account", + "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, - "fieldname": "exception_budget_approver_role", - "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": "Exception Budget Approver Role", - "length": 0, - "no_copy": 0, - "options": "Role", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 1, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "budget_detail", + "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": "Budget Detail", + "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, - "description": "For reference only.", - "fieldname": "company_info", - "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": "Company Info", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "exception_budget_approver_role", + "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": "Exception Budget Approver Role", + "length": 0, + "no_copy": 0, + "options": "Role", + "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, - "fieldname": "date_of_incorporation", - "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": "Date of Incorporation", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "description": "For reference only.", + "fetch_if_empty": 0, + "fieldname": "company_info", + "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": "Company Info", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "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, - "fieldname": "address_html", - "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, - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "date_of_incorporation", + "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": "Date of Incorporation", + "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, - "fieldname": "column_break1", - "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, - "oldfieldtype": "Column Break", - "permlevel": 0, - "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, + "fetch_if_empty": 0, + "fieldname": "address_html", + "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, + "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, + "fetch_if_empty": 0, + "fieldname": "column_break1", + "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, + "oldfieldtype": "Column Break", + "permlevel": 0, + "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, "width": "50%" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:doc.date_of_incorporation", - "fieldname": "date_of_commencement", - "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": "Date of Commencement", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "eval:doc.date_of_incorporation", + "fetch_if_empty": 0, + "fieldname": "date_of_commencement", + "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": "Date of Commencement", + "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, - "fieldname": "phone_no", - "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": "Phone No", - "length": 0, - "no_copy": 0, - "oldfieldname": "phone_no", - "oldfieldtype": "Data", - "options": "Phone", - "permlevel": 0, - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "phone_no", + "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": "Phone No", + "length": 0, + "no_copy": 0, + "oldfieldname": "phone_no", + "oldfieldtype": "Data", + "options": "Phone", + "permlevel": 0, + "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, - "fieldname": "fax", - "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": "Fax", - "length": 0, - "no_copy": 0, - "oldfieldname": "fax", - "oldfieldtype": "Data", - "options": "Phone", - "permlevel": 0, - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "fax", + "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": "Fax", + "length": 0, + "no_copy": 0, + "oldfieldname": "fax", + "oldfieldtype": "Data", + "options": "Phone", + "permlevel": 0, + "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, - "fieldname": "email", - "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": "Email", - "length": 0, - "no_copy": 0, - "oldfieldname": "email", - "oldfieldtype": "Data", - "options": "Email", - "permlevel": 0, - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "email", + "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": "Email", + "length": 0, + "no_copy": 0, + "oldfieldname": "email", + "oldfieldtype": "Data", + "options": "Email", + "permlevel": 0, + "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, - "fieldname": "website", - "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": "Website", - "length": 0, - "no_copy": 0, - "oldfieldname": "website", - "oldfieldtype": "Data", - "permlevel": 0, - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "website", + "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": "Website", + "length": 0, + "no_copy": 0, + "oldfieldname": "website", + "oldfieldtype": "Data", + "permlevel": 0, + "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, - "description": "", - "fieldname": "registration_info", - "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, - "oldfieldtype": "Section Break", - "permlevel": 0, - "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, + "description": "", + "fetch_if_empty": 0, + "fieldname": "registration_info", + "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, + "oldfieldtype": "Section Break", + "permlevel": 0, + "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, "width": "50%" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "description": "Company registration numbers for your reference. Tax numbers etc.", - "fieldname": "registration_details", - "fieldtype": "Code", - "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": "Registration Details", - "length": 0, - "no_copy": 0, - "oldfieldname": "registration_details", - "oldfieldtype": "Code", - "permlevel": 0, - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "description": "Company registration numbers for your reference. Tax numbers etc.", + "fetch_if_empty": 0, + "fieldname": "registration_details", + "fieldtype": "Code", + "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": "Registration Details", + "length": 0, + "no_copy": 0, + "oldfieldname": "registration_details", + "oldfieldtype": "Code", + "permlevel": 0, + "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, - "fieldname": "delete_company_transactions", - "fieldtype": "Button", - "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": "Delete Company Transactions", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "delete_company_transactions", + "fieldtype": "Button", + "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": "Delete Company Transactions", + "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, - "fieldname": "lft", - "fieldtype": "Int", - "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Lft", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 1, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "lft", + "fieldtype": "Int", + "hidden": 1, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Lft", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 1, + "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, - "fieldname": "rgt", - "fieldtype": "Int", - "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Rgt", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 1, - "set_only_once": 0, - "translatable": 0, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "rgt", + "fieldtype": "Int", + "hidden": 1, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Rgt", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 1, + "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, - "fieldname": "old_parent", - "fieldtype": "Data", - "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "old_parent", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "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, + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "old_parent", + "fieldtype": "Data", + "hidden": 1, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "old_parent", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "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 } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "icon": "fa fa-building", - "idx": 1, - "image_field": "company_logo", - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "menu_index": 0, - "modified": "2019-02-26 13:24:55.386120", - "modified_by": "Administrator", - "module": "Setup", - "name": "Company", - "owner": "Administrator", + ], + "has_web_view": 0, + "hide_heading": 0, + "hide_toolbar": 0, + "icon": "fa fa-building", + "idx": 1, + "image_field": "company_logo", + "image_view": 0, + "in_create": 0, + "is_submittable": 0, + "issingle": 0, + "istable": 0, + "max_attachments": 0, + "menu_index": 0, + "modified": "2019-05-12 15:26:11.503507", + "modified_by": "Administrator", + "module": "Setup", + "name": "Company", + "owner": "Administrator", "permissions": [ { - "amend": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "System Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 0, + "amend": 0, + "cancel": 0, + "create": 1, + "delete": 1, + "email": 1, + "export": 0, + "if_owner": 0, + "import": 0, + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "set_user_permissions": 0, + "share": 1, + "submit": 0, "write": 1 }, { - "amend": 0, - "cancel": 0, - "create": 0, - "delete": 0, - "email": 1, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 0, - "role": "Accounts User", - "set_user_permissions": 0, - "share": 0, - "submit": 0, + "amend": 0, + "cancel": 0, + "create": 0, + "delete": 0, + "email": 1, + "export": 0, + "if_owner": 0, + "import": 0, + "permlevel": 0, + "print": 1, + "read": 1, + "report": 0, + "role": "Accounts User", + "set_user_permissions": 0, + "share": 0, + "submit": 0, "write": 0 }, { - "amend": 0, - "cancel": 0, - "create": 0, - "delete": 0, - "email": 0, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 0, - "read": 1, - "report": 0, - "role": "Employee", - "set_user_permissions": 0, - "share": 0, - "submit": 0, + "amend": 0, + "cancel": 0, + "create": 0, + "delete": 0, + "email": 0, + "export": 0, + "if_owner": 0, + "import": 0, + "permlevel": 0, + "print": 0, + "read": 1, + "report": 0, + "role": "Employee", + "set_user_permissions": 0, + "share": 0, + "submit": 0, "write": 0 }, { - "amend": 0, - "cancel": 0, - "create": 0, - "delete": 0, - "email": 0, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 0, - "read": 1, - "report": 0, - "role": "Sales User", - "set_user_permissions": 0, - "share": 0, - "submit": 0, + "amend": 0, + "cancel": 0, + "create": 0, + "delete": 0, + "email": 0, + "export": 0, + "if_owner": 0, + "import": 0, + "permlevel": 0, + "print": 0, + "read": 1, + "report": 0, + "role": "Sales User", + "set_user_permissions": 0, + "share": 0, + "submit": 0, "write": 0 }, { - "amend": 0, - "cancel": 0, - "create": 0, - "delete": 0, - "email": 0, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 0, - "read": 1, - "report": 0, - "role": "Purchase User", - "set_user_permissions": 0, - "share": 0, - "submit": 0, + "amend": 0, + "cancel": 0, + "create": 0, + "delete": 0, + "email": 0, + "export": 0, + "if_owner": 0, + "import": 0, + "permlevel": 0, + "print": 0, + "read": 1, + "report": 0, + "role": "Purchase User", + "set_user_permissions": 0, + "share": 0, + "submit": 0, "write": 0 }, { - "amend": 0, - "cancel": 0, - "create": 0, - "delete": 0, - "email": 0, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 0, - "read": 1, - "report": 0, - "role": "Stock User", - "set_user_permissions": 0, - "share": 0, - "submit": 0, + "amend": 0, + "cancel": 0, + "create": 0, + "delete": 0, + "email": 0, + "export": 0, + "if_owner": 0, + "import": 0, + "permlevel": 0, + "print": 0, + "read": 1, + "report": 0, + "role": "Stock User", + "set_user_permissions": 0, + "share": 0, + "submit": 0, "write": 0 }, { - "amend": 0, - "cancel": 0, - "create": 0, - "delete": 0, - "email": 0, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 0, - "read": 1, - "report": 0, - "role": "Projects User", - "set_user_permissions": 0, - "share": 0, - "submit": 0, + "amend": 0, + "cancel": 0, + "create": 0, + "delete": 0, + "email": 0, + "export": 0, + "if_owner": 0, + "import": 0, + "permlevel": 0, + "print": 0, + "read": 1, + "report": 0, + "role": "Projects User", + "set_user_permissions": 0, + "share": 0, + "submit": 0, "write": 0 } - ], - "quick_entry": 0, - "read_only": 0, - "read_only_onload": 0, - "show_name_in_global_search": 1, - "sort_order": "ASC", - "track_changes": 1, - "track_seen": 0, + ], + "quick_entry": 0, + "read_only": 0, + "read_only_onload": 0, + "show_name_in_global_search": 1, + "sort_order": "ASC", + "track_changes": 1, + "track_seen": 0, "track_views": 0 } \ No newline at end of file From 077e20f7aeeab48f2cbbefa2cb65fb5143f82341 Mon Sep 17 00:00:00 2001 From: Saurabh Date: Mon, 13 May 2019 15:21:06 +0530 Subject: [PATCH 16/32] fix: valiadte customer while pulling information --- erpnext/accounts/doctype/pricing_rule/pricing_rule.py | 7 ++++++- erpnext/public/js/controllers/transaction.js | 1 + erpnext/stock/get_item_details.py | 4 ++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py index ac0cd7e895c..7f0f60ff02e 100644 --- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py +++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py @@ -167,7 +167,12 @@ def get_pricing_rule_for_item(args): if args.transaction_type=="selling": if args.customer and not (args.customer_group and args.territory): - customer = frappe.get_cached_value("Customer", args.customer, ["customer_group", "territory"]) + + if args.quotation_to and args.quotation_to != 'Customer': + customer = frappe._dict() + else: + customer = frappe.get_cached_value("Customer", args.customer, ["customer_group", "territory"]) + if customer: args.customer_group, args.territory = customer diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index 8c74f736eab..623b6e7d216 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -429,6 +429,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ set_warehouse: me.frm.doc.set_warehouse, warehouse: item.warehouse, customer: me.frm.doc.customer || me.frm.doc.party_name, + quotation_to: me.frm.doc.quotation_to, supplier: me.frm.doc.supplier, currency: me.frm.doc.currency, update_stock: update_stock, diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py index 1c614dffab9..f9a4a151a4b 100644 --- a/erpnext/stock/get_item_details.py +++ b/erpnext/stock/get_item_details.py @@ -573,6 +573,10 @@ def validate_conversion_rate(args, meta): def get_party_item_code(args, item_doc, out): if args.transaction_type=="selling" and args.customer: out.customer_item_code = None + + if args.quotation_to != 'Customer': + return + customer_item_code = item_doc.get("customer_items", {"customer_name": args.customer}) if customer_item_code: From a6ad0b0ec82e77b3ea49d49265102c449b3c23f3 Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Tue, 14 May 2019 08:49:24 +0530 Subject: [PATCH 17/32] fix: Do not append row if item is sold within days since last order --- .../report/inactive_sales_items/inactive_sales_items.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/erpnext/accounts/report/inactive_sales_items/inactive_sales_items.py b/erpnext/accounts/report/inactive_sales_items/inactive_sales_items.py index 42761a58b95..b670e6e91fa 100644 --- a/erpnext/accounts/report/inactive_sales_items/inactive_sales_items.py +++ b/erpnext/accounts/report/inactive_sales_items/inactive_sales_items.py @@ -96,6 +96,8 @@ def get_data(filters): "qty": item_obj.qty, "days_since_last_order": item_obj.days_since_last_order }) + else: + continue data.append(row) From 3b810ea8da80f7089e0dafb64d8b202a60db14dc Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Tue, 14 May 2019 14:32:36 +0530 Subject: [PATCH 18/32] fix: Make territory filter mandatory --- .../report/inactive_sales_items/inactive_sales_items.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/report/inactive_sales_items/inactive_sales_items.js b/erpnext/accounts/report/inactive_sales_items/inactive_sales_items.js index a54a6c17fb7..ef0716a4903 100644 --- a/erpnext/accounts/report/inactive_sales_items/inactive_sales_items.js +++ b/erpnext/accounts/report/inactive_sales_items/inactive_sales_items.js @@ -8,7 +8,8 @@ frappe.query_reports["Inactive Sales Items"] = { fieldname: "territory", label: __("Territory"), fieldtype: "Link", - options: "Territory" + options: "Territory", + reqd: 1, }, { fieldname: "item", From 2389e2c43894f863b6b052843363f2b6abd10094 Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Tue, 14 May 2019 14:40:18 +0530 Subject: [PATCH 19/32] fix: Change lead to party_name --- erpnext/crm/doctype/lead/lead.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/crm/doctype/lead/lead.py b/erpnext/crm/doctype/lead/lead.py index 338e0368c7d..bbd73e63c80 100644 --- a/erpnext/crm/doctype/lead/lead.py +++ b/erpnext/crm/doctype/lead/lead.py @@ -102,7 +102,7 @@ class Lead(SellingController): def has_lost_quotation(self): return frappe.db.get_value("Quotation", { - "lead": self.name, + "party_name": self.name, "docstatus": 1, "status": "Lost" }) From cfd18d4e03a3af51d3fd2a5b484803d79b9356fb Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Tue, 14 May 2019 14:57:22 +0530 Subject: [PATCH 20/32] fix: Lead and customer dashboard fixes --- erpnext/crm/doctype/lead/lead_dashboard.py | 7 +++++-- erpnext/selling/doctype/customer/customer_dashboard.py | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/erpnext/crm/doctype/lead/lead_dashboard.py b/erpnext/crm/doctype/lead/lead_dashboard.py index b33f12f5089..69d8ca70926 100644 --- a/erpnext/crm/doctype/lead/lead_dashboard.py +++ b/erpnext/crm/doctype/lead/lead_dashboard.py @@ -5,8 +5,11 @@ def get_data(): return { 'fieldname': 'lead', 'non_standard_fieldnames': { - 'Quotation': 'customer_name', - 'Opportunity': 'customer_name' + 'Quotation': 'party_name', + 'Opportunity': 'party_name' + }, + 'dynamic_links': { + 'party_name': ['Lead', 'quotation_to'] }, 'transactions': [ { diff --git a/erpnext/selling/doctype/customer/customer_dashboard.py b/erpnext/selling/doctype/customer/customer_dashboard.py index 67c69339ea9..075ad4eb60c 100644 --- a/erpnext/selling/doctype/customer/customer_dashboard.py +++ b/erpnext/selling/doctype/customer/customer_dashboard.py @@ -7,8 +7,11 @@ def get_data(): 'heatmap_message': _('This is based on transactions against this Customer. See timeline below for details'), 'fieldname': 'customer', 'non_standard_fieldnames': { - 'Quotation': 'customer_name', - 'Opportunity': 'customer_name' + 'Quotation': 'party_name', + 'Opportunity': 'party_name' + }, + 'dynamic_links': { + 'party_name': ['Customer', 'quotation_to'] }, 'transactions': [ { From 0e30e705c543e696abe9c4024cbb8327128bc84b Mon Sep 17 00:00:00 2001 From: Sahil Khan Date: Tue, 14 May 2019 17:08:26 +0550 Subject: [PATCH 21/32] bumped to version 11.1.29 --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 92d7435ebd0..fdf815bda17 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -5,7 +5,7 @@ import frappe from erpnext.hooks import regional_overrides from frappe.utils import getdate -__version__ = '11.1.28' +__version__ = '11.1.29' def get_default_company(user=None): '''Get default company for user''' From 0361c5050347b7634e527440ead1ab652b520bb2 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Wed, 15 May 2019 07:38:57 +0530 Subject: [PATCH 22/32] refactor: Payroll processing and tax calculation (#17595) * refactor: Payroll processing and tax calculation * fix: payroll test cases * fix: Codacy fixes * fix: removed debug mode * fix: payroll test cases * Update payroll_period.py --- .../doctype/bank_guarantee/bank_guarantee.py | 2 - .../bank_reconciliation.py | 2 +- .../accounts_receivable.html | 6 +- .../additional_salary/additional_salary.js | 9 +- .../additional_salary/additional_salary.json | 50 +- .../additional_salary/additional_salary.py | 23 +- .../employee_benefit_application.js | 17 +- .../employee_benefit_application.py | 107 +- .../employee_benefit_claim.py | 39 +- .../employee_tax_exemption_declaration.json | 68 +- .../employee_tax_exemption_declaration.py | 3 +- ...ployee_tax_exemption_proof_submission.json | 68 +- .../hr/doctype/payroll_entry/payroll_entry.py | 5 +- .../doctype/payroll_period/payroll_period.py | 50 +- .../salary_component/salary_component.js | 8 - .../salary_component/salary_component.json | 73 +- .../salary_component/test_records.json | 3 +- .../salary_component/test_salary_component.py | 4 +- .../doctype/salary_detail/salary_detail.json | 105 +- erpnext/hr/doctype/salary_slip/salary_slip.js | 193 +-- .../hr/doctype/salary_slip/salary_slip.json | 106 +- erpnext/hr/doctype/salary_slip/salary_slip.py | 1030 ++++++++--------- .../doctype/salary_slip/test_salary_slip.py | 46 +- .../salary_structure/salary_structure.js | 3 +- .../salary_structure/salary_structure.py | 4 +- .../salary_structure/test_salary_structure.py | 9 +- .../report/salary_register/salary_register.py | 4 +- erpnext/hr/utils.py | 12 +- erpnext/regional/india/utils.py | 9 +- erpnext/setup/doctype/company/company.js | 5 - 30 files changed, 1069 insertions(+), 994 deletions(-) diff --git a/erpnext/accounts/doctype/bank_guarantee/bank_guarantee.py b/erpnext/accounts/doctype/bank_guarantee/bank_guarantee.py index 13ed5b6b948..9aa2ee271a4 100644 --- a/erpnext/accounts/doctype/bank_guarantee/bank_guarantee.py +++ b/erpnext/accounts/doctype/bank_guarantee/bank_guarantee.py @@ -22,7 +22,5 @@ class BankGuarantee(Document): @frappe.whitelist() def get_vouchar_detials(column_list, doctype, docname): - print (column_list, doctype, docname) return frappe.db.sql(''' select {columns} from `tab{doctype}` where name=%s''' .format(columns=", ".join(json.loads(column_list)), doctype=doctype), docname, as_dict=1)[0] - diff --git a/erpnext/accounts/page/bank_reconciliation/bank_reconciliation.py b/erpnext/accounts/page/bank_reconciliation/bank_reconciliation.py index bc642212793..3d4a6125057 100644 --- a/erpnext/accounts/page/bank_reconciliation/bank_reconciliation.py +++ b/erpnext/accounts/page/bank_reconciliation/bank_reconciliation.py @@ -122,7 +122,7 @@ def check_matching_amount(bank_account, company, transaction): """, { 'bank_account': bank_account, 'txt': '%%%s%%' % amount - }, as_dict=True, debug=1) + }, as_dict=True) frappe.errprint(journal_entries) diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.html b/erpnext/accounts/report/accounts_receivable/accounts_receivable.html index 1bff93cb77e..d7aa0c0d191 100644 --- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.html +++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.html @@ -111,10 +111,10 @@ {%= __("Age (Days)") %} {% if(report.report_name === "Accounts Receivable" && filters.show_sales_person_in_print) { %} - {%= __("Reference") %} + {%= __("Reference") %} {%= __("Sales Person") %} {% } else { %} - {%= __("Reference") %} + {%= __("Reference") %} {% } %} {% if(!filters.show_pdc_in_print) { %} {%= (filters.customer || filters.supplier) ? __("Remarks"): __("Party") %} @@ -127,7 +127,7 @@ {%= __("Outstanding Amount") %} {% if(filters.show_pdc_in_print) { %} {% if(report.report_name === "Accounts Receivable") { %} - {%= __("Customer LPO No.") %} + {%= __("Customer LPO No.") %} {% } %} {%= __("PDC/LC Ref") %} {%= __("PDC/LC Amount") %} diff --git a/erpnext/hr/doctype/additional_salary/additional_salary.js b/erpnext/hr/doctype/additional_salary/additional_salary.js index a96bb942825..d0f64ab51bb 100644 --- a/erpnext/hr/doctype/additional_salary/additional_salary.js +++ b/erpnext/hr/doctype/additional_salary/additional_salary.js @@ -3,13 +3,8 @@ frappe.ui.form.on('Additional Salary', { setup: function(frm) { - frm.set_query("salary_component", function() { - return { - filters: { - is_additional_component: true - } - }; - }); + frm.add_fetch("salary_component", "deduct_full_tax_on_selected_payroll_date", "deduct_full_tax_on_selected_payroll_date"); + frm.set_query("employee", function() { return { filters: { diff --git a/erpnext/hr/doctype/additional_salary/additional_salary.json b/erpnext/hr/doctype/additional_salary/additional_salary.json index 7f9e51b5f9d..6768b49e288 100644 --- a/erpnext/hr/doctype/additional_salary/additional_salary.json +++ b/erpnext/hr/doctype/additional_salary/additional_salary.json @@ -1,5 +1,6 @@ { "allow_copy": 0, + "allow_events_in_timeline": 0, "allow_guest_to_view": 0, "allow_import": 1, "allow_rename": 0, @@ -21,6 +22,7 @@ "collapsible": 0, "columns": 0, "default": "", + "fetch_if_empty": 0, "fieldname": "naming_series", "fieldtype": "Select", "hidden": 0, @@ -54,6 +56,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "employee", "fieldtype": "Link", "hidden": 0, @@ -87,6 +90,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "salary_component", "fieldtype": "Link", "hidden": 0, @@ -120,6 +124,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "amount", "fieldtype": "Currency", "hidden": 0, @@ -153,6 +158,7 @@ "collapsible": 0, "columns": 0, "default": "1", + "fetch_if_empty": 0, "fieldname": "overwrite_salary_structure_amount", "fieldtype": "Check", "hidden": 0, @@ -185,6 +191,40 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, + "fieldname": "deduct_full_tax_on_selected_payroll_date", + "fieldtype": "Check", + "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": "Deduct Full Tax on Selected Payroll 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": 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, + "fetch_if_empty": 0, "fieldname": "column_break_5", "fieldtype": "Column Break", "hidden": 0, @@ -217,6 +257,8 @@ "collapsible": 0, "columns": 0, "default": "", + "description": "Date on which this component is applied", + "fetch_if_empty": 0, "fieldname": "payroll_date", "fieldtype": "Date", "hidden": 0, @@ -250,6 +292,7 @@ "collapsible": 0, "columns": 0, "fetch_from": "employee.employee_name", + "fetch_if_empty": 0, "fieldname": "employee_name", "fieldtype": "Data", "hidden": 0, @@ -284,6 +327,7 @@ "collapsible": 0, "columns": 0, "fetch_from": "employee.department", + "fetch_if_empty": 0, "fieldname": "department", "fieldtype": "Link", "hidden": 0, @@ -317,6 +361,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "company", "fieldtype": "Link", "hidden": 0, @@ -350,6 +395,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "salary_slip", "fieldtype": "Link", "hidden": 0, @@ -384,6 +430,7 @@ "collapsible": 0, "columns": 0, "fetch_from": "salary_component.type", + "fetch_if_empty": 0, "fieldname": "type", "fieldtype": "Data", "hidden": 0, @@ -417,6 +464,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "amended_from", "fieldtype": "Link", "hidden": 0, @@ -453,7 +501,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2018-08-21 14:44:22.921926", + "modified": "2019-05-09 19:53:37.475839", "modified_by": "Administrator", "module": "HR", "name": "Additional Salary", diff --git a/erpnext/hr/doctype/additional_salary/additional_salary.py b/erpnext/hr/doctype/additional_salary/additional_salary.py index 9ca1260fe06..1ae51aea2a8 100644 --- a/erpnext/hr/doctype/additional_salary/additional_salary.py +++ b/erpnext/hr/doctype/additional_salary/additional_salary.py @@ -35,7 +35,8 @@ class AdditionalSalary(Document): @frappe.whitelist() def get_additional_salary_component(employee, start_date, end_date): additional_components = frappe.db.sql(""" - select salary_component, sum(amount) as amount, overwrite_salary_structure_amount from `tabAdditional Salary` + select salary_component, sum(amount) as amount, overwrite_salary_structure_amount, deduct_full_tax_on_selected_payroll_date + from `tabAdditional Salary` where employee=%(employee)s and docstatus = 1 and payroll_date between %(from_date)s and %(to_date)s @@ -48,16 +49,20 @@ def get_additional_salary_component(employee, start_date, end_date): }, as_dict=1) additional_components_list = [] + component_fields = ["depends_on_payment_days", "salary_component_abbr", "is_tax_applicable", "variable_based_on_taxable_salary", 'type'] for d in additional_components: - component = frappe.get_doc("Salary Component", d.salary_component) - struct_row = {'salary_component': d.salary_component} - for field in ["depends_on_payment_days", "abbr", "is_tax_applicable", "variable_based_on_taxable_salary", "is_additional_component"]: - struct_row[field] = component.get(field) + struct_row = frappe._dict({'salary_component': d.salary_component}) + component = frappe.get_all("Salary Component", filters={'name': d.salary_component}, fields=component_fields) + if component: + struct_row.update(component[0]) - additional_components_list.append({ + struct_row['deduct_full_tax_on_selected_payroll_date'] = d.deduct_full_tax_on_selected_payroll_date + struct_row['is_additional_component'] = 1 + + additional_components_list.append(frappe._dict({ 'amount': d.amount, - 'type': component.type, + 'type': component[0].type, 'struct_row': struct_row, - 'overwrite': d.overwrite_salary_structure_amount - }) + 'overwrite': d.overwrite_salary_structure_amount, + })) return additional_components_list \ No newline at end of file diff --git a/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.js b/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.js index 412a08aa9f5..e71ce1276b5 100644 --- a/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.js +++ b/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.js @@ -3,13 +3,18 @@ frappe.ui.form.on('Employee Benefit Application', { setup: function(frm) { - frm.set_query("earning_component", "employee_benefits", function() { - return { - query : "erpnext.hr.doctype.employee_benefit_application.employee_benefit_application.get_earning_components", - filters: {date: frm.doc.date, employee: frm.doc.employee} - }; - }); + if(!frm.doc.employee || !frm.doc.date) { + frappe.throw(__("Please select Employee and Date first")); + } else { + frm.set_query("earning_component", "employee_benefits", function() { + return { + query : "erpnext.hr.doctype.employee_benefit_application.employee_benefit_application.get_earning_components", + filters: {date: frm.doc.date, employee: frm.doc.employee} + }; + }); + } }, + employee: function(frm) { var method, args; if(frm.doc.employee && frm.doc.date && frm.doc.payroll_period){ diff --git a/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.py b/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.py index 701ae2465ff..fea4246d646 100644 --- a/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.py +++ b/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.py @@ -7,7 +7,7 @@ import frappe from frappe import _ from frappe.utils import date_diff, getdate, rounded, add_days, cstr, cint, flt from frappe.model.document import Document -from erpnext.hr.doctype.payroll_period.payroll_period import get_payroll_period_days +from erpnext.hr.doctype.payroll_period.payroll_period import get_payroll_period_days, get_period_factor from erpnext.hr.doctype.salary_structure_assignment.salary_structure_assignment import get_assigned_salary_structure from erpnext.hr.utils import get_sal_slip_total_benefit_given, get_holidays_for_employee, get_previous_claimed_amount @@ -131,7 +131,7 @@ def get_max_benefits_remaining(employee, on_date, payroll_period): salary_component = frappe.get_doc("Salary Component", sal_struct_row.salary_component) if salary_component.depends_on_payment_days == 1 and salary_component.pay_against_benefit_claim != 1: have_depends_on_payment_days = True - benefit_amount = get_benefit_pro_rata_ratio_amount(sal_struct, salary_component.max_benefit_amount) + benefit_amount = get_benefit_amount_based_on_pro_rata(sal_struct, salary_component.max_benefit_amount) amount_per_day = benefit_amount / payroll_period_days per_day_amount_total += amount_per_day @@ -167,16 +167,14 @@ def calculate_lwp(employee, start_date, holidays, working_days): lwp = cint(leave[0][1]) and (lwp + 0.5) or (lwp + 1) return lwp -def get_benefit_component_amount(employee, start_date, end_date, struct_row, sal_struct, period_length, frequency): - payroll_period, period_factor, actual_payroll_days = get_payroll_period_days(start_date, end_date, employee) - +def get_benefit_component_amount(employee, start_date, end_date, salary_component, sal_struct, payroll_frequency, payroll_period): if not payroll_period: - frappe.msgprint(_("Start and end dates not in a valid Payroll Period, cannot calculate {0}.") - .format(struct_row.salary_component)) + frappe.msgprint(_("Start and end dates not in a valid Payroll Period, cannot calculate {0}") + .format(salary_component)) return False # Considering there is only one application for a year - benefit_application_name = frappe.db.sql(""" + benefit_application = frappe.db.sql(""" select name from `tabEmployee Benefit Application` where @@ -185,69 +183,58 @@ def get_benefit_component_amount(employee, start_date, end_date, struct_row, sal and docstatus = 1 """, { 'employee': employee, - 'payroll_period': payroll_period + 'payroll_period': payroll_period.name }) - if frappe.db.get_value("Salary Component", struct_row.salary_component, "depends_on_payment_days") != 1: - if frequency == "Monthly" and actual_payroll_days in range(360, 370): - period_length = 1 - period_factor = 12 + current_benefit_amount = 0.0 + component_max_benefit, depends_on_payment_days = frappe.db.get_value("Salary Component", + salary_component, ["max_benefit_amount", "depends_on_payment_days"]) - if period_factor: - # If there is application for benefit then fetch the amount from the application. - # else Split the max benefits to the pro-rata components with the ratio of their max_benefit_amount - if benefit_application_name: - benefit_application = frappe.get_doc("Employee Benefit Application", benefit_application_name[0][0]) - return get_benefit_amount(benefit_application, struct_row, period_factor, period_length) + if benefit_application: + benefit_amount = frappe.db.get_value("Employee Benefit Application Detail", + {"parent": benefit_application[0][0], "earning_component": salary_component}, "amount") + elif component_max_benefit: + benefit_amount = get_benefit_amount_based_on_pro_rata(sal_struct, component_max_benefit) - # TODO: Check if there is benefit claim for employee then pro-rata divide the rest of amount (Late Benefit Application) - else: - component_max = frappe.db.get_value("Salary Component", struct_row.salary_component, "max_benefit_amount") - if component_max: - benefit_amount = get_benefit_pro_rata_ratio_amount(sal_struct, component_max) - return get_amount(period_factor, benefit_amount, period_length) - return False + current_benefit_amount = 0 + if benefit_amount: + total_sub_periods = get_period_factor(employee, + start_date, end_date, payroll_frequency, payroll_period, depends_on_payment_days)[0] -def get_benefit_pro_rata_ratio_amount(sal_struct, component_max): - total_pro_rata_max = 0 + current_benefit_amount = benefit_amount / total_sub_periods + + return current_benefit_amount + +def get_benefit_amount_based_on_pro_rata(sal_struct, component_max_benefit): + max_benefits_total = 0 benefit_amount = 0 - for sal_struct_row in sal_struct.get("earnings"): - pay_against_benefit_claim, max_benefit_amount = frappe.db.get_value("Salary Component", - sal_struct_row.salary_component, ["pay_against_benefit_claim", "max_benefit_amount"]) - if sal_struct_row.is_flexible_benefit == 1 and pay_against_benefit_claim != 1: - total_pro_rata_max += max_benefit_amount - if total_pro_rata_max > 0: - benefit_amount = component_max * sal_struct.max_benefits / total_pro_rata_max - if benefit_amount > component_max: - benefit_amount = component_max + for d in sal_struct.get("earnings"): + if d.is_flexible_benefit == 1: + component = frappe.db.get_value("Salary Component", d.salary_component, ["max_benefit_amount", "pay_against_benefit_claim"], as_dict=1) + if not component.pay_against_benefit_claim: + max_benefits_total += component.max_benefit_amount + + if max_benefits_total > 0: + benefit_amount = sal_struct.max_benefits * component.max_benefit_amount / max_benefits_total + if benefit_amount > component_max_benefit: + benefit_amount = component_max_benefit + return benefit_amount -def get_benefit_amount(application, struct_row, period_factor, period_length): - amount = 0 - for employee_benefit in application.employee_benefits: - if employee_benefit.earning_component == struct_row.salary_component: - amount += get_amount(period_factor, employee_benefit.amount, period_length) - return amount if amount > 0 else False - -def get_amount(period_factor, amount, period_length): - amount_per_day = amount / period_factor - total_amount = amount_per_day * period_length - return total_amount def get_earning_components(doctype, txt, searchfield, start, page_len, filters): if len(filters) < 2: return {} - employee = filters['employee'] - date = filters['date'] - salary_structure = get_assigned_salary_structure(employee, date) + + salary_structure = get_assigned_salary_structure(filters['employee'], filters['date']) if salary_structure: - query = """select salary_component from `tabSalary Detail` where parent = '{salary_structure}' - and is_flexible_benefit = 1 - order by name""" - - return frappe.db.sql(query.format(**{ - "salary_structure": salary_structure - })) - - return {} + return frappe.db.sql(""" + select salary_component + from `tabSalary Detail` + where parent = %s and is_flexible_benefit = 1 + order by name + """, salary_structure) + else: + frappe.throw(_("Salary Structure not found for employee {0} and date {1}") + .format(filters['employee'], filters['date'])) \ No newline at end of file diff --git a/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.py b/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.py index 8be67a866ab..3a80b303659 100644 --- a/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.py +++ b/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.py @@ -5,9 +5,11 @@ from __future__ import unicode_literals import frappe from frappe import _ +from frappe.utils import flt from frappe.model.document import Document from erpnext.hr.doctype.employee_benefit_application.employee_benefit_application import get_max_benefits -from erpnext.hr.utils import get_payroll_period, get_previous_claimed_amount +from erpnext.hr.utils import get_previous_claimed_amount +from erpnext.hr.doctype.payroll_period.payroll_period import get_payroll_period from erpnext.hr.doctype.salary_structure_assignment.salary_structure_assignment import get_assigned_salary_structure class EmployeeBenefitClaim(Document): @@ -97,31 +99,28 @@ def get_benefit_pro_rata_ratio_amount(employee, on_date, sal_struct): benefit_amount_total += benefit_amount return benefit_amount_total -def get_benefit_claim_amount(employee, start_date, end_date, salary_component): - query = """select claimed_amount from `tabEmployee Benefit Claim` - where employee=%(employee)s - and docstatus = 1 and pay_against_benefit_claim = 1 +def get_benefit_claim_amount(employee, start_date, end_date, salary_component=None): + query = """ + select sum(claimed_amount) + from `tabEmployee Benefit Claim` + where + employee=%(employee)s + and docstatus = 1 + and pay_against_benefit_claim = 1 + and claim_date between %(start_date)s and %(end_date)s """ - if not start_date: - query += "and claim_date <= %(end_date)s" - else: - query += "and (claim_date between %(start_date)s and %(end_date)s)" if salary_component: - query += "and earning_component = %(earning_component)s" + query += " and earning_component = %(earning_component)s" - benefit_claim_details = frappe.db.sql(query, { + claimed_amount = flt(frappe.db.sql(query, { 'employee': employee, 'start_date': start_date, 'end_date': end_date, 'earning_component': salary_component - }, as_dict = True) - if benefit_claim_details: - claimed_amount = 0 - for claim_detail in benefit_claim_details: - claimed_amount += claim_detail.claimed_amount - return claimed_amount - return False + })[0][0]) + + return claimed_amount def get_total_benefit_dispensed(employee, sal_struct, sal_slip_start_date, payroll_period): pro_rata_amount = 0 @@ -140,11 +139,11 @@ def get_total_benefit_dispensed(employee, sal_struct, sal_slip_start_date, payro else: pro_rata_amount = get_benefit_pro_rata_ratio_amount(employee, sal_slip_start_date, sal_struct) - claimed_amount += get_benefit_claim_amount(employee, payroll_period.start_date, payroll_period.end_date, False) + claimed_amount += get_benefit_claim_amount(employee, payroll_period.start_date, payroll_period.end_date) return claimed_amount + pro_rata_amount -def get_last_payroll_period_benefits(employee, sal_slip_start_date, sal_slip_end_date, current_flexi_amount, payroll_period, sal_struct): +def get_last_payroll_period_benefits(employee, sal_slip_start_date, sal_slip_end_date, payroll_period, sal_struct): max_benefits = get_max_benefits(employee, payroll_period.end_date) if not max_benefits: max_benefits = 0 diff --git a/erpnext/hr/doctype/employee_tax_exemption_declaration/employee_tax_exemption_declaration.json b/erpnext/hr/doctype/employee_tax_exemption_declaration/employee_tax_exemption_declaration.json index 8891b97a5de..e102ff8d705 100644 --- a/erpnext/hr/doctype/employee_tax_exemption_declaration/employee_tax_exemption_declaration.json +++ b/erpnext/hr/doctype/employee_tax_exemption_declaration/employee_tax_exemption_declaration.json @@ -446,6 +446,72 @@ "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, + "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 + }, + { + "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 } ], "has_web_view": 0, @@ -458,7 +524,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2019-04-25 16:38:05.847925", + "modified": "2019-05-11 16:13:50.472670", "modified_by": "Administrator", "module": "HR", "name": "Employee Tax Exemption Declaration", diff --git a/erpnext/hr/doctype/employee_tax_exemption_declaration/employee_tax_exemption_declaration.py b/erpnext/hr/doctype/employee_tax_exemption_declaration/employee_tax_exemption_declaration.py index cbdfcf8ecdf..f2bba7afed7 100644 --- a/erpnext/hr/doctype/employee_tax_exemption_declaration/employee_tax_exemption_declaration.py +++ b/erpnext/hr/doctype/employee_tax_exemption_declaration/employee_tax_exemption_declaration.py @@ -25,7 +25,8 @@ class EmployeeTaxExemptionDeclaration(Document): filters = { "employee": self.employee, "payroll_period": self.payroll_period, - "name": ["!=", self.name] + "name": ["!=", self.name], + "docstatus": ["!=", 2] } ) if duplicate: 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 76c09d6c7b7..9792bd1db61 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 @@ -448,6 +448,72 @@ "translatable": 0, "unique": 0 }, + { + "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 + }, + { + "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 + }, { "allow_bulk_edit": 0, "allow_in_quick_entry": 0, @@ -558,7 +624,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2019-04-25 17:06:36.569549", + "modified": "2019-05-13 12:17:18.045171", "modified_by": "Administrator", "module": "HR", "name": "Employee Tax Exemption Proof Submission", diff --git a/erpnext/hr/doctype/payroll_entry/payroll_entry.py b/erpnext/hr/doctype/payroll_entry/payroll_entry.py index af5e3d0570e..daf1532ce4c 100644 --- a/erpnext/hr/doctype/payroll_entry/payroll_entry.py +++ b/erpnext/hr/doctype/payroll_entry/payroll_entry.py @@ -539,14 +539,15 @@ def submit_salary_slips_for_employees(payroll_entry, salary_slips, publish_progr payroll_entry.email_salary_slip(submitted_ss) - payroll_entry.db_set("salary_slips_submitted", 1) - payroll_entry.notify_update() + payroll_entry.db_set("salary_slips_submitted", 1) + payroll_entry.notify_update() if not submitted_ss and not not_submitted_ss: frappe.msgprint(_("No salary slip found to submit for the above selected criteria OR salary slip already submitted")) if not_submitted_ss: frappe.msgprint(_("Could not submit some Salary Slips")) + def get_payroll_entries_for_jv(doctype, txt, searchfield, start, page_len, filters): return frappe.db.sql(""" select name from `tabPayroll Entry` diff --git a/erpnext/hr/doctype/payroll_period/payroll_period.py b/erpnext/hr/doctype/payroll_period/payroll_period.py index 506af99f50e..c1769591eaf 100644 --- a/erpnext/hr/doctype/payroll_period/payroll_period.py +++ b/erpnext/hr/doctype/payroll_period/payroll_period.py @@ -5,7 +5,7 @@ from __future__ import unicode_literals import frappe from frappe import _ -from frappe.utils import date_diff, getdate, formatdate, cint +from frappe.utils import date_diff, getdate, formatdate, cint, month_diff, flt from frappe.model.document import Document from erpnext.hr.utils import get_holidays_for_employee @@ -48,12 +48,13 @@ class PayrollPeriod(Document): def get_payroll_period_days(start_date, end_date, employee): company = frappe.db.get_value("Employee", employee, "company") payroll_period = frappe.db.sql(""" - select name, start_date, end_date from `tabPayroll Period` - where company=%(company)s - and ( - (%(start_date)s between start_date and end_date) - and (%(end_date)s between start_date and end_date) - )""", { + select name, start_date, end_date + from `tabPayroll Period` + where + company=%(company)s + and %(start_date)s between start_date and end_date + and %(end_date)s between start_date and end_date + """, { 'company': company, 'start_date': start_date, 'end_date': end_date @@ -67,3 +68,38 @@ def get_payroll_period_days(start_date, end_date, employee): working_days -= len(holidays) return payroll_period[0][0], working_days, actual_no_of_days return False, False, False + +def get_payroll_period(from_date, to_date, company): + payroll_period = frappe.db.sql(""" + select name, start_date, end_date + from `tabPayroll Period` + where start_date<=%s and end_date>= %s and company=%s + """, (from_date, to_date, company), as_dict=1) + + return payroll_period[0] if payroll_period else None + +def get_period_factor(employee, start_date, end_date, payroll_frequency, payroll_period, depends_on_payment_days=0): + # TODO if both deduct checked update the factor to make tax consistent + period_start, period_end = payroll_period.start_date, payroll_period.end_date + joining_date, relieving_date = frappe.db.get_value("Employee", employee, ["date_of_joining", "relieving_date"]) + + if getdate(joining_date) > getdate(period_start): + period_start = joining_date + if relieving_date and getdate(relieving_date) < getdate(period_end): + period_end = relieving_date + + total_sub_periods, remaining_sub_periods = 0.0, 0.0 + + if payroll_frequency == "Monthly" and not depends_on_payment_days: + total_sub_periods = month_diff(payroll_period.end_date, payroll_period.start_date) + remaining_sub_periods = month_diff(period_end, start_date) + else: + salary_days = date_diff(end_date, start_date) + 1 + + days_in_payroll_period = date_diff(payroll_period.end_date, payroll_period.start_date) + 1 + total_sub_periods = flt(days_in_payroll_period) / flt(salary_days) + + remaining_days_in_payroll_period = date_diff(period_end, start_date) + 1 + remaining_sub_periods = flt(remaining_days_in_payroll_period) / flt(salary_days) + + return total_sub_periods, remaining_sub_periods diff --git a/erpnext/hr/doctype/salary_component/salary_component.js b/erpnext/hr/doctype/salary_component/salary_component.js index f6afd5efebc..c455eb3303b 100644 --- a/erpnext/hr/doctype/salary_component/salary_component.js +++ b/erpnext/hr/doctype/salary_component/salary_component.js @@ -24,14 +24,6 @@ frappe.ui.form.on('Salary Component', { is_flexible_benefit: function(frm) { if(frm.doc.is_flexible_benefit){ set_value_for_condition_and_formula(frm); - frm.set_value("is_additional_component", 0); - frm.set_value("formula", ''); - frm.set_value("amount", 0); - } - }, - is_additional_component: function(frm) { - if(frm.doc.is_additional_component){ - frm.set_value("is_flexible_benefit", 0); frm.set_value("formula", ''); frm.set_value("amount", 0); } diff --git a/erpnext/hr/doctype/salary_component/salary_component.json b/erpnext/hr/doctype/salary_component/salary_component.json index 697d224092c..ca49ceac006 100644 --- a/erpnext/hr/doctype/salary_component/salary_component.json +++ b/erpnext/hr/doctype/salary_component/salary_component.json @@ -115,40 +115,6 @@ "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": "eval:doc.is_flexible_benefit != 1", - "fetch_if_empty": 0, - "fieldname": "is_additional_component", - "fieldtype": "Check", - "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": "Is Additional Component", - "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, @@ -285,6 +251,39 @@ "translatable": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "deduct_full_tax_on_selected_payroll_date", + "fieldtype": "Check", + "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": "Deduct Full Tax on Selected Payroll 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": 0, + "search_index": 0, + "set_only_once": 0, + "translatable": 0, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_in_quick_entry": 0, @@ -424,7 +423,7 @@ "bold": 0, "collapsible": 0, "columns": 0, - "depends_on": "eval:doc.type==\"Earning\" && doc.is_additional_component != 1 && doc.statistical_component!=1", + "depends_on": "eval:doc.type==\"Earning\" && doc.statistical_component!=1", "fetch_if_empty": 0, "fieldname": "flexible_benefits", "fieldtype": "Section Break", @@ -458,7 +457,7 @@ "bold": 0, "collapsible": 0, "columns": 0, - "depends_on": "eval:doc.is_additional_component != 1", + "depends_on": "", "fetch_if_empty": 0, "fieldname": "is_flexible_benefit", "fieldtype": "Check", @@ -1035,7 +1034,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2019-04-16 19:08:55.323567", + "modified": "2019-05-13 12:55:55.424370", "modified_by": "Administrator", "module": "HR", "name": "Salary Component", diff --git a/erpnext/hr/doctype/salary_component/test_records.json b/erpnext/hr/doctype/salary_component/test_records.json index 69491bed99f..7b22b481f36 100644 --- a/erpnext/hr/doctype/salary_component/test_records.json +++ b/erpnext/hr/doctype/salary_component/test_records.json @@ -35,7 +35,6 @@ "salary_component": "Leave Encashment", "type": "Earning", "is_payable": 1, - "is_tax_applicable": 1, - "is_additional_component": 1 + "is_tax_applicable": 1 } ] \ No newline at end of file diff --git a/erpnext/hr/doctype/salary_component/test_salary_component.py b/erpnext/hr/doctype/salary_component/test_salary_component.py index c13843aca77..965cc9e9ffd 100644 --- a/erpnext/hr/doctype/salary_component/test_salary_component.py +++ b/erpnext/hr/doctype/salary_component/test_salary_component.py @@ -19,7 +19,5 @@ def create_salary_component(component_name, **args): "salary_component": component_name, "type": args.get("type") or "Earning", "is_payable": args.get("is_payable") or 1, - "is_tax_applicable": args.get("is_tax_applicable") or 1, - "is_additional_component": args.get("is_additional_component") or 1 + "is_tax_applicable": args.get("is_tax_applicable") or 1 }).insert() - \ No newline at end of file diff --git a/erpnext/hr/doctype/salary_detail/salary_detail.json b/erpnext/hr/doctype/salary_detail/salary_detail.json index 8f2649ad21b..edf2786821e 100644 --- a/erpnext/hr/doctype/salary_detail/salary_detail.json +++ b/erpnext/hr/doctype/salary_detail/salary_detail.json @@ -218,41 +218,6 @@ "translatable": 0, "unique": 0 }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "", - "fetch_from": "salary_component.is_additional_component", - "fetch_if_empty": 0, - "fieldname": "is_additional_component", - "fieldtype": "Check", - "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Is Additional Component", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "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 - }, { "allow_bulk_edit": 0, "allow_in_quick_entry": 0, @@ -323,6 +288,39 @@ "translatable": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fetch_if_empty": 0, + "fieldname": "deduct_full_tax_on_selected_payroll_date", + "fieldtype": "Check", + "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": "Deduct Full Tax on Selected Payroll Date", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "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 + }, { "allow_bulk_edit": 0, "allow_in_quick_entry": 0, @@ -566,6 +564,41 @@ "translatable": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "default": "", + "fetch_from": "", + "fetch_if_empty": 0, + "fieldname": "additional_amount", + "fieldtype": "Currency", + "hidden": 1, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Additional Amount", + "length": 0, + "no_copy": 1, + "permlevel": 0, + "precision": "", + "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 + }, { "allow_bulk_edit": 0, "allow_in_quick_entry": 0, @@ -713,7 +746,7 @@ "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2019-04-16 19:09:31.726597", + "modified": "2019-05-11 17:33:08.508653", "modified_by": "Administrator", "module": "HR", "name": "Salary Detail", diff --git a/erpnext/hr/doctype/salary_slip/salary_slip.js b/erpnext/hr/doctype/salary_slip/salary_slip.js index 4e9fcce8982..f430eeed4ee 100644 --- a/erpnext/hr/doctype/salary_slip/salary_slip.js +++ b/erpnext/hr/doctype/salary_slip/salary_slip.js @@ -11,7 +11,7 @@ frappe.ui.form.on("Salary Slip", { {fieldname: 'salary_component', columns: 6}, {fieldname: 'amount', columns: 4} ]; - }) + }); frm.fields_dict["timesheets"].grid.get_field("time_sheet").get_query = function(){ return { @@ -19,31 +19,39 @@ frappe.ui.form.on("Salary Slip", { employee: frm.doc.employee } } - } + }; + frm.set_query("salary_component", "earnings", function() { return { filters: { type: "earning" } } - }) + }); + frm.set_query("salary_component", "deductions", function() { return { filters: { type: "deduction" } } - }) + }); + + frm.set_query("employee", function() { + return{ + query: "erpnext.controllers.queries.employee_query" + } + }); }, - start_date: function(frm, dt, dn){ + start_date: function(frm){ if(frm.doc.start_date){ frm.trigger("set_end_date"); } }, - end_date: function(frm, dt, dn) { - get_emp_and_leave_details(frm.doc, dt, dn); + end_date: function(frm) { + frm.events.get_emp_and_leave_details(frm); }, set_end_date: function(frm){ @@ -70,43 +78,54 @@ frappe.ui.form.on("Salary Slip", { refresh: function(frm) { frm.trigger("toggle_fields") - frm.trigger("toggle_reqd_fields") - var salary_detail_fields = ["formula", "abbr", "statistical_component", "is_tax_applicable", - "is_flexible_benefit", "variable_based_on_taxable_salary", "is_additional_component"] + + var salary_detail_fields = ["formula", "abbr", "statistical_component", "variable_based_on_taxable_salary"]; cur_frm.fields_dict['earnings'].grid.set_column_disp(salary_detail_fields,false); cur_frm.fields_dict['deductions'].grid.set_column_disp(salary_detail_fields,false); }, - salary_slip_based_on_timesheet: function(frm, dt, dn) { + salary_slip_based_on_timesheet: function(frm) { frm.trigger("toggle_fields"); - get_emp_and_leave_details(frm.doc, dt, dn); + frm.events.get_emp_and_leave_details(frm); }, - payroll_frequency: function(frm, dt, dn) { + payroll_frequency: function(frm) { frm.trigger("toggle_fields"); frm.set_value('end_date', ''); }, - employee: function(frm, dt, dn) { - get_emp_and_leave_details(frm.doc, dt, dn); + employee: function(frm) { + frm.events.get_emp_and_leave_details(frm); + }, + + leave_without_pay: function(frm){ + if (frm.doc.employee && frm.doc.start_date && frm.doc.end_date) { + return frappe.call({ + method: 'process_salary_based_on_leave', + doc: frm.doc, + args: {"lwp": frm.doc.leave_without_pay}, + callback: function(r, rt) { + frm.refresh(); + } + }); + } }, toggle_fields: function(frm) { - frm.toggle_display(['hourly_wages', 'timesheets'], - cint(frm.doc.salary_slip_based_on_timesheet)==1); + frm.toggle_display(['hourly_wages', 'timesheets'], cint(frm.doc.salary_slip_based_on_timesheet)===1); frm.toggle_display(['payment_days', 'total_working_days', 'leave_without_pay'], frm.doc.payroll_frequency!=""); - } - -}) - -frappe.ui.form.on('Salary Detail', { - earnings_remove: function(frm, dt, dn) { - calculate_all(frm.doc, dt, dn); }, - deductions_remove: function(frm, dt, dn) { - calculate_all(frm.doc, dt, dn); + + get_emp_and_leave_details: function(frm) { + return frappe.call({ + method: 'get_emp_and_leave_details', + doc: frm.doc, + callback: function(r, rt) { + frm.refresh(); + } + }); } }) @@ -119,133 +138,29 @@ frappe.ui.form.on('Salary Slip Timesheet', { } }); -// Get leave details -//--------------------------------------------------------------------- -var get_emp_and_leave_details = function(doc, dt, dn) { - return frappe.call({ - method: 'get_emp_and_leave_details', - doc: locals[dt][dn], - callback: function(r, rt) { - cur_frm.refresh(); - calculate_all(doc, dt, dn); - } - }); -} - - -cur_frm.cscript.leave_without_pay = function(doc,dt,dn){ - if (doc.employee && doc.start_date && doc.end_date) { - return $c_obj(doc, 'get_leave_details', {"lwp": doc.leave_without_pay}, function(r, rt) { - var doc = locals[dt][dn]; - cur_frm.refresh(); - calculate_all(doc, dt, dn); - }); - } -} - -var calculate_all = function(doc, dt, dn) { - calculate_earning_total(doc, dt, dn); - calculate_ded_total(doc, dt, dn); - calculate_net_pay(doc, dt, dn); -} - -cur_frm.cscript.amount = function(doc,dt,dn){ - var child = locals[dt][dn]; - if(!doc.salary_structure){ - frappe.model.set_value(dt,dn, "default_amount", child.amount) - } - calculate_all(doc, dt, dn); -} - -cur_frm.cscript.depends_on_payment_days = function(doc,dt,dn){ - calculate_earning_total(doc, dt, dn, true); - calculate_ded_total(doc, dt, dn, true); - calculate_net_pay(doc, dt, dn); - refresh_many(['amount','gross_pay', 'rounded_total', 'net_pay', 'loan_repayment']); -}; - -// Calculate earning total -// ------------------------------------------------------------------------ -var calculate_earning_total = function(doc, dt, dn, reset_amount) { - - var tbl = doc.earnings || []; - var total_earn = 0; - for(var i = 0; i < tbl.length; i++){ - if(cint(tbl[i].depends_on_payment_days) == 1) { - tbl[i].amount = Math.round(tbl[i].default_amount)*(flt(doc.payment_days) / - cint(doc.total_working_days)*100)/100; - } else if(reset_amount && tbl[i].default_amount) { - tbl[i].amount = tbl[i].default_amount; - } - if(!tbl[i].do_not_include_in_total) { - total_earn += flt(tbl[i].amount); - - } - } - doc.gross_pay = total_earn; - refresh_many(['earnings', 'amount','gross_pay']); - -} - -// Calculate deduction total -// ------------------------------------------------------------------------ -var calculate_ded_total = function(doc, dt, dn, reset_amount) { - var tbl = doc.deductions || []; - var total_ded = 0; - for(var i = 0; i < tbl.length; i++){ - if(cint(tbl[i].depends_on_payment_days) == 1) { - tbl[i].amount = Math.round(tbl[i].default_amount)*(flt(doc.payment_days)/cint(doc.total_working_days)*100)/100; - } else if(reset_amount && tbl[i].default_amount) { - tbl[i].amount = tbl[i].default_amount; - } - if(!tbl[i].do_not_include_in_total) { - total_ded += flt(tbl[i].amount); - } - } - doc.total_deduction = total_ded; - refresh_many(['deductions', 'total_deduction']); -} - -var calculate_net_pay = function(doc, dt, dn) { - doc.net_pay = flt(doc.gross_pay) - flt(doc.total_deduction); - doc.rounded_total = Math.round(doc.net_pay); - refresh_many(['net_pay', 'rounded_total']); -} - -cur_frm.cscript.validate = function(doc, dt, dn) { - calculate_all(doc, dt, dn); -} - -cur_frm.fields_dict.employee.get_query = function(doc,cdt,cdn) { - return{ - query: "erpnext.controllers.queries.employee_query" - } -} - // calculate total working hours, earnings based on hourly wages and totals -// ------------------------------------------------------------------------ var total_work_hours = function(frm, dt, dn) { - frm.set_value('total_working_hours', 0); - + var total_working_hours = 0.0; $.each(frm.doc["timesheets"] || [], function(i, timesheet) { - frm.doc.total_working_hours += timesheet.working_hours; + total_working_hours += timesheet.working_hours; }); - frm.refresh_field('total_working_hours'); + frm.set_value('total_working_hours', total_working_hours); var wages_amount = frm.doc.total_working_hours * frm.doc.hour_rate; frappe.db.get_value('Salary Structure', {'name': frm.doc.salary_structure}, 'salary_component', (r) => { - frm.set_value('gross_pay', 0); - + var gross_pay = 0.0; $.each(frm.doc["earnings"], function(i, earning) { if (earning.salary_component == r.salary_component) { earning.amount = wages_amount; frm.refresh_fields('earnings'); } - frm.doc.gross_pay += earning.amount; + gross_pay += earning.amount; }); + frm.set_value('gross_pay', gross_pay); - frm.refresh_field('gross_pay'); - calculate_net_pay(frm.doc, dt, dn); + frm.doc.net_pay = flt(frm.doc.gross_pay) - flt(frm.doc.total_deduction); + frm.doc.rounded_total = Math.round(frm.doc.net_pay); + refresh_many(['net_pay', 'rounded_total']); }); } diff --git a/erpnext/hr/doctype/salary_slip/salary_slip.json b/erpnext/hr/doctype/salary_slip/salary_slip.json index dd4451028eb..a5c6280c64e 100644 --- a/erpnext/hr/doctype/salary_slip/salary_slip.json +++ b/erpnext/hr/doctype/salary_slip/salary_slip.json @@ -2,7 +2,7 @@ "allow_copy": 0, "allow_events_in_timeline": 0, "allow_guest_to_view": 0, - "allow_import": 1, + "allow_import": 0, "allow_rename": 0, "beta": 0, "creation": "2013-01-10 16:34:15", @@ -1042,73 +1042,6 @@ "translatable": 0, "unique": 0 }, - { - "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_01", - "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 - }, - { - "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": 1, - "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, - "oldfieldname": "amended_from", - "oldfieldtype": "Data", - "options": "Salary Slip", - "permlevel": 0, - "print_hide": 1, - "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, @@ -1950,6 +1883,41 @@ "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, + "fetch_if_empty": 0, + "fieldname": "amended_from", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 1, + "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, + "oldfieldname": "amended_from", + "oldfieldtype": "Data", + "options": "Salary Slip", + "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 } ], "has_web_view": 0, @@ -1963,7 +1931,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2019-05-08 20:16:21.549386", + "modified": "2019-05-13 13:10:14.524119", "modified_by": "Administrator", "module": "HR", "name": "Salary Slip", diff --git a/erpnext/hr/doctype/salary_slip/salary_slip.py b/erpnext/hr/doctype/salary_slip/salary_slip.py index bbfca7db681..62ed17aa555 100644 --- a/erpnext/hr/doctype/salary_slip/salary_slip.py +++ b/erpnext/hr/doctype/salary_slip/salary_slip.py @@ -3,7 +3,7 @@ from __future__ import unicode_literals import frappe, erpnext -import datetime +import datetime, math from frappe.utils import add_days, cint, cstr, flt, getdate, rounded, date_diff, money_in_words, getdate from frappe.model.naming import make_autoname @@ -14,7 +14,7 @@ from erpnext.hr.doctype.employee.employee import get_holiday_list_for_employee from erpnext.utilities.transaction_base import TransactionBase from frappe.utils.background_jobs import enqueue from erpnext.hr.doctype.additional_salary.additional_salary import get_additional_salary_component -from erpnext.hr.utils import get_payroll_period +from erpnext.hr.doctype.payroll_period.payroll_period import get_period_factor, get_payroll_period from erpnext.hr.doctype.employee_benefit_application.employee_benefit_application import get_benefit_component_amount from erpnext.hr.doctype.employee_benefit_claim.employee_benefit_claim import get_benefit_claim_amount, get_last_payroll_period_benefits @@ -47,7 +47,6 @@ class SalarySlip(TransactionBase): else: self.get_leave_details(lwp = self.leave_without_pay) - # if self.salary_slip_based_on_timesheet or not self.net_pay: self.calculate_net_pay() company_currency = erpnext.get_company_currency(self.company) @@ -59,148 +58,57 @@ class SalarySlip(TransactionBase): frappe.msgprint(_("Total working hours should not be greater than max working hours {0}"). format(max_working_hours), alert=True) + def on_submit(self): + if self.net_pay < 0: + frappe.throw(_("Net Pay cannot be less than 0")) + else: + self.set_status() + self.update_status(self.name) + self.update_salary_slip_in_additional_salary() + if (frappe.db.get_single_value("HR Settings", "email_salary_slip_to_employee")) and not frappe.flags.via_payroll_entry: + self.email_salary_slip() + + def on_cancel(self): + self.set_status() + self.update_status() + self.update_salary_slip_in_additional_salary() + + def on_trash(self): + from frappe.model.naming import revert_series_if_last + revert_series_if_last(self.series, self.name) + + def get_status(self): + if self.docstatus == 0: + status = "Draft" + elif self.docstatus == 1: + status = "Submitted" + elif self.docstatus == 2: + status = "Cancelled" + return status + def validate_dates(self): if date_diff(self.end_date, self.start_date) < 0: frappe.throw(_("To date cannot be before From date")) - def calculate_component_amounts(self): - if not getattr(self, '_salary_structure_doc', None): - self._salary_structure_doc = frappe.get_doc('Salary Structure', self.salary_structure) - - data = self.get_data_for_eval() - - for key in ('earnings', 'deductions'): - for struct_row in self._salary_structure_doc.get(key): - amount = self.eval_condition_and_formula(struct_row, data) - if amount and struct_row.statistical_component == 0: - self.update_component_row(struct_row, amount, key) - - if key=="earnings" and struct_row.is_flexible_benefit == 1: - self.add_employee_flexi_benefits(struct_row) - - additional_components = get_additional_salary_component(self.employee, self.start_date, self.end_date) - if additional_components: - for additional_component in additional_components: - additional_component = frappe._dict(additional_component) - amount = additional_component.amount - overwrite = additional_component.overwrite - key = "earnings" - if additional_component.type == "Deduction": - key = "deductions" - self.update_component_row(frappe._dict(additional_component.struct_row), amount, key, overwrite=overwrite) - - self.get_last_payroll_period_benefit() - - # Calculate variable_based_on_taxable_salary after all components updated in salary slip - for struct_row in self._salary_structure_doc.get("deductions"): - if struct_row.variable_based_on_taxable_salary == 1 and not struct_row.formula and not struct_row.amount: - tax_detail = self.calculate_variable_based_on_taxable_salary(struct_row.salary_component) - if tax_detail and tax_detail[1]: - self.update_component_row(frappe._dict(tax_detail[0]), tax_detail[1], "deductions", tax_detail[2], tax_detail[3]) - - def get_last_payroll_period_benefit(self): - payroll_period = get_payroll_period(self.start_date, self.end_date, self.company) - if payroll_period: - # Check for last payroll period - if (getdate(payroll_period.end_date) <= getdate(self.end_date)): - current_flexi_amount = 0 - for d in self.get("earnings"): - if d.is_flexible_benefit == 1: - current_flexi_amount += d.amount - last_benefits = get_last_payroll_period_benefits(self.employee, self.start_date, self.end_date, - current_flexi_amount, payroll_period, self._salary_structure_doc) - if last_benefits: - for last_benefit in last_benefits: - last_benefit = frappe._dict(last_benefit) - amount = last_benefit.amount - self.update_component_row(frappe._dict(last_benefit.struct_row), amount, "earnings") - - def add_employee_flexi_benefits(self, struct_row): - if frappe.db.get_value("Salary Component", struct_row.salary_component, "pay_against_benefit_claim") != 1: - benefit_component_amount = get_benefit_component_amount(self.employee, self.start_date, self.end_date, \ - struct_row, self._salary_structure_doc, self.total_working_days, self.payroll_frequency) - if benefit_component_amount: - self.update_component_row(struct_row, benefit_component_amount, "earnings") + def check_existing(self): + if not self.salary_slip_based_on_timesheet: + ret_exist = frappe.db.sql("""select name from `tabSalary Slip` + where start_date = %s and end_date = %s and docstatus != 2 + and employee = %s and name != %s""", + (self.start_date, self.end_date, self.employee, self.name)) + if ret_exist: + self.employee = '' + frappe.throw(_("Salary Slip of employee {0} already created for this period").format(self.employee)) else: - benefit_claim_amount = get_benefit_claim_amount(self.employee, self.start_date, self.end_date, struct_row.salary_component) - if benefit_claim_amount: - self.update_component_row(struct_row, benefit_claim_amount, "earnings") + for data in self.timesheets: + if frappe.db.get_value('Timesheet', data.time_sheet, 'status') == 'Payrolled': + frappe.throw(_("Salary Slip of employee {0} already created for time sheet {1}").format(self.employee, data.time_sheet)) - def update_component_row(self, struct_row, amount, key, benefit_tax=None, additional_tax=None, overwrite=1): - component_row = None - for d in self.get(key): - if d.salary_component == struct_row.salary_component: - component_row = d - - if not component_row: - self.append(key, { - 'amount': amount, - 'default_amount': amount, - 'depends_on_payment_days' : struct_row.depends_on_payment_days, - 'salary_component' : struct_row.salary_component, - 'abbr' : struct_row.abbr, - 'do_not_include_in_total' : struct_row.do_not_include_in_total, - 'is_tax_applicable': struct_row.is_tax_applicable, - 'is_flexible_benefit': struct_row.is_flexible_benefit, - 'variable_based_on_taxable_salary': struct_row.variable_based_on_taxable_salary, - 'is_additional_component': struct_row.is_additional_component, - 'tax_on_flexible_benefit': benefit_tax, - 'tax_on_additional_salary': additional_tax - }) - else: - if not overwrite: - amount += struct_row.get("default_amount", 0) - - component_row.default_amount = amount - component_row.amount = amount - - component_row.tax_on_flexible_benefit = benefit_tax - component_row.tax_on_additional_salary = additional_tax - - def eval_condition_and_formula(self, d, data): - try: - condition = d.condition.strip() if d.condition else None - if condition: - if not frappe.safe_eval(condition, self.whitelisted_globals, data): - return None - amount = d.amount - if d.amount_based_on_formula: - formula = d.formula.strip() if d.formula else None - if formula: - amount = rounded(frappe.safe_eval(formula, self.whitelisted_globals, data)) - if amount: - data[d.abbr] = amount - - return amount - - except NameError as err: - frappe.throw(_("Name error: {0}".format(err))) - except SyntaxError as err: - frappe.throw(_("Syntax error in formula or condition: {0}".format(err))) - except Exception as e: - frappe.throw(_("Error in formula or condition: {0}".format(e))) - raise - - def get_data_for_eval(self): - '''Returns data for evaluating formula''' - data = frappe._dict() - - data.update(frappe.get_doc("Salary Structure Assignment", - {"employee": self.employee, "salary_structure": self.salary_structure}).as_dict()) - - data.update(frappe.get_doc("Employee", self.employee).as_dict()) - data.update(self.as_dict()) - - # set values for components - salary_components = frappe.get_all("Salary Component", fields=["salary_component_abbr"]) - for sc in salary_components: - data.setdefault(sc.salary_component_abbr, 0) - - for key in ('earnings', 'deductions'): - for d in self.get(key): - data[d.abbr] = d.amount - - return data + def get_date_details(self): + if not self.end_date: + date_details = get_start_end_dates(self.payroll_frequency, self.start_date or self.posting_date) + self.start_date = date_details.start_date + self.end_date = date_details.end_date def get_emp_and_leave_details(self): '''First time, load all the components from salary structure''' @@ -235,12 +143,6 @@ class SalarySlip(TransactionBase): 'working_hours': data.total_hours }) - def get_date_details(self): - if not self.end_date: - date_details = get_start_end_dates(self.payroll_frequency, self.start_date or self.posting_date) - self.start_date = date_details.start_date - self.end_date = date_details.end_date - def check_sal_struct(self, joining_date, relieving_date): cond = """and sa.employee=%(employee)s and (sa.from_date <= %(start_date)s or sa.from_date <= %(end_date)s or sa.from_date <= %(joining_date)s)""" @@ -279,43 +181,18 @@ class SalarySlip(TransactionBase): make_salary_slip(self._salary_structure_doc.name, self) - def process_salary_structure(self): - '''Calculate salary after salary structure details have been updated''' - if not self.salary_slip_based_on_timesheet: - self.get_date_details() - self.pull_emp_details() - self.get_leave_details() - self.calculate_net_pay() - - def add_earning_for_hourly_wages(self, doc, salary_component, amount): - row_exists = False - for row in doc.earnings: - if row.salary_component == salary_component: - row.amount = amount - row_exists = True - break - - if not row_exists: - wages_row = { - "salary_component": salary_component, - "abbr": frappe.db.get_value("Salary Component", salary_component, "salary_component_abbr"), - "amount": self.hour_rate * self.total_working_hours - } - doc.append('earnings', wages_row) - - def pull_emp_details(self): - emp = frappe.db.get_value("Employee", self.employee, ["bank_name", "bank_ac_no"], as_dict=1) - if emp: - self.bank_name = emp.bank_name - self.bank_account_no = emp.bank_ac_no - - def get_leave_details(self, joining_date=None, relieving_date=None, lwp=None): + def get_leave_details(self, joining_date=None, relieving_date=None, lwp=None, for_preview=0): if not joining_date: joining_date, relieving_date = frappe.db.get_value("Employee", self.employee, ["date_of_joining", "relieving_date"]) - holidays = self.get_holidays_for_employee(self.start_date, self.end_date) working_days = date_diff(self.end_date, self.start_date) + 1 + if for_preview: + self.total_working_days = working_days + self.payment_days = working_days + return + + holidays = self.get_holidays_for_employee(self.start_date, self.end_date) actual_lwp = self.calculate_lwp(holidays, working_days) if not cint(frappe.db.get_value("HR Settings", None, "include_holidays_in_total_working_days")): working_days -= len(holidays) @@ -392,21 +269,422 @@ class SalarySlip(TransactionBase): lwp = cint(leave[0][1]) and (lwp + 0.5) or (lwp + 1) return lwp - def check_existing(self): - if not self.salary_slip_based_on_timesheet: - ret_exist = frappe.db.sql("""select name from `tabSalary Slip` - where start_date = %s and end_date = %s and docstatus != 2 - and employee = %s and name != %s""", - (self.start_date, self.end_date, self.employee, self.name)) - if ret_exist: - self.employee = '' - frappe.throw(_("Salary Slip of employee {0} already created for this period").format(self.employee)) - else: - for data in self.timesheets: - if frappe.db.get_value('Timesheet', data.time_sheet, 'status') == 'Payrolled': - frappe.throw(_("Salary Slip of employee {0} already created for time sheet {1}").format(self.employee, data.time_sheet)) + def add_earning_for_hourly_wages(self, doc, salary_component, amount): + row_exists = False + for row in doc.earnings: + if row.salary_component == salary_component: + row.amount = amount + row_exists = True + break - def sum_components(self, component_type, total_field, precision): + if not row_exists: + wages_row = { + "salary_component": salary_component, + "abbr": frappe.db.get_value("Salary Component", salary_component, "salary_component_abbr"), + "amount": self.hour_rate * self.total_working_hours + } + doc.append('earnings', wages_row) + + def calculate_net_pay(self): + if self.salary_structure: + self.calculate_component_amounts() + + self.gross_pay = self.get_component_totals("earnings") + self.total_deduction = self.get_component_totals("deductions") + + self.set_loan_repayment() + + self.net_pay = flt(self.gross_pay) - (flt(self.total_deduction) + flt(self.total_loan_repayment)) + self.rounded_total = rounded(self.net_pay) + + if self.net_pay < 0: + frappe.throw(_("Net Pay cannnot be negative")) + + def calculate_component_amounts(self): + if not getattr(self, '_salary_structure_doc', None): + self._salary_structure_doc = frappe.get_doc('Salary Structure', self.salary_structure) + + payroll_period = get_payroll_period(self.start_date, self.end_date, self.company) + + self.add_structure_components() + self.add_employee_benefits(payroll_period) + self.add_additional_salary_components() + self.add_tax_components(payroll_period) + + def add_structure_components(self): + data = self.get_data_for_eval() + for key in ('earnings', 'deductions'): + for struct_row in self._salary_structure_doc.get(key): + amount = self.eval_condition_and_formula(struct_row, data) + if amount and struct_row.statistical_component == 0: + self.update_component_row(struct_row, amount, key) + + def get_data_for_eval(self): + '''Returns data for evaluating formula''' + data = frappe._dict() + + data.update(frappe.get_doc("Salary Structure Assignment", + {"employee": self.employee, "salary_structure": self.salary_structure}).as_dict()) + + data.update(frappe.get_doc("Employee", self.employee).as_dict()) + data.update(self.as_dict()) + + # set values for components + salary_components = frappe.get_all("Salary Component", fields=["salary_component_abbr"]) + for sc in salary_components: + data.setdefault(sc.salary_component_abbr, 0) + + for key in ('earnings', 'deductions'): + for d in self.get(key): + data[d.abbr] = d.amount + + return data + + def eval_condition_and_formula(self, d, data): + try: + condition = d.condition.strip() if d.condition else None + if condition: + if not frappe.safe_eval(condition, self.whitelisted_globals, data): + return None + amount = d.amount + if d.amount_based_on_formula: + formula = d.formula.strip() if d.formula else None + if formula: + amount = flt(frappe.safe_eval(formula, self.whitelisted_globals, data), d.precision("amount")) + if amount: + data[d.abbr] = amount + + return amount + + except NameError as err: + frappe.throw(_("Name error: {0}".format(err))) + except SyntaxError as err: + frappe.throw(_("Syntax error in formula or condition: {0}".format(err))) + except Exception as e: + frappe.throw(_("Error in formula or condition: {0}".format(e))) + raise + + def add_employee_benefits(self, payroll_period): + for struct_row in self._salary_structure_doc.get("earnings"): + if struct_row.is_flexible_benefit == 1: + if frappe.db.get_value("Salary Component", struct_row.salary_component, "pay_against_benefit_claim") != 1: + benefit_component_amount = get_benefit_component_amount(self.employee, self.start_date, self.end_date, + struct_row.salary_component, self._salary_structure_doc, self.payroll_frequency, payroll_period) + if benefit_component_amount: + self.update_component_row(struct_row, benefit_component_amount, "earnings") + else: + benefit_claim_amount = get_benefit_claim_amount(self.employee, self.start_date, self.end_date, struct_row.salary_component) + if benefit_claim_amount: + self.update_component_row(struct_row, benefit_claim_amount, "earnings") + + self.adjust_benefits_in_last_payroll_period(payroll_period) + + def adjust_benefits_in_last_payroll_period(self, payroll_period): + if payroll_period: + if (getdate(payroll_period.end_date) <= getdate(self.end_date)): + last_benefits = get_last_payroll_period_benefits(self.employee, self.start_date, self.end_date, + payroll_period, self._salary_structure_doc) + if last_benefits: + for last_benefit in last_benefits: + last_benefit = frappe._dict(last_benefit) + amount = last_benefit.amount + self.update_component_row(frappe._dict(last_benefit.struct_row), amount, "earnings") + + def add_additional_salary_components(self): + additional_components = get_additional_salary_component(self.employee, self.start_date, self.end_date) + if additional_components: + for additional_component in additional_components: + amount = additional_component.amount + overwrite = additional_component.overwrite + key = "earnings" if additional_component.type == "Earning" else "deductions" + self.update_component_row(frappe._dict(additional_component.struct_row), amount, key, overwrite=overwrite) + + def add_tax_components(self, payroll_period): + # Calculate variable_based_on_taxable_salary after all components updated in salary slip + struct_tax_components = [d.salary_component for d in self._salary_structure_doc.get("deductions") + if d.variable_based_on_taxable_salary == 1 and not d.formula and not d.amount] + + if not struct_tax_components: + struct_tax_components = [d.name for d in + frappe.get_all("Salary Component", filters={"variable_based_on_taxable_salary": 1})] + + for d in struct_tax_components: + tax_amount = self.calculate_variable_based_on_taxable_salary(d, payroll_period) + tax_row = self.get_salary_slip_row(d) + self.update_component_row(tax_row, tax_amount, "deductions") + + def update_component_row(self, struct_row, amount, key, overwrite=1): + component_row = None + for d in self.get(key): + if d.salary_component == struct_row.salary_component: + component_row = d + + if not component_row: + if amount: + self.append(key, { + 'amount': amount, + 'default_amount': amount if not struct_row.get("is_additional_component") else 0, + 'depends_on_payment_days' : struct_row.depends_on_payment_days, + 'salary_component' : struct_row.salary_component, + 'abbr' : struct_row.abbr, + 'do_not_include_in_total' : struct_row.do_not_include_in_total, + 'is_tax_applicable': struct_row.is_tax_applicable, + 'is_flexible_benefit': struct_row.is_flexible_benefit, + 'variable_based_on_taxable_salary': struct_row.variable_based_on_taxable_salary, + 'deduct_full_tax_on_selected_payroll_date': struct_row.deduct_full_tax_on_selected_payroll_date, + 'additional_amount': amount if struct_row.get("is_additional_component") else 0 + }) + else: + if struct_row.get("is_additional_component"): + if overwrite: + component_row.additional_amount = amount - component_row.get("default_amount", 0) + else: + component_row.additional_amount = amount + + if not overwrite: + amount += component_row.default_amount + + component_row.amount = amount + component_row.deduct_full_tax_on_selected_payroll_date = struct_row.deduct_full_tax_on_selected_payroll_date + + def calculate_variable_based_on_taxable_salary(self, tax_component, payroll_period): + if not payroll_period: + frappe.msgprint(_("Start and end dates not in a valid Payroll Period, cannot calculate {0}.") + .format(tax_component)) + return + + # Deduct taxes forcefully for unsubmitted tax exemption proof and unclaimed benefits in the last period + if payroll_period.end_date <= getdate(self.end_date): + self.deduct_tax_for_unsubmitted_tax_exemption_proof = 1 + self.deduct_tax_for_unclaimed_employee_benefits = 1 + + return self.calculate_variable_tax(payroll_period, tax_component) + + def calculate_variable_tax(self, payroll_period, tax_component): + # get remaining numbers of sub-period (period for which one salary is processed) + remaining_sub_periods = get_period_factor(self.employee, + self.start_date, self.end_date, self.payroll_frequency, payroll_period)[1] + + # get taxable_earnings, paid_taxes for previous period + previous_taxable_earnings = self.get_taxable_earnings_for_prev_period(payroll_period.start_date, self.start_date) + previous_total_paid_taxes = self.get_tax_paid_in_period(payroll_period.start_date, self.start_date, tax_component) + + # get taxable_earnings for current period (all days) + current_taxable_earnings = self.get_taxable_earnings() + future_structured_taxable_earnings = current_taxable_earnings.taxable_earnings * (math.ceil(remaining_sub_periods) - 1) + + # get taxable_earnings, addition_earnings for current actual payment days + self.set_component_amounts_based_on_payment_days() + current_taxable_earnings_for_payment_days = self.get_taxable_earnings() + current_structured_taxable_earnings = current_taxable_earnings_for_payment_days.taxable_earnings + current_additional_earnings = current_taxable_earnings_for_payment_days.additional_income + current_additional_earnings_with_full_tax = current_taxable_earnings_for_payment_days.additional_income_with_full_tax + + # Get taxable unclaimed benefits + unclaimed_taxable_benefits = 0 + if self.deduct_tax_for_unclaimed_employee_benefits: + unclaimed_taxable_benefits = self.calculate_unclaimed_taxable_benefits(payroll_period) + unclaimed_taxable_benefits += current_taxable_earnings_for_payment_days.flexi_benefits + + # Total exemption amount based on tax exemption declaration + total_exemption_amount, other_incomes = self.get_total_exemption_amount_and_other_incomes(payroll_period) + + # Total taxable earnings including additional and other incomes + total_taxable_earnings = previous_taxable_earnings + current_structured_taxable_earnings + future_structured_taxable_earnings \ + + current_additional_earnings + other_incomes + unclaimed_taxable_benefits - total_exemption_amount + + # Total taxable earnings without additional earnings with full tax + total_taxable_earnings_without_full_tax_addl_components = total_taxable_earnings - current_additional_earnings_with_full_tax + + # Structured tax amount + total_structured_tax_amount = self.calculate_tax_by_tax_slab(payroll_period, total_taxable_earnings_without_full_tax_addl_components) + + current_structured_tax_amount = (total_structured_tax_amount - previous_total_paid_taxes) / remaining_sub_periods + + # Total taxable earnings with additional earnings with full tax + full_tax_on_additional_earnings = 0.0 + if current_additional_earnings_with_full_tax: + total_tax_amount = self.calculate_tax_by_tax_slab(payroll_period, total_taxable_earnings) + full_tax_on_additional_earnings = total_tax_amount - total_structured_tax_amount + + current_tax_amount = current_structured_tax_amount + full_tax_on_additional_earnings + if flt(current_tax_amount) < 0: + current_tax_amount = 0 + + return current_tax_amount + + def get_taxable_earnings_for_prev_period(self, start_date, end_date): + taxable_earnings = frappe.db.sql(""" + select sum(sd.amount) + from + `tabSalary Detail` sd join `tabSalary Slip` ss on sd.parent=ss.name + where + sd.parentfield='earnings' + and sd.is_tax_applicable=1 + and is_flexible_benefit=0 + and ss.docstatus=1 + and ss.employee=%(employee)s + and ss.start_date between %(from_date)s and %(to_date)s + and ss.end_date between %(from_date)s and %(to_date)s + """, { + "employee": self.employee, + "from_date": start_date, + "to_date": end_date + }) + return flt(taxable_earnings[0][0]) if taxable_earnings else 0 + + def get_tax_paid_in_period(self, start_date, end_date, tax_component): + # find total_tax_paid, tax paid for benefit, additional_salary + total_tax_paid = flt(frappe.db.sql(""" + select + sum(sd.amount) + from + `tabSalary Detail` sd join `tabSalary Slip` ss on sd.parent=ss.name + where + sd.parentfield='deductions' + and sd.salary_component=%(salary_component)s + and sd.variable_based_on_taxable_salary=1 + and ss.docstatus=1 + and ss.employee=%(employee)s + and ss.start_date between %(from_date)s and %(to_date)s + and ss.end_date between %(from_date)s and %(to_date)s + """, { + "salary_component": tax_component, + "employee": self.employee, + "from_date": start_date, + "to_date": end_date + })[0][0]) + + return total_tax_paid + + def get_taxable_earnings(self, only_flexi=0): + taxable_earnings = 0 + additional_income = 0 + additional_income_with_full_tax = 0 + flexi_benefits = 0 + + for earning in self.earnings: + if earning.is_tax_applicable: + if flt(earning.additional_amount): + taxable_earnings += (earning.amount - earning.additional_amount) + additional_income += earning.additional_amount + if earning.deduct_full_tax_on_selected_payroll_date: + additional_income_with_full_tax += earning.additional_amount + continue + + if earning.is_flexible_benefit: + flexi_benefits += earning.amount + else: + taxable_earnings += earning.amount + + return frappe._dict({ + "taxable_earnings": taxable_earnings, + "additional_income": additional_income, + "additional_income_with_full_tax": additional_income_with_full_tax, + "flexi_benefits": flexi_benefits + }) + + def calculate_unclaimed_taxable_benefits(self, payroll_period): + # get total sum of benefits paid + total_benefits_paid = flt(frappe.db.sql(""" + select sum(sd.amount) + from `tabSalary Detail` sd join `tabSalary Slip` ss on sd.parent=ss.name + where + sd.parentfield='earnings' + and sd.is_tax_applicable=1 + and is_flexible_benefit=1 + and ss.docstatus=1 + and ss.employee=%(employee)s + and ss.start_date between %(start_date)s and %(end_date)s + and ss.end_date between %(start_date)s and %(end_date)s + """, { + "employee": self.employee, + "start_date": payroll_period.start_date, + "end_date": self.start_date + })[0][0]) + + # get total benefits claimed + total_benefits_claimed = flt(frappe.db.sql(""" + select sum(claimed_amount) + from `tabEmployee Benefit Claim` + where + docstatus=1 + and employee=%s + and claim_date between %s and %s + """, (self.employee, payroll_period.start_date, self.end_date))[0][0]) + + return total_benefits_paid - total_benefits_claimed + + def get_total_exemption_amount_and_other_incomes(self, payroll_period): + total_exemption_amount, other_incomes = 0, 0 + if self.deduct_tax_for_unsubmitted_tax_exemption_proof: + exemption_proof = frappe.db.get_value("Employee Tax Exemption Proof Submission", + {"employee": self.employee, "payroll_period": payroll_period.name, "docstatus": 1}, + ["exemption_amount", "income_from_other_sources"]) + if exemption_proof: + total_exemption_amount, other_incomes = exemption_proof + else: + declaration = frappe.db.get_value("Employee Tax Exemption Declaration", + {"employee": self.employee, "payroll_period": payroll_period.name, "docstatus": 1}, + ["total_exemption_amount", "income_from_other_sources"]) + if declaration: + total_exemption_amount, other_incomes = declaration + + return total_exemption_amount, other_incomes + + def calculate_tax_by_tax_slab(self, payroll_period, annual_taxable_earning): + payroll_period_obj = frappe.get_doc("Payroll Period", payroll_period) + annual_taxable_earning -= flt(payroll_period_obj.standard_tax_exemption_amount) + data = self.get_data_for_eval() + data.update({"annual_taxable_earning": annual_taxable_earning}) + taxable_amount = 0 + for slab in payroll_period_obj.taxable_salary_slabs: + if slab.condition and not self.eval_tax_slab_condition(slab.condition, data): + continue + if not slab.to_amount and annual_taxable_earning > slab.from_amount: + taxable_amount += (annual_taxable_earning - slab.from_amount) * slab.percent_deduction *.01 + continue + if annual_taxable_earning > slab.from_amount and annual_taxable_earning < slab.to_amount: + taxable_amount += (annual_taxable_earning - slab.from_amount) * slab.percent_deduction *.01 + elif annual_taxable_earning > slab.from_amount and annual_taxable_earning > slab.to_amount: + taxable_amount += (slab.to_amount - slab.from_amount) * slab.percent_deduction * .01 + return taxable_amount + + def eval_tax_slab_condition(self, condition, data): + try: + condition = condition.strip() + if condition: + return frappe.safe_eval(condition, self.whitelisted_globals, data) + except NameError as err: + frappe.throw(_("Name error: {0}".format(err))) + except SyntaxError as err: + frappe.throw(_("Syntax error in condition: {0}".format(err))) + except Exception as e: + frappe.throw(_("Error in formula or condition: {0}".format(e))) + raise + + def get_salary_slip_row(self, salary_component): + component = frappe.get_doc("Salary Component", salary_component) + # Data for update_component_row + struct_row = frappe._dict() + struct_row['depends_on_payment_days'] = component.depends_on_payment_days + struct_row['salary_component'] = component.name + struct_row['abbr'] = component.salary_component_abbr + struct_row['do_not_include_in_total'] = component.do_not_include_in_total + struct_row['is_tax_applicable'] = component.is_tax_applicable + struct_row['is_flexible_benefit'] = component.is_flexible_benefit + struct_row['variable_based_on_taxable_salary'] = component.variable_based_on_taxable_salary + return struct_row + + def get_component_totals(self, component_type): + total = 0.0 + for d in self.get(component_type): + if not d.do_not_include_in_total: + d.amount = flt(d.amount, d.precision("amount")) + total += d.amount + return total + + def set_component_amounts_based_on_payment_days(self): joining_date, relieving_date = frappe.db.get_value("Employee", self.employee, ["date_of_joining", "relieving_date"]) @@ -416,48 +694,24 @@ class SalarySlip(TransactionBase): if not joining_date: frappe.throw(_("Please set the Date Of Joining for employee {0}").format(frappe.bold(self.employee_name))) - for d in self.get(component_type): - if (self.salary_structure and - cint(d.depends_on_payment_days) and cint(self.total_working_days) and - (not - self.salary_slip_based_on_timesheet or - getdate(self.start_date) < joining_date or - getdate(self.end_date) > relieving_date - )): + for component_type in ("earnings", "deductions"): + for d in self.get(component_type): + if (self.salary_structure and + cint(d.depends_on_payment_days) and cint(self.total_working_days) and + (not self.salary_slip_based_on_timesheet or + getdate(self.start_date) < joining_date or + getdate(self.end_date) > relieving_date + )): - d.amount = rounded( - (flt(d.default_amount, precision) * flt(self.payment_days) - / cint(self.total_working_days)), self.precision("amount", component_type) - ) + d.amount = flt( + (flt(d.default_amount + d.additional_amount) * flt(self.payment_days) + / cint(self.total_working_days)) + , d.precision("amount")) - elif not self.payment_days and not self.salary_slip_based_on_timesheet and \ - cint(d.depends_on_payment_days): - d.amount = 0 - elif not d.amount: - d.amount = d.default_amount - if not d.do_not_include_in_total: - self.set(total_field, self.get(total_field) + flt(d.amount, precision)) - - def calculate_net_pay(self): - if self.salary_structure: - self.calculate_component_amounts() - - disable_rounded_total = cint(frappe.db.get_value("Global Defaults", None, "disable_rounded_total")) - precision = frappe.defaults.get_global_default("currency_precision") - self.total_deduction = 0 - self.gross_pay = 0 - - self.sum_components('earnings', 'gross_pay', precision) - self.sum_components('deductions', 'total_deduction', precision) - - self.set_loan_repayment() - - self.net_pay = flt(self.gross_pay) - (flt(self.total_deduction) + flt(self.total_loan_repayment)) - self.rounded_total = rounded(self.net_pay, - self.precision("net_pay") if disable_rounded_total else 0) - - if self.net_pay < 0: - frappe.throw(_("Net Pay cannnot be negative")) + elif not self.payment_days and not self.salary_slip_based_on_timesheet and cint(d.depends_on_payment_days): + d.amount = 0 + elif not d.amount: + d.amount = d.default_amount + d.additional_amount def set_loan_repayment(self): self.set('loans', []) @@ -489,25 +743,6 @@ class SalarySlip(TransactionBase): l.repay_from_salary = 1 and l.docstatus = 1 and l.applicant = %s""", (self.start_date, self.end_date, self.employee), as_dict=True) or [] - def on_submit(self): - if self.net_pay < 0: - frappe.throw(_("Net Pay cannot be less than 0")) - else: - self.set_status() - self.update_status(self.name) - self.update_salary_slip_in_additional_salary() - if (frappe.db.get_single_value("HR Settings", "email_salary_slip_to_employee")) and not frappe.flags.via_payroll_entry: - self.email_salary_slip() - - def on_cancel(self): - self.set_status() - self.update_status() - self.update_salary_slip_in_additional_salary() - - def on_trash(self): - from frappe.model.naming import revert_series_if_last - revert_series_if_last(self.series, self.name) - def update_salary_slip_in_additional_salary(self): salary_slip = self.name if self.docstatus==1 else None frappe.db.sql(""" @@ -549,289 +784,24 @@ class SalarySlip(TransactionBase): status = self.get_status() self.db_set("status", status) - def get_status(self): - if self.docstatus == 0: - status = "Draft" - elif self.docstatus == 1: - status = "Submitted" - elif self.docstatus == 2: - status = "Cancelled" - return status - def calculate_variable_based_on_taxable_salary(self, tax_component): - payroll_period = get_payroll_period(self.start_date, self.end_date, self.company) - if not payroll_period: - frappe.msgprint(_("Start and end dates not in a valid Payroll Period, cannot calculate {0}.") - .format(tax_component)) - return False - if payroll_period.end_date <= getdate(self.end_date): - if not self.deduct_tax_for_unsubmitted_tax_exemption_proof or not\ - self.deduct_tax_for_unclaimed_employee_benefits: - frappe.throw(_("You have to Deduct Tax for Unsubmitted Tax Exemption Proof and Unclaimed \ - Employee Benefits in the last Salary Slip of Payroll Period")) - # calc prorata tax to be applied - return self.calculate_variable_tax(tax_component, payroll_period) + def process_salary_structure(self, for_preview=0): + '''Calculate salary after salary structure details have been updated''' + if not self.salary_slip_based_on_timesheet: + self.get_date_details() + self.pull_emp_details() + self.get_leave_details(for_preview=for_preview) + self.calculate_net_pay() - def calculate_variable_tax(self, tax_component, payroll_period): - annual_taxable_earning, period_factor = 0, 0 - pro_rata_tax_paid, additional_tax_paid, benefit_tax_paid = 0.0, 0.0, 0.0 - unclaimed_earning, unclaimed_benefit, additional_income = 0.0, 0.0, 0.0 + def pull_emp_details(self): + emp = frappe.db.get_value("Employee", self.employee, ["bank_name", "bank_ac_no"], as_dict=1) + if emp: + self.bank_name = emp.bank_name + self.bank_account_no = emp.bank_ac_no - # get taxable_earning, additional_income in this slip - taxable_earning = self.get_taxable_earnings() - if self.deduct_tax_for_unclaimed_employee_benefits: - # get all untaxed benefits till date, pass amount to be taxed by later methods - unclaimed_benefit = self.calculate_unclaimed_taxable_benefit(payroll_period) - # flexi's excluded from monthly tax, add flexis in this slip to unclaimed_benefit - unclaimed_benefit += self.get_taxable_earnings(only_flexi=True)["taxable_earning"] - if self.deduct_tax_for_unsubmitted_tax_exemption_proof: - # do not consider exemption, calc tax to be paid for the period till date - # considering prorata taxes paid and proofs submitted - unclaimed_earning = self.calculate_unclaimed_taxable_earning(payroll_period, tax_component) - earning_in_period = taxable_earning["taxable_earning"] + unclaimed_earning - period_factor = self.get_period_factor(payroll_period.start_date, payroll_period.end_date, - payroll_period.start_date, self.end_date) - annual_taxable_earning = earning_in_period * period_factor - additional_income += self.get_total_additional_income(payroll_period.start_date) - else: - # consider exemption declaration, find annual_earning by monthly taxable salary - period_factor = self.get_period_factor(payroll_period.start_date, payroll_period.end_date) - annual_earning = taxable_earning["taxable_earning"] * period_factor - exemption_amount = 0 - if frappe.db.exists("Employee Tax Exemption Declaration", {"employee": self.employee, - "payroll_period": payroll_period.name, "docstatus": 1}): - exemption_amount = frappe.db.get_value("Employee Tax Exemption Declaration", - {"employee": self.employee, "payroll_period": payroll_period.name, "docstatus": 1}, - "total_exemption_amount") - annual_taxable_earning = annual_earning - exemption_amount - - if self.deduct_tax_for_unclaimed_employee_benefits or self.deduct_tax_for_unsubmitted_tax_exemption_proof: - tax_detail = self.get_tax_paid_in_period(payroll_period, tax_component) - if tax_detail: - pro_rata_tax_paid = tax_detail["total_tax_paid"] - tax_detail["additional_tax"] - tax_detail["benefit_tax"] - additional_tax_paid = tax_detail["additional_tax"] - benefit_tax_paid = tax_detail["benefit_tax"] - - # add any additional income in this slip - additional_income += taxable_earning["additional_income"] - args = { - "payroll_period": payroll_period.name, - "tax_component": tax_component, - "period_factor": period_factor, - "annual_taxable_earning": annual_taxable_earning, - "additional_income": additional_income, - "unclaimed_benefit": unclaimed_benefit, - "pro_rata_tax_paid": pro_rata_tax_paid, - "benefit_tax_paid": benefit_tax_paid, - "additional_tax_paid": additional_tax_paid - } - return self.calculate_tax(args) - - def calculate_unclaimed_taxable_benefit(self, payroll_period): - total_benefit, total_benefit_claim = 0, 0 - - # get total sum of benefits paid - sum_benefit = frappe.db.sql("""select sum(sd.amount) from `tabSalary Detail` sd join - `tabSalary Slip` ss on sd.parent=ss.name where sd.parentfield='earnings' - and sd.is_tax_applicable=1 and is_flexible_benefit=1 and ss.docstatus=1 - and ss.employee='{0}' and ss.start_date between '{1}' and '{2}' and - ss.end_date between '{1}' and '{2}'""".format(self.employee, - payroll_period.start_date, self.start_date)) - if sum_benefit and sum_benefit[0][0]: - total_benefit = sum_benefit[0][0] - - # get total benefits claimed - sum_benefit_claim = frappe.db.sql("""select sum(claimed_amount) from - `tabEmployee Benefit Claim` where docstatus=1 and employee='{0}' and claim_date - between '{1}' and '{2}'""".format(self.employee, payroll_period.start_date, self.end_date)) - if sum_benefit_claim and sum_benefit_claim[0][0]: - total_benefit_claim = sum_benefit_claim[0][0] - return total_benefit - total_benefit_claim - - def calculate_unclaimed_taxable_earning(self, payroll_period, tax_component): - total_taxable_earning, total_exemption_amount = 0, 0 - # calc total taxable amount in period - sum_taxable_earning = frappe.db.sql("""select sum(sd.amount) from `tabSalary Detail` sd join - `tabSalary Slip` ss on sd.parent=ss.name where sd.parentfield='earnings' - and sd.is_tax_applicable=1 and is_additional_component=0 and is_flexible_benefit=0 - and ss.docstatus=1 and ss.employee='{0}' and ss.start_date between '{1}' and '{2}' - and ss.end_date between '{1}' and '{2}'""".format(self.employee, - payroll_period.start_date, self.start_date)) - if sum_taxable_earning and sum_taxable_earning[0][0]: - total_taxable_earning = sum_taxable_earning[0][0] - - # add up total Proof Submission - sum_exemption = frappe.db.sql("""select sum(exemption_amount) from - `tabEmployee Tax Exemption Proof Submission` where docstatus=1 and employee='{0}' and - payroll_period='{1}' and submission_date between '{2}' and '{3}'""".format(self.employee, - payroll_period.name, payroll_period.start_date, self.end_date)) - if sum_exemption and sum_exemption[0][0]: - total_exemption_amount = sum_exemption[0][0] - total_taxable_earning -= total_exemption_amount - return total_taxable_earning - - def get_total_additional_income(self, from_date): - sum_additional_earning = frappe.db.sql(""" - select sum(sd.amount) - from - `tabSalary Detail` sd join `tabSalary Slip` ss on sd.parent=ss.name - where - sd.parentfield='earnings' - and sd.is_tax_applicable=1 and is_additional_component=1 - and is_flexible_benefit=0 and ss.docstatus=1 - and ss.employee=%(employee)s - and ss.start_date between %(from_date)s and %(to_date)s - and ss.end_date between %(from_date)s and %(to_date)s - """, { - "employee": self.employee, - "from_date": from_date, - "to_date": self.start_date - }) - return flt(sum_additional_earning[0][0]) if sum_additional_earning else 0 - - def get_tax_paid_in_period(self, payroll_period, tax_component, only_total=False): - # find total_tax_paid, tax paid for benefit, additional_salary - sum_tax_paid = frappe.db.sql(""" - select - sum(sd.amount), sum(tax_on_flexible_benefit), sum(tax_on_additional_salary) - from - `tabSalary Detail` sd join `tabSalary Slip` ss on sd.parent=ss.name - where - sd.parentfield='deductions' and sd.salary_component=%(salary_component)s - and sd.variable_based_on_taxable_salary=1 - and ss.docstatus=1 and ss.employee=%(employee)s - and ss.start_date between %(from_date)s and %(to_date)s - and ss.end_date between %(from_date)s and %(to_date)s - """, { - "salary_component": tax_component, - "employee": self.employee, - "from_date": payroll_period.start_date, - "to_date": self.start_date - }) - if sum_tax_paid and sum_tax_paid[0][0]: - return { - 'total_tax_paid': sum_tax_paid[0][0], - 'benefit_tax':sum_tax_paid[0][1], - 'additional_tax': sum_tax_paid[0][2] - } - - def get_taxable_earnings(self, include_flexi=0, only_flexi=0): - taxable_earning = 0 - additional_income = 0 - for earning in self.earnings: - if earning.is_tax_applicable: - if earning.is_additional_component: - additional_income += earning.amount - continue - if only_flexi: - if earning.is_flexible_benefit: - taxable_earning += earning.amount - continue - if include_flexi or not earning.is_flexible_benefit: - taxable_earning += earning.amount - return { - "taxable_earning": taxable_earning, - "additional_income": additional_income - } - - def calculate_tax(self, args): - tax_amount, benefit_tax, additional_tax = 0, 0, 0 - annual_taxable_earning = args.get("annual_taxable_earning") - benefit_to_tax = args.get("unclaimed_benefit") - additional_income = args.get("additional_income") - - # Get tax calc by period - annual_tax = self.calculate_tax_by_tax_slab(args.get("payroll_period"), annual_taxable_earning) - - # Calc prorata tax - tax_amount = annual_tax / args.get("period_factor") - - # Benefit is a part of Salary Structure, add the tax diff, update annual_tax - if benefit_to_tax > 0: - annual_taxable_earning += benefit_to_tax - annual_tax_with_benefit_income = self.calculate_tax_by_tax_slab( - args.get("payroll_period"), annual_taxable_earning) - benefit_tax = annual_tax_with_benefit_income - annual_tax - args.get("benefit_tax_paid") - tax_amount += benefit_tax - annual_tax = annual_tax_with_benefit_income - - # find the annual tax diff caused by additional_income, add to tax_amount - if additional_income > 0: - annual_tax_with_additional_income = self.calculate_tax_by_tax_slab( - args.get("payroll_period"), annual_taxable_earning + additional_income) - additional_tax = annual_tax_with_additional_income - annual_tax - args.get("additional_tax_paid") - tax_amount += additional_tax - # less paid taxes - if args.get("pro_rata_tax_paid"): - tax_amount -= args.get("pro_rata_tax_paid") - tax_amount = rounded(tax_amount) - struct_row = self.get_salary_slip_row(args.get("tax_component")) - return [struct_row, tax_amount, benefit_tax, additional_tax] - - def calculate_tax_by_tax_slab(self, payroll_period, annual_taxable_earning): - payroll_period_obj = frappe.get_doc("Payroll Period", payroll_period) - annual_taxable_earning -= flt(payroll_period_obj.standard_tax_exemption_amount) - data = self.get_data_for_eval() - data.update({"annual_taxable_earning": annual_taxable_earning}) - - taxable_amount = 0 - for slab in payroll_period_obj.taxable_salary_slabs: - if slab.condition and not self.eval_tax_slab_condition(slab.condition, data): - continue - if not slab.to_amount and annual_taxable_earning > slab.from_amount: - taxable_amount += (annual_taxable_earning - slab.from_amount) * slab.percent_deduction *.01 - continue - if annual_taxable_earning > slab.from_amount and annual_taxable_earning < slab.to_amount: - taxable_amount += (annual_taxable_earning - slab.from_amount) * slab.percent_deduction *.01 - elif annual_taxable_earning > slab.from_amount and annual_taxable_earning > slab.to_amount: - taxable_amount += (slab.to_amount - slab.from_amount) * slab.percent_deduction * .01 - return taxable_amount - - def eval_tax_slab_condition(self, condition, data): - try: - condition = condition.strip() - if condition: - return frappe.safe_eval(condition, self.whitelisted_globals, data) - except NameError as err: - frappe.throw(_("Name error: {0}".format(err))) - except SyntaxError as err: - frappe.throw(_("Syntax error in condition: {0}".format(err))) - except Exception as e: - frappe.throw(_("Error in formula or condition: {0}".format(e))) - raise - - def get_period_factor(self, period_start, period_end, start_date=None, end_date=None): - # TODO if both deduct checked update the factor to make tax consistent - joining_date, relieving_date = frappe.db.get_value("Employee", self.employee, ["date_of_joining", "relieving_date"]) - if getdate(joining_date) > getdate(period_start): - period_start = joining_date - if relieving_date and getdate(relieving_date) < getdate(period_end): - period_end = relieving_date - - payroll_days = date_diff(period_end, period_start) + 1 - if start_date and end_date: - salary_days = date_diff(end_date, start_date) + 1 - return flt(payroll_days)/flt(salary_days) - - # if period configured for a year and monthly frequency return 12 to make tax calc consistent - if 360 <= payroll_days <= 370 and self.payroll_frequency == "Monthly": - return 12 - - salary_days = date_diff(self.end_date, self.start_date) + 1 - return flt(payroll_days)/flt(salary_days) - - def get_salary_slip_row(self, salary_component): - component = frappe.get_doc("Salary Component", salary_component) - # Data for update_component_row - struct_row = {} - struct_row['depends_on_payment_days'] = component.depends_on_payment_days - struct_row['salary_component'] = component.name - struct_row['abbr'] = component.salary_component_abbr - struct_row['do_not_include_in_total'] = component.do_not_include_in_total - struct_row['is_tax_applicable'] = component.is_tax_applicable - struct_row['is_flexible_benefit'] = component.is_flexible_benefit - struct_row['variable_based_on_taxable_salary'] = component.variable_based_on_taxable_salary - return struct_row + def process_salary_based_on_leave(self, lwp=0): + self.get_leave_details(lwp=lwp) + self.calculate_net_pay() def unlink_ref_doc_from_salary_slip(ref_no): linked_ss = frappe.db.sql_list("""select name from `tabSalary Slip` diff --git a/erpnext/hr/doctype/salary_slip/test_salary_slip.py b/erpnext/hr/doctype/salary_slip/test_salary_slip.py index 75c1e420b8e..b7e07820013 100644 --- a/erpnext/hr/doctype/salary_slip/test_salary_slip.py +++ b/erpnext/hr/doctype/salary_slip/test_salary_slip.py @@ -45,12 +45,12 @@ class TestSalarySlip(unittest.TestCase): self.assertEqual(ss.total_working_days, no_of_days[0]) self.assertEqual(ss.payment_days, no_of_days[0]) - self.assertEqual(ss.earnings[0].amount, 25000) + self.assertEqual(ss.earnings[0].amount, 50000) self.assertEqual(ss.earnings[1].amount, 3000) self.assertEqual(ss.deductions[0].amount, 5000) self.assertEqual(ss.deductions[1].amount, 5000) - self.assertEqual(ss.gross_pay, 40500) - self.assertEqual(ss.net_pay, 29918) + self.assertEqual(ss.gross_pay, 78000) + self.assertEqual(ss.net_pay, 67418.0) def test_salary_slip_with_holidays_excluded(self): no_of_days = self.get_no_of_days() @@ -64,13 +64,13 @@ class TestSalarySlip(unittest.TestCase): self.assertEqual(ss.total_working_days, no_of_days[0] - no_of_days[1]) self.assertEqual(ss.payment_days, no_of_days[0] - no_of_days[1]) - self.assertEqual(ss.earnings[0].amount, 25000) - self.assertEqual(ss.earnings[0].default_amount, 25000) + self.assertEqual(ss.earnings[0].amount, 50000) + self.assertEqual(ss.earnings[0].default_amount, 50000) self.assertEqual(ss.earnings[1].amount, 3000) self.assertEqual(ss.deductions[0].amount, 5000) self.assertEqual(ss.deductions[1].amount, 5000) - self.assertEqual(ss.gross_pay, 40500) - self.assertEqual(ss.net_pay, 29918) + self.assertEqual(ss.gross_pay, 78000) + self.assertEqual(ss.net_pay, 67418.0) def test_payment_days(self): no_of_days = self.get_no_of_days() @@ -211,7 +211,7 @@ class TestSalarySlip(unittest.TestCase): tax_paid = get_tax_paid_in_period(employee) # total taxable income 586000, 250000 @ 5%, 86000 @ 20% ie. 12500 + 17200 - annual_tax = 29700 + annual_tax = 113567.79 try: self.assertEqual(tax_paid, annual_tax) except AssertionError: @@ -250,7 +250,7 @@ class TestSalarySlip(unittest.TestCase): # total taxable income 416000, 166000 @ 5% ie. 8300 try: - self.assertEqual(tax_paid, 8300) + self.assertEqual(tax_paid, 88607.79) except AssertionError: print("\nSalary Slip - Tax calculation failed on following case\n", data, "\n") raise @@ -265,7 +265,7 @@ class TestSalarySlip(unittest.TestCase): # total taxable income 566000, 250000 @ 5%, 66000 @ 20%, 12500 + 13200 tax_paid = get_tax_paid_in_period(employee) try: - self.assertEqual(tax_paid, 25700) + self.assertEqual(tax_paid, 121211.48) except AssertionError: print("\nSalary Slip - Tax calculation failed on following case\n", data, "\n") raise @@ -365,7 +365,7 @@ def make_earning_salary_component(setup=False, test_tax=False): "salary_component": 'Basic Salary', "abbr":'BS', "condition": 'base > 10000', - "formula": 'base*.5', + "formula": 'base', "type": "Earning", "amount_based_on_formula": 1 }, @@ -386,7 +386,6 @@ def make_earning_salary_component(setup=False, test_tax=False): { "salary_component": "Leave Encashment", "abbr": 'LE', - "is_additional_component": 1, "type": "Earning" } ] @@ -398,7 +397,8 @@ def make_earning_salary_component(setup=False, test_tax=False): "is_flexible_benefit": 1, "type": "Earning", "pay_against_benefit_claim": 1, - "max_benefit_amount": 100000 + "max_benefit_amount": 100000, + "depends_on_payment_days": 0 }, { "salary_component": "Medical Allowance", @@ -409,9 +409,8 @@ def make_earning_salary_component(setup=False, test_tax=False): "max_benefit_amount": 15000 }, { - "salary_component": "Perfomance Bonus", + "salary_component": "Performance Bonus", "abbr": 'B', - "is_additional_component": 1, "type": "Earning" } ]) @@ -442,7 +441,8 @@ def make_deduction_salary_component(setup=False, test_tax=False): "abbr":'T', "formula": 'base*.1', "type": "Deduction", - "amount_based_on_formula": 1 + "amount_based_on_formula": 1, + "depends_on_payment_days": 0 } ] if not test_tax: @@ -512,21 +512,23 @@ def create_tax_slab(payroll_period): { "from_amount": 250000, "to_amount": 500000, - "percent_deduction": 5 + "percent_deduction": 5.2, + "condition": "annual_taxable_earning > 500000" }, { - "from_amount": 500000, + "from_amount": 500001, "to_amount": 1000000, - "percent_deduction": 20 + "percent_deduction": 20.8 }, { - "from_amount": 1000000, - "percent_deduction": 30 + "from_amount": 1000001, + "percent_deduction": 31.2 } ] payroll_period.taxable_salary_slabs = [] for item in data: payroll_period.append("taxable_salary_slabs", item) + payroll_period.standard_tax_exemption_amount = 52500 payroll_period.save() def create_salary_slips_for_payroll_period(employee, salary_structure, payroll_period, deduct_random=True): @@ -559,7 +561,7 @@ def create_additional_salary(employee, payroll_period, amount): "doctype": "Additional Salary", "employee": employee, "company": erpnext.get_default_company(), - "salary_component": "Perfomance Bonus", + "salary_component": "Performance Bonus", "payroll_date": salary_date, "amount": amount, "type": "Earning" diff --git a/erpnext/hr/doctype/salary_structure/salary_structure.js b/erpnext/hr/doctype/salary_structure/salary_structure.js index e3f37e71059..d56320a0732 100755 --- a/erpnext/hr/doctype/salary_structure/salary_structure.js +++ b/erpnext/hr/doctype/salary_structure/salary_structure.js @@ -147,7 +147,8 @@ frappe.ui.form.on('Salary Structure', { source_name: frm.doc.name, employee: values.employee, as_print: 1, - print_format: print_format + print_format: print_format, + for_preview: 1 }, callback: function(r) { var new_window = window.open(); diff --git a/erpnext/hr/doctype/salary_structure/salary_structure.py b/erpnext/hr/doctype/salary_structure/salary_structure.py index 3431d3d4a8e..f7d712d3f16 100644 --- a/erpnext/hr/doctype/salary_structure/salary_structure.py +++ b/erpnext/hr/doctype/salary_structure/salary_structure.py @@ -137,7 +137,7 @@ def get_existing_assignments(employees, salary_structure,from_date): return salary_structures_assignments @frappe.whitelist() -def make_salary_slip(source_name, target_doc = None, employee = None, as_print = False, print_format = None): +def make_salary_slip(source_name, target_doc = None, employee = None, as_print = False, print_format = None, for_preview=0): def postprocess(source, target): if employee: employee_details = frappe.db.get_value("Employee", employee, @@ -147,7 +147,7 @@ def make_salary_slip(source_name, target_doc = None, employee = None, as_print = target.branch = employee_details.branch target.designation = employee_details.designation target.department = employee_details.department - target.run_method('process_salary_structure') + target.run_method('process_salary_structure', for_preview=for_preview) doc = get_mapped_doc("Salary Structure", source_name, { "Salary Structure": { diff --git a/erpnext/hr/doctype/salary_structure/test_salary_structure.py b/erpnext/hr/doctype/salary_structure/test_salary_structure.py index 1a660d90ecd..848c3df57ab 100644 --- a/erpnext/hr/doctype/salary_structure/test_salary_structure.py +++ b/erpnext/hr/doctype/salary_structure/test_salary_structure.py @@ -39,18 +39,19 @@ class TestSalaryStructure(unittest.TestCase): holiday_list.save() def test_amount_totals(self): + frappe.db.set_value("HR Settings", None, "include_holidays_in_total_working_days", 0) sal_slip = frappe.get_value("Salary Slip", {"employee_name":"test_employee_2@salary.com"}) if not sal_slip: sal_slip = make_employee_salary_slip("test_employee_2@salary.com", "Monthly", "Salary Structure Sample") self.assertEqual(sal_slip.get("salary_structure"), 'Salary Structure Sample') - self.assertEqual(sal_slip.get("earnings")[0].amount, 25000) + self.assertEqual(sal_slip.get("earnings")[0].amount, 50000) self.assertEqual(sal_slip.get("earnings")[1].amount, 3000) - self.assertEqual(sal_slip.get("earnings")[2].amount, 12500) - self.assertEqual(sal_slip.get("gross_pay"), 40500) + self.assertEqual(sal_slip.get("earnings")[2].amount, 25000) + self.assertEqual(sal_slip.get("gross_pay"), 78000) self.assertEqual(sal_slip.get("deductions")[0].amount, 5000) self.assertEqual(sal_slip.get("deductions")[1].amount, 5000) self.assertEqual(sal_slip.get("total_deduction"), 10000) - self.assertEqual(sal_slip.get("net_pay"), 30500) + self.assertEqual(sal_slip.get("net_pay"), 68000) def test_whitespaces_in_formula_conditions_fields(self): salary_structure = make_salary_structure("Salary Structure Sample", "Monthly", dont_submit=True) diff --git a/erpnext/hr/report/salary_register/salary_register.py b/erpnext/hr/report/salary_register/salary_register.py index 237c5e26786..3326ac7a6c8 100644 --- a/erpnext/hr/report/salary_register/salary_register.py +++ b/erpnext/hr/report/salary_register/salary_register.py @@ -35,6 +35,8 @@ def execute(filters=None): for d in ded_types: row.append(ss_ded_map.get(ss.name, {}).get(d)) + row.append(ss.total_loan_repayment) + row += [ss.total_deduction, ss.net_pay] data.append(row) @@ -67,7 +69,7 @@ def get_columns(salary_slips): columns = columns + [(e + ":Currency:120") for e in salary_components[_("Earning")]] + \ [_("Gross Pay") + ":Currency:120"] + [(d + ":Currency:120") for d in salary_components[_("Deduction")]] + \ - [_("Total Deduction") + ":Currency:120", _("Net Pay") + ":Currency:120"] + [_("Loan Repayment") + ":Currency:120", _("Total Deduction") + ":Currency:120", _("Net Pay") + ":Currency:120"] return columns, salary_components[_("Earning")], salary_components[_("Deduction")] diff --git a/erpnext/hr/utils.py b/erpnext/hr/utils.py index 70752c65323..a29cbd639ca 100644 --- a/erpnext/hr/utils.py +++ b/erpnext/hr/utils.py @@ -125,9 +125,9 @@ def get_employee_fields_label(): fields = [] for df in frappe.get_meta("Employee").get("fields"): if df.fieldname in ["salutation", "user_id", "employee_number", "employment_type", - "holiday_list", "branch", "department", "designation", "grade", - "notice_number_of_days", "reports_to", "leave_policy", "company_email"]: - fields.append({"value": df.fieldname, "label": df.label}) + "holiday_list", "branch", "department", "designation", "grade", + "notice_number_of_days", "reports_to", "leave_policy", "company_email"]: + fields.append({"value": df.fieldname, "label": df.label}) return fields @frappe.whitelist() @@ -262,12 +262,6 @@ def get_leave_period(from_date, to_date, company): if leave_period: return leave_period -def get_payroll_period(from_date, to_date, company): - payroll_period = frappe.db.sql("""select name, start_date, end_date from - `tabPayroll Period` - where start_date<=%s and end_date>= %s and company=%s""", (from_date, to_date, company), as_dict=1) - return payroll_period[0] if payroll_period else None - def allocate_earned_leaves(): '''Allocate earned leaves to Employees''' e_leave_types = frappe.get_all("Leave Type", diff --git a/erpnext/regional/india/utils.py b/erpnext/regional/india/utils.py index c6100cf5fcf..9077b79b78c 100644 --- a/erpnext/regional/india/utils.py +++ b/erpnext/regional/india/utils.py @@ -154,11 +154,9 @@ def calculate_annual_eligible_hra_exemption(doc): hra_component = frappe.get_cached_value('Company', doc.company, "hra_component") if not (basic_component and hra_component): frappe.throw(_("Please mention Basic and HRA component in Company")) - annual_exemption, monthly_exemption, hra_amount = 0, 0, 0 if hra_component and basic_component: assignment = get_salary_assignment(doc.employee, nowdate()) - if assignment: hra_component_exists = frappe.db.exists("Salary Detail", { "parent": assignment.salary_structure, @@ -166,18 +164,19 @@ def calculate_annual_eligible_hra_exemption(doc): "parentfield": "earnings", "parenttype": "Salary Structure" }) + if hra_component_exists: basic_amount, hra_amount = get_component_amt_from_salary_slip(doc.employee, assignment.salary_structure, basic_component, hra_component) if hra_amount: if doc.monthly_house_rent: annual_exemption = calculate_hra_exemption(assignment.salary_structure, - basic_amount, hra_amount, doc.monthly_house_rent, - doc.rented_in_metro_city) + basic_amount, hra_amount, doc.monthly_house_rent, doc.rented_in_metro_city) if annual_exemption > 0: monthly_exemption = annual_exemption / 12 else: annual_exemption = 0 + elif doc.docstatus == 1: frappe.throw(_("Salary Structure must be submitted before submission of Tax Ememption Declaration")) @@ -188,7 +187,7 @@ def calculate_annual_eligible_hra_exemption(doc): }) def get_component_amt_from_salary_slip(employee, salary_structure, basic_component, hra_component): - salary_slip = make_salary_slip(salary_structure, employee=employee) + salary_slip = make_salary_slip(salary_structure, employee=employee, for_preview=1) basic_amt, hra_amt = 0, 0 for earning in salary_slip.earnings: if earning.salary_component == basic_component: diff --git a/erpnext/setup/doctype/company/company.js b/erpnext/setup/doctype/company/company.js index aff4baf9314..cb8d8960274 100644 --- a/erpnext/setup/doctype/company/company.js +++ b/erpnext/setup/doctype/company/company.js @@ -11,11 +11,6 @@ frappe.ui.form.on("Company", { filters: {"type": "Earning"} } }); - frm.set_query("arrear_component", function(){ - return { - filters: {"is_additional_component": 1} - } - }); frm.set_query("parent_company", function() { return { From 391b3b67cbfa3665281d160de52d35c9fc2eac5a Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Wed, 15 May 2019 07:41:10 +0530 Subject: [PATCH 23/32] fix: limit offset was missing in the get_delivery_notes_to_be_billed method (#17609) --- erpnext/controllers/queries.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/erpnext/controllers/queries.py b/erpnext/controllers/queries.py index f8f1e544596..a40f0eff43b 100644 --- a/erpnext/controllers/queries.py +++ b/erpnext/controllers/queries.py @@ -254,11 +254,13 @@ def get_delivery_notes_to_be_billed(doctype, txt, searchfield, start, page_len, and return_against in (select name from `tabDelivery Note` where per_billed < 100) ) ) - %(mcond)s order by `tabDelivery Note`.`%(key)s` asc + %(mcond)s order by `tabDelivery Note`.`%(key)s` asc limit %(start)s, %(page_len)s """ % { "key": searchfield, "fcond": get_filters_cond(doctype, filters, []), "mcond": get_match_cond(doctype), + "start": start, + "page_len": page_len, "txt": "%(txt)s" }, {"txt": ("%%%s%%" % txt)}, as_dict=as_dict) From 1c2915f74bb2068ae10e5ae50e5c76fd13ac166d Mon Sep 17 00:00:00 2001 From: Saurabh Date: Wed, 15 May 2019 07:43:16 +0530 Subject: [PATCH 24/32] fix: reload docs before creating custom fields (#17585) --- .../create_department_records_for_each_company.py | 2 +- erpnext/patches/v11_0/inter_state_field_for_gst.py | 11 +++++++++++ erpnext/patches/v8_7/sync_india_custom_fields.py | 3 +++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/erpnext/patches/v11_0/create_department_records_for_each_company.py b/erpnext/patches/v11_0/create_department_records_for_each_company.py index b5a7bd91bd5..f09c5b2c5df 100644 --- a/erpnext/patches/v11_0/create_department_records_for_each_company.py +++ b/erpnext/patches/v11_0/create_department_records_for_each_company.py @@ -70,7 +70,7 @@ def update_instructors(comp_dict): emp_details = frappe.get_all("Employee", fields=["name", "company"]) for employee in emp_details: - records = comp_dict[employee.company] + records = comp_dict[employee.company] if employee.company else [] for department in records: when_then.append(''' diff --git a/erpnext/patches/v11_0/inter_state_field_for_gst.py b/erpnext/patches/v11_0/inter_state_field_for_gst.py index 232d44256f6..48249c9bbf5 100644 --- a/erpnext/patches/v11_0/inter_state_field_for_gst.py +++ b/erpnext/patches/v11_0/inter_state_field_for_gst.py @@ -8,6 +8,17 @@ def execute(): return frappe.reload_doc("hr", "doctype", "Employee Tax Exemption Declaration") frappe.reload_doc("hr", "doctype", "Employee Tax Exemption Proof Submission") + frappe.reload_doc("hr", "doctype", "Employee Grade") + frappe.reload_doc("hr", "doctype", "Leave Policy") + + frappe.reload_doc("accounts", "doctype", "Bank Account") + frappe.reload_doc("accounts", "doctype", "Tax Withholding Category") + frappe.reload_doc("accounts", "doctype", "Allowed To Transact With") + frappe.reload_doc("accounts", "doctype", "Finance Book") + frappe.reload_doc("accounts", "doctype", "Loyalty Program") + + frappe.reload_doc("stock", "doctype", "Item Barcode") + make_custom_fields() frappe.reload_doc("accounts", "doctype", "sales_taxes_and_charges") diff --git a/erpnext/patches/v8_7/sync_india_custom_fields.py b/erpnext/patches/v8_7/sync_india_custom_fields.py index c684b24b2b7..80d66c2ab19 100644 --- a/erpnext/patches/v8_7/sync_india_custom_fields.py +++ b/erpnext/patches/v8_7/sync_india_custom_fields.py @@ -7,8 +7,11 @@ def execute(): if not company: return + frappe.reload_doc('hr', 'doctype', 'payroll_period') frappe.reload_doc('hr', 'doctype', 'employee_tax_exemption_declaration') frappe.reload_doc('hr', 'doctype', 'employee_tax_exemption_proof_submission') + frappe.reload_doc('hr', 'doctype', 'employee_tax_exemption_declaration_category') + frappe.reload_doc('hr', 'doctype', 'employee_tax_exemption_proof_submission_detail') for doctype in ["Sales Invoice", "Delivery Note", "Purchase Invoice"]: frappe.db.sql("""delete from `tabCustom Field` where dt = %s From aa493a25f86584e4fc111c27d0d129174d292c79 Mon Sep 17 00:00:00 2001 From: Prasad Ramesh Date: Wed, 15 May 2019 07:43:39 +0530 Subject: [PATCH 25/32] fix: made Sales Partner Comission report visible in Selling module (#17604) --- erpnext/config/selling.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/erpnext/config/selling.py b/erpnext/config/selling.py index 99b8ce0e5ec..8021a2196c1 100644 --- a/erpnext/config/selling.py +++ b/erpnext/config/selling.py @@ -291,6 +291,12 @@ def get_data(): "name": "Customers Without Any Sales Transactions", "doctype": "Customer" }, + { + "type": "report", + "is_query_report": True, + "name": "Sales Partners Commission", + "doctype": "Customer" + } ] }, { From 15e0861e828f849a3b6f645b55e8de1e4401119a Mon Sep 17 00:00:00 2001 From: sahil28297 <37302950+sahil28297@users.noreply.github.com> Date: Wed, 15 May 2019 07:44:45 +0530 Subject: [PATCH 26/32] fix(patch): set attribute to none if it does not exist (#17605) --- .../v11_1/set_default_action_for_quality_inspection.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/erpnext/patches/v11_1/set_default_action_for_quality_inspection.py b/erpnext/patches/v11_1/set_default_action_for_quality_inspection.py index 82d43b05206..b13239f7d12 100644 --- a/erpnext/patches/v11_1/set_default_action_for_quality_inspection.py +++ b/erpnext/patches/v11_1/set_default_action_for_quality_inspection.py @@ -6,5 +6,10 @@ import frappe def execute(): stock_settings = frappe.get_doc('Stock Settings') + if stock_settings.default_warehouse and not frappe.db.exists("Warehouse", stock_settings.default_warehouse): + stock_settings.default_warehouse = None + if stock_settings.stock_uom and not frappe.db.exists("UOM", stock_settings.stock_uom): + stock_settings.stock_uom = None + stock_settings.flags.ignore_mandatory = True stock_settings.action_if_quality_inspection_is_not_submitted = "Stop" - stock_settings.save() \ No newline at end of file + stock_settings.save() From ab1bf1af19801fec9412faaca08f1998e7279c90 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Wed, 15 May 2019 07:45:47 +0530 Subject: [PATCH 27/32] fix: not able to create the sales invoice without item code (#17610) --- erpnext/accounts/doctype/sales_invoice/sales_invoice.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 56d52069c69..611fc44143c 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -508,8 +508,8 @@ class SalesInvoice(SellingController): for i in dic: if frappe.db.get_single_value('Selling Settings', dic[i][0]) == 'Yes': for d in self.get('items'): - if frappe.get_cached_value('Item', d.item_code, 'is_stock_item') == 1 \ - and not d.get(i.lower().replace(' ','_')) and not self.get(dic[i][1]): + if (d.item_code and frappe.get_cached_value('Item', d.item_code, 'is_stock_item') == 1 + and not d.get(i.lower().replace(' ','_')) and not self.get(dic[i][1])): msgprint(_("{0} is mandatory for Item {1}").format(i,d.item_code), raise_exception=1) From 3fa5eec07b6f924314f28336120ad5e98709c8ea Mon Sep 17 00:00:00 2001 From: Saurabh Date: Wed, 15 May 2019 08:37:29 +0600 Subject: [PATCH 28/32] bumped to version 11.1.30 --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index fdf815bda17..f1e06ef8227 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -5,7 +5,7 @@ import frappe from erpnext.hooks import regional_overrides from frappe.utils import getdate -__version__ = '11.1.29' +__version__ = '11.1.30' def get_default_company(user=None): '''Get default company for user''' From 9e9e415c5fe21f55437026436b75cbf215ee89f4 Mon Sep 17 00:00:00 2001 From: Palash Jhabak Date: Wed, 15 May 2019 11:37:31 +0530 Subject: [PATCH 29/32] fix: Cancelled Lab Tests shouldnt show in SI (#17616) Cancelled Lab Tests were also showing up in Get Items of SI fixes issue #17607 --- erpnext/healthcare/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/healthcare/utils.py b/erpnext/healthcare/utils.py index 0987eb5403b..6a226d9c6b2 100644 --- a/erpnext/healthcare/utils.py +++ b/erpnext/healthcare/utils.py @@ -82,7 +82,7 @@ def get_healthcare_services_to_invoice(patient): 'service': service_item, 'rate': practitioner_charge, 'income_account': income_account}) - lab_tests = frappe.get_list("Lab Test", {'patient': patient.name, 'invoiced': False}) + lab_tests = frappe.get_list("Lab Test", {'patient': patient.name, 'invoiced': False, 'docstatus': 1}) if lab_tests: for lab_test in lab_tests: lab_test_obj = frappe.get_doc("Lab Test", lab_test['name']) From c78b92141293a40c7e42ae6c10c9d9e469291522 Mon Sep 17 00:00:00 2001 From: bghayad Date: Wed, 15 May 2019 09:28:59 +0300 Subject: [PATCH 30/32] Fix for Chart of Account sorting problem (#17563) * First Commit from Master * Fix for CoA sorting problem * Fixing for CoA sorting problem * Fix for Chart of Account Sorting Problem --- erpnext/accounts/report/financial_statements.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/erpnext/accounts/report/financial_statements.py b/erpnext/accounts/report/financial_statements.py index d26aeb11b9e..fe030c5f1ce 100644 --- a/erpnext/accounts/report/financial_statements.py +++ b/erpnext/accounts/report/financial_statements.py @@ -321,7 +321,10 @@ def sort_accounts(accounts, is_root=False, key="name"): """Sort root types as Asset, Liability, Equity, Income, Expense""" def compare_accounts(a, b): - if is_root: + if re.split('\W+', a[key])[0].isdigit(): + # if chart of accounts is numbered, then sort by number + return cmp(a[key], b[key]) + elif is_root: if a.report_type != b.report_type and a.report_type == "Balance Sheet": return -1 if a.root_type != b.root_type and a.root_type == "Asset": @@ -330,10 +333,6 @@ def sort_accounts(accounts, is_root=False, key="name"): return -1 if a.root_type == "Income" and b.root_type == "Expense": return -1 - else: - if re.split('\W+', a[key])[0].isdigit(): - # if chart of accounts is numbered, then sort by number - return cmp(a[key], b[key]) return 1 accounts.sort(key = functools.cmp_to_key(compare_accounts)) From e0ade62e387907f1ce8f1a719d45f85a329785f9 Mon Sep 17 00:00:00 2001 From: Deepesh Garg <42651287+deepeshgarg007@users.noreply.github.com> Date: Wed, 15 May 2019 12:18:12 +0530 Subject: [PATCH 31/32] fix: Status updater fixes in PO and SO and test coverage for return (#17490) * fix: Status updator fixes in sales and purchase cycle * fix: Test cases for return in so and po --- .../purchase_invoice/purchase_invoice.py | 44 ++++++------ .../doctype/sales_invoice/sales_invoice.py | 31 ++++---- .../purchase_order/test_purchase_order.py | 70 +++++++++++++++++++ .../doctype/sales_order/test_sales_order.py | 38 ++++++++++ .../doctype/delivery_note/delivery_note.py | 22 +++--- .../purchase_receipt/purchase_receipt.py | 29 ++++---- 6 files changed, 175 insertions(+), 59 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index 53db2086768..a33e3f760d0 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -100,6 +100,7 @@ class PurchaseInvoice(BuyingController): self.validate_fixed_asset() self.create_remarks() self.set_status() + self.validate_purchase_receipt_if_update_stock() validate_inter_company_party(self.doctype, self.supplier, self.company, self.inter_company_invoice_reference) def validate_release_date(self): @@ -284,7 +285,7 @@ class PurchaseInvoice(BuyingController): def update_status_updater_args(self): if cint(self.update_stock): - self.status_updater.extend([{ + self.status_updater.append({ 'source_dt': 'Purchase Invoice Item', 'target_dt': 'Purchase Order Item', 'join_field': 'po_detail', @@ -292,28 +293,29 @@ class PurchaseInvoice(BuyingController): 'target_parent_dt': 'Purchase Order', 'target_parent_field': 'per_received', 'target_ref_field': 'qty', - 'source_field': 'qty', + 'source_field': 'received_qty', + 'second_source_dt': 'Purchase Receipt Item', + 'second_source_field': 'received_qty', + 'second_join_field': 'purchase_order_item', 'percent_join_field':'purchase_order', - # 'percent_join_field': 'prevdoc_docname', 'overflow_type': 'receipt', 'extra_cond': """ and exists(select name from `tabPurchase Invoice` where name=`tabPurchase Invoice Item`.parent and update_stock = 1)""" - }, - { - 'source_dt': 'Purchase Invoice Item', - 'target_dt': 'Purchase Order Item', - 'join_field': 'po_detail', - 'target_field': 'returned_qty', - 'target_parent_dt': 'Purchase Order', - # 'target_parent_field': 'per_received', - # 'target_ref_field': 'qty', - 'source_field': '-1 * qty', - # 'percent_join_field': 'prevdoc_docname', - # 'overflow_type': 'receipt', - 'extra_cond': """ and exists (select name from `tabPurchase Invoice` - where name=`tabPurchase Invoice Item`.parent and update_stock=1 and is_return=1)""" - } - ]) + }) + if cint(self.is_return): + self.status_updater.append({ + 'source_dt': 'Purchase Invoice Item', + 'target_dt': 'Purchase Order Item', + 'join_field': 'po_detail', + 'target_field': 'returned_qty', + 'source_field': '-1 * qty', + 'second_source_dt': 'Purchase Receipt Item', + 'second_source_field': '-1 * qty', + 'second_join_field': 'purchase_order_item', + 'overflow_type': 'receipt', + 'extra_cond': """ and exists (select name from `tabPurchase Invoice` + where name=`tabPurchase Invoice Item`.parent and update_stock=1 and is_return=1)""" + }) def validate_purchase_receipt_if_update_stock(self): if self.update_stock: @@ -327,13 +329,13 @@ class PurchaseInvoice(BuyingController): self.check_prev_docstatus() self.update_status_updater_args() + self.update_prevdoc_status() frappe.get_doc('Authorization Control').validate_approving_authority(self.doctype, self.company, self.base_grand_total) if not self.is_return: self.update_against_document_in_jv() - self.update_prevdoc_status() self.update_billing_status_for_zero_amount_refdoc("Purchase Order") self.update_billing_status_in_pr() @@ -763,13 +765,13 @@ class PurchaseInvoice(BuyingController): self.check_for_closed_status() self.update_status_updater_args() + self.update_prevdoc_status() if not self.is_return: from erpnext.accounts.utils import unlink_ref_doc_from_payment_entries if frappe.db.get_single_value('Accounts Settings', 'unlink_payment_on_cancellation_of_invoice'): unlink_ref_doc_from_payment_entries(self) - self.update_prevdoc_status() self.update_billing_status_for_zero_amount_refdoc("Purchase Order") self.update_billing_status_in_pr() diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 611fc44143c..77842d0b5c7 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -256,7 +256,7 @@ class SalesInvoice(SellingController): def update_status_updater_args(self): if cint(self.update_stock): - self.status_updater.extend([{ + self.status_updater.append({ 'source_dt':'Sales Invoice Item', 'target_dt':'Sales Order Item', 'target_parent_dt':'Sales Order', @@ -274,21 +274,20 @@ class SalesInvoice(SellingController): 'overflow_type': 'delivery', 'extra_cond': """ and exists(select name from `tabSales Invoice` where name=`tabSales Invoice Item`.parent and update_stock = 1)""" - }, - { - 'source_dt': 'Sales Invoice Item', - 'target_dt': 'Sales Order Item', - 'join_field': 'so_detail', - 'target_field': 'returned_qty', - 'target_parent_dt': 'Sales Order', - # 'target_parent_field': 'per_delivered', - # 'target_ref_field': 'qty', - 'source_field': '-1 * qty', - # 'percent_join_field': 'sales_order', - # 'overflow_type': 'delivery', - 'extra_cond': """ and exists (select name from `tabSales Invoice` where name=`tabSales Invoice Item`.parent and update_stock=1 and is_return=1)""" - } - ]) + }) + if cint(self.is_return): + self.status_updater.append({ + 'source_dt': 'Sales Invoice Item', + 'target_dt': 'Sales Order Item', + 'join_field': 'so_detail', + 'target_field': 'returned_qty', + 'target_parent_dt': 'Sales Order', + 'source_field': '-1 * qty', + 'second_source_dt': 'Delivery Note Item', + 'second_source_field': '-1 * qty', + 'second_join_field': 'so_detail', + 'extra_cond': """ and exists (select name from `tabSales Invoice` where name=`tabSales Invoice Item`.parent and update_stock=1 and is_return=1)""" + }) def check_credit_limit(self): from erpnext.selling.doctype.customer.customer import check_credit_limit diff --git a/erpnext/buying/doctype/purchase_order/test_purchase_order.py b/erpnext/buying/doctype/purchase_order/test_purchase_order.py index c7401faeb2d..13fcb0b6212 100644 --- a/erpnext/buying/doctype/purchase_order/test_purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/test_purchase_order.py @@ -108,6 +108,69 @@ class TestPurchaseOrder(unittest.TestCase): self.assertEqual(po.get("items")[0].amount, 1400) self.assertEqual(get_ordered_qty(), existing_ordered_qty + 3) + def test_update_qty(self): + po = create_purchase_order() + + make_pr_against_po(po.name, 6) + + po.load_from_db() + self.assertEqual(po.get("items")[0].received_qty, 6) + + # Check received_qty after make_purchase_invoice without update_stock checked + pi1 = make_purchase_invoice(po.name) + pi1.get("items")[0].qty = 6 + pi1.insert() + pi1.submit() + + po.load_from_db() + self.assertEqual(po.get("items")[0].received_qty, 6) + + # Check received_qty after make_purchase_invoice with update_stock checked + pi2 = make_purchase_invoice(po.name) + pi2.set("update_stock", 1) + pi2.get("items")[0].qty = 3 + pi2.insert() + pi2.submit() + + po.load_from_db() + self.assertEqual(po.get("items")[0].received_qty, 9) + + def test_return_against_purchase_order(self): + po = create_purchase_order() + + pr = make_pr_against_po(po.name, 6) + + po.load_from_db() + self.assertEqual(po.get("items")[0].received_qty, 6) + + pi2 = make_purchase_invoice(po.name) + pi2.set("update_stock", 1) + pi2.get("items")[0].qty = 3 + pi2.insert() + pi2.submit() + + po.load_from_db() + self.assertEqual(po.get("items")[0].received_qty, 9) + + # Make return purchase receipt, purchase invoice and check quantity + from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt \ + import make_purchase_receipt as make_purchase_receipt_return + from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice \ + import make_purchase_invoice as make_purchase_invoice_return + + pr1 = make_purchase_receipt_return(is_return=1, return_against=pr.name, qty=-3, do_not_submit=True) + pr1.items[0].purchase_order = po.name + pr1.items[0].purchase_order_item = po.items[0].name + pr1.submit() + + pi1= make_purchase_invoice_return(is_return=1, return_against=pi2.name, qty=-1, update_stock=1, do_not_submit=True) + pi1.items[0].purchase_order = po.name + pi1.items[0].po_detail = po.items[0].name + pi1.submit() + + + po.load_from_db() + self.assertEqual(po.get("items")[0].received_qty, 5) def test_make_purchase_invoice(self): po = create_purchase_order(do_not_submit=True) @@ -469,6 +532,13 @@ class TestPurchaseOrder(unittest.TestCase): self.assertEquals(se_items, supplied_items) update_backflush_based_on("BOM") +def make_pr_against_po(po, received_qty=0): + pr = make_purchase_receipt(po) + pr.get("items")[0].qty = received_qty or 5 + pr.insert() + pr.submit() + return pr + def make_subcontracted_item(item_code): from erpnext.manufacturing.doctype.production_plan.test_production_plan import make_bom diff --git a/erpnext/selling/doctype/sales_order/test_sales_order.py b/erpnext/selling/doctype/sales_order/test_sales_order.py index f270938ad3a..572d40460dc 100644 --- a/erpnext/selling/doctype/sales_order/test_sales_order.py +++ b/erpnext/selling/doctype/sales_order/test_sales_order.py @@ -123,6 +123,44 @@ class TestSalesOrder(unittest.TestCase): so.load_from_db() self.assertEqual(so.get("items")[0].delivered_qty, 9) + def test_return_against_sales_order(self): + so = make_sales_order() + + dn = create_dn_against_so(so.name, 6) + + so.load_from_db() + self.assertEqual(so.get("items")[0].delivered_qty, 6) + + # Check delivered_qty after make_sales_invoice with update_stock checked + si2 = make_sales_invoice(so.name) + si2.set("update_stock", 1) + si2.get("items")[0].qty = 3 + si2.insert() + si2.submit() + + so.load_from_db() + + self.assertEqual(so.get("items")[0].delivered_qty, 9) + + # Make return deliver note, sales invoice and check quantity + from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note + from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice + + dn1 = create_delivery_note(is_return=1, return_against=dn.name, qty=-3, do_not_submit=True) + dn1.items[0].against_sales_order = so.name + dn1.items[0].so_detail = so.items[0].name + dn1.submit() + + si1 = create_sales_invoice(is_return=1, return_against=si2.name, qty=-1, update_stock=1, do_not_submit=True) + si1.items[0].sales_order = so.name + si1.items[0].so_detail = so.items[0].name + si1.submit() + + + so.load_from_db() + self.assertEqual(so.get("items")[0].delivered_qty, 5) + + def test_reserved_qty_for_partial_delivery(self): make_stock_entry(target="_Test Warehouse - _TC", qty=10, rate=100) existing_reserved_qty = get_reserved_qty() diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py index 184bf17aea8..24a71128465 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/delivery_note.py @@ -52,16 +52,20 @@ class DeliveryNote(SellingController): 'percent_join_field': 'against_sales_invoice', 'overflow_type': 'delivery', 'no_tolerance': 1 - }, - { - 'source_dt': 'Delivery Note Item', - 'target_dt': 'Sales Order Item', - 'join_field': 'so_detail', - 'target_field': 'returned_qty', - 'target_parent_dt': 'Sales Order', - 'source_field': '-1 * qty', - 'extra_cond': """ and exists (select name from `tabDelivery Note` where name=`tabDelivery Note Item`.parent and is_return=1)""" }] + if cint(self.is_return): + self.status_updater.append({ + 'source_dt': 'Delivery Note Item', + 'target_dt': 'Sales Order Item', + 'join_field': 'so_detail', + 'target_field': 'returned_qty', + 'target_parent_dt': 'Sales Order', + 'source_field': '-1 * qty', + 'second_source_dt': 'Sales Invoice Item', + 'second_source_field': '-1 * qty', + 'second_join_field': 'so_detail', + 'extra_cond': """ and exists (select name from `tabDelivery Note` where name=`tabDelivery Note Item`.parent and is_return=1)""" + }) def before_print(self): def toggle_print_hide(meta, fieldname): diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py index d09f24a965f..378f1f6187a 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py @@ -24,29 +24,32 @@ class PurchaseReceipt(BuyingController): def __init__(self, *args, **kwargs): super(PurchaseReceipt, self).__init__(*args, **kwargs) self.status_updater = [{ - 'source_dt': 'Purchase Receipt Item', 'target_dt': 'Purchase Order Item', 'join_field': 'purchase_order_item', 'target_field': 'received_qty', 'target_parent_dt': 'Purchase Order', 'target_parent_field': 'per_received', 'target_ref_field': 'qty', + 'source_dt': 'Purchase Receipt Item', 'source_field': 'received_qty', + 'second_source_dt': 'Purchase Invoice Item', + 'second_source_field': 'received_qty', + 'second_join_field': 'po_detail', 'percent_join_field': 'purchase_order', 'overflow_type': 'receipt' - }, - { - 'source_dt': 'Purchase Receipt Item', - 'target_dt': 'Purchase Order Item', - 'join_field': 'purchase_order_item', - 'target_field': 'returned_qty', - 'target_parent_dt': 'Purchase Order', - # 'target_parent_field': 'per_received', - # 'target_ref_field': 'qty', - 'source_field': '-1 * qty', - # 'overflow_type': 'receipt', - 'extra_cond': """ and exists (select name from `tabPurchase Receipt` where name=`tabPurchase Receipt Item`.parent and is_return=1)""" }] + if cint(self.is_return): + self.status_updater.append({ + 'source_dt': 'Purchase Receipt Item', + 'target_dt': 'Purchase Order Item', + 'join_field': 'purchase_order_item', + 'target_field': 'returned_qty', + 'source_field': '-1 * qty', + 'second_source_dt': 'Purchase Invoice Item', + 'second_source_field': '-1 * qty', + 'second_join_field': 'po_detail', + 'extra_cond': """ and exists (select name from `tabPurchase Receipt` where name=`tabPurchase Receipt Item`.parent and is_return=1)""" + }) def validate(self): self.validate_posting_time() From d83e8c56b22ee73bfbcacd9ebf4ad06d2cce98cb Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Wed, 15 May 2019 14:10:10 +0530 Subject: [PATCH 32/32] fix: set barcode on selection of item if item has one barcode --- erpnext/stock/get_item_details.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py index f9a4a151a4b..cb2c62e7b0a 100644 --- a/erpnext/stock/get_item_details.py +++ b/erpnext/stock/get_item_details.py @@ -306,8 +306,21 @@ def get_basic_details(args, item): for fieldname in ("item_name", "item_group", "barcodes", "brand", "stock_uom"): out[fieldname] = item.get(fieldname) + child_doctype = args.doctype + ' Item' + meta = frappe.get_meta(child_doctype) + if meta.get_field("barcode"): + update_barcode_value(out) + return out +def update_barcode_value(out): + from erpnext.accounts.doctype.sales_invoice.pos import get_barcode_data + barcode_data = get_barcode_data([out]) + + # If item has one barcode then update the value of the barcode field + if barcode_data and len(barcode_data.get(out.item_code)) == 1: + out['barcode'] = barcode_data.get(out.item_code) + @frappe.whitelist() def calculate_service_end_date(args, item=None): args = process_args(args)