From 1a4bfdd090c0c5f73bde90f81d3783d2b7d0a4c7 Mon Sep 17 00:00:00 2001 From: Zlash65 Date: Mon, 28 Jan 2019 16:35:41 +0530 Subject: [PATCH 01/12] feat: selecting parent_company should disable chart_of_accounts based fields --- erpnext/setup/doctype/company/company.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/erpnext/setup/doctype/company/company.js b/erpnext/setup/doctype/company/company.js index 70e047a4e80..dbfbc5932ea 100644 --- a/erpnext/setup/doctype/company/company.js +++ b/erpnext/setup/doctype/company/company.js @@ -16,6 +16,14 @@ frappe.ui.form.on("Company", { filters: {"is_additional_component": 1} } }); + + frm.set_df_property("create_chart_of_accounts_based_on", "read_only", frm.doc.parent_company ? 1 : 0); + frm.set_df_property("existing_company", "read_only", frm.doc.parent_company ? 1 : 0); + frm.set_query("parent_company", function() { + return { + filters: {"is_group": 1} + } + }); }, company_name: function(frm) { @@ -28,6 +36,12 @@ frappe.ui.form.on("Company", { } }, + parent_company: function(frm) { + if(!frm.doc.parent_company) return; + frm.set_value("create_chart_of_accounts_based_on", "Existing Company"); + frm.set_value("existing_company", frm.doc.parent_company); + }, + date_of_commencement: function(frm) { if(frm.doc.date_of_commencement Date: Mon, 28 Jan 2019 16:39:14 +0530 Subject: [PATCH 02/12] feat: once company is saved, parent_company cannot be selected --- erpnext/setup/doctype/company/company.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/setup/doctype/company/company.js b/erpnext/setup/doctype/company/company.js index dbfbc5932ea..5592e9bd64d 100644 --- a/erpnext/setup/doctype/company/company.js +++ b/erpnext/setup/doctype/company/company.js @@ -53,8 +53,9 @@ frappe.ui.form.on("Company", { }, refresh: function(frm) { - if(frm.doc.abbr && !frm.doc.__islocal) { + if(!frm.doc.__islocal) { frm.set_df_property("abbr", "read_only", 1); + frm.set_df_property("parent_company", "read_only", 1); } frm.toggle_display('address_html', !frm.doc.__islocal); From 2def228da88043f944053826d4e7a92f15895c6d Mon Sep 17 00:00:00 2001 From: Zlash65 Date: Tue, 29 Jan 2019 12:28:56 +0530 Subject: [PATCH 03/12] feat: allow adding account only if topmost parent company - hidden filter for Parent Company added - Add button overriden with new condition --- .../accounts/doctype/account/account_tree.js | 58 ++++++++++++++++--- 1 file changed, 49 insertions(+), 9 deletions(-) diff --git a/erpnext/accounts/doctype/account/account_tree.js b/erpnext/accounts/doctype/account/account_tree.js index a9cbdd5dee7..5a80258e71b 100644 --- a/erpnext/accounts/doctype/account/account_tree.js +++ b/erpnext/accounts/doctype/account/account_tree.js @@ -4,13 +4,40 @@ frappe.treeview_settings["Account"] = { breadcrumbs: "Accounts", title: __("Chart Of Accounts"), get_tree_root: false, - filters: [{ - fieldname: "company", - fieldtype:"Select", - options: erpnext.utils.get_tree_options("company"), - label: __("Company"), - default: erpnext.utils.get_tree_default("company") - }], + filters: [ + { + fieldname: "company", + fieldtype:"Select", + options: erpnext.utils.get_tree_options("company"), + label: __("Company"), + default: erpnext.utils.get_tree_default("company"), + on_change: function() { + var me = frappe.treeview_settings['Account'].treeview; + var company = me.page.fields_dict.company.get_value(); + frappe.call({ + method: "frappe.client.get_value", + args: { + doctype: "Company", + fieldname: "parent_company", + filters: { name: company}, + }, + callback: function(r, rt) { + if(r.message) { + me.page.fields_dict.parent_company.set_value(r.message["parent_company"] || ""); + } + } + }); + } + }, + { + fieldname: "parent_company", + fieldtype:"Data", + fetch_from: "company.parent_company", + label: __("Parent Company"), + hidden: true, + disable_onchange: true + } + ], root_label: "Accounts", get_tree_nodes: 'erpnext.accounts.utils.get_children', add_tree_node: 'erpnext.accounts.utils.add_ac', @@ -42,8 +69,8 @@ frappe.treeview_settings["Account"] = { ], ignore_fields:["parent_account"], onload: function(treeview) { - frappe.treeview_settings['Account'].page = {}; - $.extend(frappe.treeview_settings['Account'].page, treeview.page); + frappe.treeview_settings['Account'].treeview = {}; + $.extend(frappe.treeview_settings['Account'].treeview, treeview); function get_company() { return treeview.page.fields_dict.company.get_value(); } @@ -93,6 +120,19 @@ frappe.treeview_settings["Account"] = { } }, toolbar: [ + { + label:__("Add Child"), + condition: function(node) { + return frappe.boot.user.can_create.indexOf("Account") !== -1 && + !frappe.treeview_settings['Account'].treeview.page.fields_dict.parent_company.get_value() && + node.expandable && !node.hide_add; + }, + click: function(node) { + var me = frappe.treeview_settings['Account'].treeview; + me.new_node(node); + }, + btnClass: "hidden-xs" + }, { condition: function(node) { return !node.root && frappe.boot.user.can_read.indexOf("GL Entry") !== -1 From 0407bf1e005a316322118bcf7043b834183fb788 Mon Sep 17 00:00:00 2001 From: Zlash65 Date: Wed, 30 Jan 2019 11:12:15 +0530 Subject: [PATCH 04/12] fix: override primary action button, change filter to root company --- .../accounts/doctype/account/account_tree.js | 32 ++++++++++++------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/erpnext/accounts/doctype/account/account_tree.js b/erpnext/accounts/doctype/account/account_tree.js index 5a80258e71b..4bedb3c26c7 100644 --- a/erpnext/accounts/doctype/account/account_tree.js +++ b/erpnext/accounts/doctype/account/account_tree.js @@ -15,25 +15,23 @@ frappe.treeview_settings["Account"] = { var me = frappe.treeview_settings['Account'].treeview; var company = me.page.fields_dict.company.get_value(); frappe.call({ - method: "frappe.client.get_value", + method: "erpnext.accounts.doctype.account.account.get_root_company", args: { - doctype: "Company", - fieldname: "parent_company", - filters: { name: company}, + company: company, }, callback: function(r, rt) { if(r.message) { - me.page.fields_dict.parent_company.set_value(r.message["parent_company"] || ""); + let root_company = r.message.length ? r.message[0] : ""; + me.page.fields_dict.root_company.set_value(root_company); } } }); } }, { - fieldname: "parent_company", + fieldname: "root_company", fieldtype:"Data", - fetch_from: "company.parent_company", - label: __("Parent Company"), + label: __("Root Company"), hidden: true, disable_onchange: true } @@ -105,6 +103,18 @@ frappe.treeview_settings["Account"] = { } }, + post_render: function(treeview) { + frappe.treeview_settings['Account'].treeview["tree"] = treeview.tree; + treeview.page.set_primary_action(__("New"), function() { + let root_company = treeview.page.fields_dict.root_company.get_value(); + + if(root_company) { + frappe.throw(__("Please add the account to root level Company - ") + root_company); + } else { + treeview.new_node(); + } + }, "octicon octicon-plus"); + }, onrender: function(node) { if(frappe.boot.user.can_read.indexOf("GL Entry") !== -1){ var dr_or_cr = node.data.balance < 0 ? "Cr" : "Dr"; @@ -124,12 +134,12 @@ frappe.treeview_settings["Account"] = { label:__("Add Child"), condition: function(node) { return frappe.boot.user.can_create.indexOf("Account") !== -1 && - !frappe.treeview_settings['Account'].treeview.page.fields_dict.parent_company.get_value() && + !frappe.treeview_settings['Account'].treeview.page.fields_dict.root_company.get_value() && node.expandable && !node.hide_add; }, click: function(node) { var me = frappe.treeview_settings['Account'].treeview; - me.new_node(node); + me.new_node(); }, btnClass: "hidden-xs" }, @@ -143,7 +153,7 @@ frappe.treeview_settings["Account"] = { "account": node.label, "from_date": frappe.sys_defaults.year_start_date, "to_date": frappe.sys_defaults.year_end_date, - "company": frappe.treeview_settings['Account'].page.fields_dict.company.get_value() + "company": frappe.treeview_settings['Account'].treeview.page.fields_dict.company.get_value() }; frappe.set_route("query-report", "General Ledger"); }, From 88c990901d5a060a7d2e9c4db27c30d95b064d8f Mon Sep 17 00:00:00 2001 From: Zlash65 Date: Wed, 30 Jan 2019 11:12:28 +0530 Subject: [PATCH 05/12] fix: added validation to if account is being added to child company --- erpnext/accounts/doctype/account/account.py | 14 ++++++++++++++ erpnext/setup/doctype/company/company.py | 1 + 2 files changed, 15 insertions(+) diff --git a/erpnext/accounts/doctype/account/account.py b/erpnext/accounts/doctype/account/account.py index 5d504b94be6..d699146049f 100644 --- a/erpnext/accounts/doctype/account/account.py +++ b/erpnext/accounts/doctype/account/account.py @@ -34,6 +34,7 @@ class Account(NestedSet): return self.validate_parent() self.validate_root_details() + self.validate_root_company() validate_field_number("Account", self.name, self.account_number, self.company, "account_number") self.validate_group_or_ledger() self.set_root_and_report_type() @@ -90,6 +91,13 @@ class Account(NestedSet): if not self.parent_account and not self.is_group: frappe.throw(_("Root Account must be a group")) + def validate_root_company(self): + # fetch all ancestors in top-down hierarchy + if frappe.local.flags.ignore_root_company_validation: return + ancestors = get_root_company(self.company) + if ancestors: + frappe.throw(_("Please add the account to root level Company - %s" % ancestors[0])) + def validate_group_or_ledger(self): if self.get("__islocal"): return @@ -250,3 +258,9 @@ def merge_account(old, new, is_group, root_type, company): frappe.rename_doc("Account", old, new, merge=1, ignore_permissions=1) return new + +@frappe.whitelist() +def get_root_company(company): + # return the topmost company in the hierarchy + ancestors = frappe.utils.nestedset.get_ancestors_of('Company', company, "lft asc") + return [ancestors[0]] if ancestors else [] diff --git a/erpnext/setup/doctype/company/company.py b/erpnext/setup/doctype/company/company.py index c49c2642511..33361e81d46 100644 --- a/erpnext/setup/doctype/company/company.py +++ b/erpnext/setup/doctype/company/company.py @@ -141,6 +141,7 @@ class Company(NestedSet): def create_default_accounts(self): from erpnext.accounts.doctype.account.chart_of_accounts.chart_of_accounts import create_charts + frappe.local.flags.ignore_root_company_validation = True create_charts(self.name, self.chart_of_accounts, self.existing_company) frappe.db.set(self, "default_receivable_account", frappe.db.get_value("Account", From d787ef8b8e504a499c5fda283861a3f17910f781 Mon Sep 17 00:00:00 2001 From: Zlash65 Date: Wed, 30 Jan 2019 14:00:56 +0530 Subject: [PATCH 06/12] feat: sync account created for a group company to all its descendants --- erpnext/accounts/doctype/account/account.py | 30 ++++++++++++++++----- 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/erpnext/accounts/doctype/account/account.py b/erpnext/accounts/doctype/account/account.py index d699146049f..dea82d8ed6c 100644 --- a/erpnext/accounts/doctype/account/account.py +++ b/erpnext/accounts/doctype/account/account.py @@ -5,7 +5,7 @@ from __future__ import unicode_literals import frappe from frappe.utils import cint, cstr from frappe import throw, _ -from frappe.utils.nestedset import NestedSet +from frappe.utils.nestedset import NestedSet, get_ancestors_of, get_descendants_of class RootNotEditable(frappe.ValidationError): pass class BalanceMismatchError(frappe.ValidationError): pass @@ -34,7 +34,6 @@ class Account(NestedSet): return self.validate_parent() self.validate_root_details() - self.validate_root_company() validate_field_number("Account", self.name, self.account_number, self.company, "account_number") self.validate_group_or_ledger() self.set_root_and_report_type() @@ -42,6 +41,7 @@ class Account(NestedSet): self.validate_frozen_accounts_modifier() self.validate_balance_must_be_debit_or_credit() self.validate_account_currency() + self.validate_root_company_and_sync_account_to_children() def validate_parent(self): """Fetch Parent Details and validate parent account""" @@ -91,12 +91,30 @@ class Account(NestedSet): if not self.parent_account and not self.is_group: frappe.throw(_("Root Account must be a group")) - def validate_root_company(self): - # fetch all ancestors in top-down hierarchy - if frappe.local.flags.ignore_root_company_validation: return + def validate_root_company_and_sync_account_to_children(self): + # ignore validation while creating new compnay or while syncing to child companies + if frappe.local.flags.ignore_root_company_validation or self.flags.ignore_root_company_validation: + return + ancestors = get_root_company(self.company) if ancestors: frappe.throw(_("Please add the account to root level Company - %s" % ancestors[0])) + else: + descendants = get_descendants_of('Company', self.company) + acc_name = frappe.db.get_value('Account', self.parent_account, "account_name") + + acc_name_map = {} + for d in frappe.db.get_values('Account', + {"company": ["in", descendants], "account_name": acc_name}, + ["company", "name"], as_dict=True): + acc_name_map[d["company"]] = d["name"] + + for company in descendants: + doc = frappe.copy_doc(self) + doc.flags.ignore_root_company_validation = True + doc.update({"company": company, "account_currency": None, + "parent": acc_name_map[company], "parent_account": acc_name_map[company]}) + doc.save() def validate_group_or_ledger(self): if self.get("__islocal"): @@ -262,5 +280,5 @@ def merge_account(old, new, is_group, root_type, company): @frappe.whitelist() def get_root_company(company): # return the topmost company in the hierarchy - ancestors = frappe.utils.nestedset.get_ancestors_of('Company', company, "lft asc") + ancestors = get_ancestors_of('Company', company, "lft asc") return [ancestors[0]] if ancestors else [] From 73acb8c83702e636a4b126add7a2181ddad2a012 Mon Sep 17 00:00:00 2001 From: Zlash65 Date: Wed, 13 Feb 2019 16:31:37 +0530 Subject: [PATCH 07/12] fix: set chart of accounts based on parent company on server side --- erpnext/setup/doctype/company/company.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/erpnext/setup/doctype/company/company.py b/erpnext/setup/doctype/company/company.py index 33361e81d46..ad9d64baf53 100644 --- a/erpnext/setup/doctype/company/company.py +++ b/erpnext/setup/doctype/company/company.py @@ -39,6 +39,7 @@ class Company(NestedSet): self.validate_coa_input() self.validate_perpetual_inventory() self.check_country_change() + self.set_chart_of_accounts() def validate_abbr(self): if not self.abbr: @@ -174,6 +175,12 @@ class Company(NestedSet): self.country != frappe.get_cached_value('Company', self.name, 'country'): frappe.flags.country_change = True + def set_chart_of_accounts(self): + ''' If parent company is set, chart of accounts will be based on that company ''' + if self.parent_company: + self.create_chart_of_accounts_based_on = "Existing Company" + self.existing_company = self.parent_company + def set_default_accounts(self): self._set_default_account("default_cash_account", "Cash") self._set_default_account("default_bank_account", "Bank") From f71cb8dc6db03ee5ddc50aac58ef52b4fc783c71 Mon Sep 17 00:00:00 2001 From: Zlash65 Date: Wed, 13 Feb 2019 16:32:04 +0530 Subject: [PATCH 08/12] fix: return if no descendants found --- erpnext/accounts/doctype/account/account.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/account/account.py b/erpnext/accounts/doctype/account/account.py index dea82d8ed6c..e241fc4a3af 100644 --- a/erpnext/accounts/doctype/account/account.py +++ b/erpnext/accounts/doctype/account/account.py @@ -101,9 +101,10 @@ class Account(NestedSet): frappe.throw(_("Please add the account to root level Company - %s" % ancestors[0])) else: descendants = get_descendants_of('Company', self.company) - acc_name = frappe.db.get_value('Account', self.parent_account, "account_name") + if not descendants: return acc_name_map = {} + acc_name = frappe.db.get_value('Account', self.parent_account, "account_name") for d in frappe.db.get_values('Account', {"company": ["in", descendants], "account_name": acc_name}, ["company", "name"], as_dict=True): From cc65447e62d768354984bb042e6f3a01043fc031 Mon Sep 17 00:00:00 2001 From: Zlash65 Date: Wed, 13 Feb 2019 16:32:50 +0530 Subject: [PATCH 09/12] fix: chart of accounts field toggling improv --- erpnext/setup/doctype/company/company.js | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/erpnext/setup/doctype/company/company.js b/erpnext/setup/doctype/company/company.js index 5592e9bd64d..aff4baf9314 100644 --- a/erpnext/setup/doctype/company/company.js +++ b/erpnext/setup/doctype/company/company.js @@ -17,8 +17,6 @@ frappe.ui.form.on("Company", { } }); - frm.set_df_property("create_chart_of_accounts_based_on", "read_only", frm.doc.parent_company ? 1 : 0); - frm.set_df_property("existing_company", "read_only", frm.doc.parent_company ? 1 : 0); frm.set_query("parent_company", function() { return { filters: {"is_group": 1} @@ -37,9 +35,10 @@ frappe.ui.form.on("Company", { }, parent_company: function(frm) { - if(!frm.doc.parent_company) return; - frm.set_value("create_chart_of_accounts_based_on", "Existing Company"); - frm.set_value("existing_company", frm.doc.parent_company); + var bool = frm.doc.parent_company ? true : false; + frm.set_value('create_chart_of_accounts_based_on', bool ? "Existing Company" : ""); + frm.set_value('existing_company', bool ? frm.doc.parent_company : ""); + disbale_coa_fields(frm, bool); }, date_of_commencement: function(frm) { @@ -54,8 +53,9 @@ frappe.ui.form.on("Company", { refresh: function(frm) { if(!frm.doc.__islocal) { - frm.set_df_property("abbr", "read_only", 1); + frm.doc.abbr && frm.set_df_property("abbr", "read_only", 1); frm.set_df_property("parent_company", "read_only", 1); + disbale_coa_fields(frm); } frm.toggle_display('address_html', !frm.doc.__islocal); @@ -271,3 +271,9 @@ erpnext.company.set_custom_query = function(frm, v) { } }); } + +var disbale_coa_fields = function(frm, bool=true) { + frm.set_df_property("create_chart_of_accounts_based_on", "read_only", bool); + frm.set_df_property("chart_of_accounts", "read_only", bool); + frm.set_df_property("existing_company", "read_only", bool); +}; \ No newline at end of file From 11bba571afb7a6bd49e5ac6bed623bdc8149e7be Mon Sep 17 00:00:00 2001 From: Zlash65 Date: Wed, 13 Feb 2019 16:33:28 +0530 Subject: [PATCH 10/12] test case added to check account syncing --- .../accounts/doctype/account/test_account.py | 13 +++++++ .../setup/doctype/company/test_records.json | 34 +++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/erpnext/accounts/doctype/account/test_account.py b/erpnext/accounts/doctype/account/test_account.py index acaa0966a20..4c057d95492 100644 --- a/erpnext/accounts/doctype/account/test_account.py +++ b/erpnext/accounts/doctype/account/test_account.py @@ -97,6 +97,19 @@ class TestAccount(unittest.TestCase): self.assertRaises(frappe.ValidationError, merge_account, "Capital Stock - _TC",\ "Softwares - _TC", doc.is_group, doc.root_type, doc.company) + def test_account_sync(self): + del frappe.local.flags["ignore_root_company_validation"] + acc = frappe.new_doc("Account") + acc.account_name = "Test Sync Account" + acc.parent_account = "Temporary Accounts - _TC3" + acc.company = "_Test Company 3" + acc.insert() + + acc_tc_4 = frappe.db.get_value('Account', {'account_name': "Test Sync Account", "company": "_Test Company 4"}) + acc_tc_5 = frappe.db.get_value('Account', {'account_name': "Test Sync Account", "company": "_Test Company 5"}) + self.assertEqual(acc_tc_4, "Test Sync Account - _TC4") + self.assertEqual(acc_tc_5, "Test Sync Account - _TC5") + def _make_test_records(verbose): from frappe.test_runner import make_test_objects diff --git a/erpnext/setup/doctype/company/test_records.json b/erpnext/setup/doctype/company/test_records.json index 7e26ca32074..bf9d4bdd190 100644 --- a/erpnext/setup/doctype/company/test_records.json +++ b/erpnext/setup/doctype/company/test_records.json @@ -28,5 +28,39 @@ "domain": "Retail", "chart_of_accounts": "Standard", "default_holiday_list": "_Test Holiday List" + }, + { + "abbr": "_TC3", + "company_name": "_Test Company 3", + "is_group": 1, + "country": "India", + "default_currency": "INR", + "doctype": "Company", + "domain": "Manufacturing", + "chart_of_accounts": "Standard", + "default_holiday_list": "_Test Holiday List" + }, + { + "abbr": "_TC4", + "company_name": "_Test Company 4", + "parent_company": "_Test Company 3", + "is_group": 1, + "country": "India", + "default_currency": "INR", + "doctype": "Company", + "domain": "Manufacturing", + "chart_of_accounts": "Standard", + "default_holiday_list": "_Test Holiday List" + }, + { + "abbr": "_TC5", + "company_name": "_Test Company 5", + "parent_company": "_Test Company 4", + "country": "India", + "default_currency": "INR", + "doctype": "Company", + "domain": "Manufacturing", + "chart_of_accounts": "Standard", + "default_holiday_list": "_Test Holiday List" } ] From 01086ff60c54a5463f23f747c2681ac45a531ff9 Mon Sep 17 00:00:00 2001 From: Zlash65 Date: Wed, 13 Feb 2019 16:33:42 +0530 Subject: [PATCH 11/12] codacy fixes --- erpnext/accounts/doctype/account/account_tree.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/account/account_tree.js b/erpnext/accounts/doctype/account/account_tree.js index 4bedb3c26c7..df0486cc271 100644 --- a/erpnext/accounts/doctype/account/account_tree.js +++ b/erpnext/accounts/doctype/account/account_tree.js @@ -19,7 +19,7 @@ frappe.treeview_settings["Account"] = { args: { company: company, }, - callback: function(r, rt) { + callback: function(r) { if(r.message) { let root_company = r.message.length ? r.message[0] : ""; me.page.fields_dict.root_company.set_value(root_company); @@ -137,7 +137,7 @@ frappe.treeview_settings["Account"] = { !frappe.treeview_settings['Account'].treeview.page.fields_dict.root_company.get_value() && node.expandable && !node.hide_add; }, - click: function(node) { + click: function() { var me = frappe.treeview_settings['Account'].treeview; me.new_node(); }, From d4e4316d0b9432a0b4ed36a54cdd97bc3a49d2fc Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Mon, 18 Mar 2019 10:53:43 +0530 Subject: [PATCH 12/12] fix: test cases and codacy --- erpnext/accounts/doctype/account/account.py | 2 + .../hr/doctype/staffing_plan/staffing_plan.py | 10 ++ .../staffing_plan/test_staffing_plan.py | 10 +- .../setup/doctype/company/test_records.json | 128 +++++++++--------- 4 files changed, 81 insertions(+), 69 deletions(-) diff --git a/erpnext/accounts/doctype/account/account.py b/erpnext/accounts/doctype/account/account.py index e241fc4a3af..427f3dba20d 100644 --- a/erpnext/accounts/doctype/account/account.py +++ b/erpnext/accounts/doctype/account/account.py @@ -116,6 +116,8 @@ class Account(NestedSet): doc.update({"company": company, "account_currency": None, "parent": acc_name_map[company], "parent_account": acc_name_map[company]}) doc.save() + frappe.msgprint(_("Account {0} is added in the child company {1}") + .format(doc.name, company)) def validate_group_or_ledger(self): if self.get("__islocal"): diff --git a/erpnext/hr/doctype/staffing_plan/staffing_plan.py b/erpnext/hr/doctype/staffing_plan/staffing_plan.py index 70e185cde56..83e53135ef4 100644 --- a/erpnext/hr/doctype/staffing_plan/staffing_plan.py +++ b/erpnext/hr/doctype/staffing_plan/staffing_plan.py @@ -20,6 +20,7 @@ class StaffingPlan(Document): self.total_estimated_budget = 0 for detail in self.get("staffing_details"): + self.set_vacancies(detail) self.validate_overlap(detail) self.validate_with_subsidiary_plans(detail) self.validate_with_parent_plan(detail) @@ -39,6 +40,15 @@ class StaffingPlan(Document): else: detail.vacancies = detail.number_of_positions = detail.total_estimated_cost = 0 self.total_estimated_budget += detail.total_estimated_cost + def set_vacancies(self, row): + if not row.vacancies: + current_openings = 0 + for field in ['current_count', 'current_openings']: + if row.get(field): + current_openings += row.get(field) + + row.vacancies = row.number_of_positions - current_openings + def validate_overlap(self, staffing_plan_detail): # Validate if any submitted Staffing Plan exist for any Designations in this plan # and spd.vacancies>0 ? diff --git a/erpnext/hr/doctype/staffing_plan/test_staffing_plan.py b/erpnext/hr/doctype/staffing_plan/test_staffing_plan.py index 66d9cdd07a5..22dba99af00 100644 --- a/erpnext/hr/doctype/staffing_plan/test_staffing_plan.py +++ b/erpnext/hr/doctype/staffing_plan/test_staffing_plan.py @@ -18,7 +18,7 @@ class TestStaffingPlan(unittest.TestCase): if frappe.db.exists("Staffing Plan", "Test"): return staffing_plan = frappe.new_doc("Staffing Plan") - staffing_plan.company = "_Test Company 3" + staffing_plan.company = "_Test Company 10" staffing_plan.name = "Test" staffing_plan.from_date = nowdate() staffing_plan.to_date = add_days(nowdate(), 10) @@ -67,7 +67,7 @@ class TestStaffingPlan(unittest.TestCase): if frappe.db.exists("Staffing Plan", "Test 1"): return staffing_plan = frappe.new_doc("Staffing Plan") - staffing_plan.company = "_Test Company 3" + staffing_plan.company = "_Test Company 10" staffing_plan.name = "Test 1" staffing_plan.from_date = nowdate() staffing_plan.to_date = add_days(nowdate(), 10) @@ -85,11 +85,11 @@ def _set_up(): make_company() def make_company(): - if frappe.db.exists("Company", "_Test Company 3"): + if frappe.db.exists("Company", "_Test Company 10"): return company = frappe.new_doc("Company") - company.company_name = "_Test Company 3" - company.abbr = "_TC3" + company.company_name = "_Test Company 10" + company.abbr = "_TC10" company.parent_company = "_Test Company" company.default_currency = "INR" company.country = "India" diff --git a/erpnext/setup/doctype/company/test_records.json b/erpnext/setup/doctype/company/test_records.json index bf9d4bdd190..58d8b5c3346 100644 --- a/erpnext/setup/doctype/company/test_records.json +++ b/erpnext/setup/doctype/company/test_records.json @@ -1,66 +1,66 @@ [ - { - "abbr": "_TC", - "company_name": "_Test Company", - "country": "India", - "default_currency": "INR", - "doctype": "Company", - "domain": "Manufacturing", - "chart_of_accounts": "Standard", - "default_holiday_list": "_Test Holiday List" - }, - { - "abbr": "_TC1", - "company_name": "_Test Company 1", - "country": "United States", - "default_currency": "USD", - "doctype": "Company", - "domain": "Retail", - "chart_of_accounts": "Standard", - "default_holiday_list": "_Test Holiday List" - }, - { - "abbr": "_TC2", - "company_name": "_Test Company 2", - "default_currency": "EUR", - "country": "Germany", - "doctype": "Company", - "domain": "Retail", - "chart_of_accounts": "Standard", - "default_holiday_list": "_Test Holiday List" - }, - { - "abbr": "_TC3", - "company_name": "_Test Company 3", - "is_group": 1, - "country": "India", - "default_currency": "INR", - "doctype": "Company", - "domain": "Manufacturing", - "chart_of_accounts": "Standard", - "default_holiday_list": "_Test Holiday List" - }, - { - "abbr": "_TC4", - "company_name": "_Test Company 4", - "parent_company": "_Test Company 3", - "is_group": 1, - "country": "India", - "default_currency": "INR", - "doctype": "Company", - "domain": "Manufacturing", - "chart_of_accounts": "Standard", - "default_holiday_list": "_Test Holiday List" - }, - { - "abbr": "_TC5", - "company_name": "_Test Company 5", - "parent_company": "_Test Company 4", - "country": "India", - "default_currency": "INR", - "doctype": "Company", - "domain": "Manufacturing", - "chart_of_accounts": "Standard", - "default_holiday_list": "_Test Holiday List" - } + { + "abbr": "_TC", + "company_name": "_Test Company", + "country": "India", + "default_currency": "INR", + "doctype": "Company", + "domain": "Manufacturing", + "chart_of_accounts": "Standard", + "default_holiday_list": "_Test Holiday List" + }, + { + "abbr": "_TC1", + "company_name": "_Test Company 1", + "country": "United States", + "default_currency": "USD", + "doctype": "Company", + "domain": "Retail", + "chart_of_accounts": "Standard", + "default_holiday_list": "_Test Holiday List" + }, + { + "abbr": "_TC2", + "company_name": "_Test Company 2", + "default_currency": "EUR", + "country": "Germany", + "doctype": "Company", + "domain": "Retail", + "chart_of_accounts": "Standard", + "default_holiday_list": "_Test Holiday List" + }, + { + "abbr": "_TC3", + "company_name": "_Test Company 3", + "is_group": 1, + "country": "India", + "default_currency": "INR", + "doctype": "Company", + "domain": "Manufacturing", + "chart_of_accounts": "Standard", + "default_holiday_list": "_Test Holiday List" + }, + { + "abbr": "_TC4", + "company_name": "_Test Company 4", + "parent_company": "_Test Company 3", + "is_group": 1, + "country": "India", + "default_currency": "INR", + "doctype": "Company", + "domain": "Manufacturing", + "chart_of_accounts": "Standard", + "default_holiday_list": "_Test Holiday List" + }, + { + "abbr": "_TC5", + "company_name": "_Test Company 5", + "parent_company": "_Test Company 4", + "country": "India", + "default_currency": "INR", + "doctype": "Company", + "domain": "Manufacturing", + "chart_of_accounts": "Standard", + "default_holiday_list": "_Test Holiday List" + } ]