diff --git a/erpnext/docs/assets/img/human-resources/staffing-plan-detail.png b/erpnext/docs/assets/img/human-resources/staffing-plan-detail.png
new file mode 100644
index 0000000000..63532b7a73
Binary files /dev/null and b/erpnext/docs/assets/img/human-resources/staffing-plan-detail.png differ
diff --git a/erpnext/docs/assets/img/human-resources/staffing-plan.png b/erpnext/docs/assets/img/human-resources/staffing-plan.png
new file mode 100644
index 0000000000..f6550290ee
Binary files /dev/null and b/erpnext/docs/assets/img/human-resources/staffing-plan.png differ
diff --git a/erpnext/docs/user/manual/en/human-resources/staffing-plan.md b/erpnext/docs/user/manual/en/human-resources/staffing-plan.md
new file mode 100644
index 0000000000..d16a1ec0ce
--- /dev/null
+++ b/erpnext/docs/user/manual/en/human-resources/staffing-plan.md
@@ -0,0 +1,18 @@
+# Staffing Plan
+Staffing Plan helps you to plan human resource recruitments for your Company. ERPNext allows you to do this at a group company level helping you efficiently plan and budget new hirings for a period. Job Openings can only be created as per the number of vacancies and budget as per the active Staffing Plan.
+
+> Human Resources > Setup > Staffing Plan > New Staffing Plan
+
+
+
+- **Designation:** The designations for which you are creating the Staffing Plan.
+- **Number of Positions:** The number of positions you plan to recruit for between the Staffing Plan from and to dates.
+- **Current Count:** This is the number of Employees already hired for the Designation.
+- **Vacancies:** The number of vacancies based on the Number of Positions you wish to recruit and the current Employee count.
+- **Estimated Cost Per Position:** You can specify the cost to company per position so that hiring officials can stick to the budget.
+
+
+
+**Total Estimated Budget** Once you enter the recruitment plan for all the designations, Staffing Plan will draw up the total estimated budget.
diff --git a/erpnext/hr/doctype/job_opening/job_opening.js b/erpnext/hr/doctype/job_opening/job_opening.js
index 7b0e447a9e..b303b2451d 100644
--- a/erpnext/hr/doctype/job_opening/job_opening.js
+++ b/erpnext/hr/doctype/job_opening/job_opening.js
@@ -14,7 +14,7 @@ frappe.ui.form.on('Job Opening', {
designation: function(frm) {
if(frm.doc.designation && frm.doc.company){
frappe.call({
- "method": "erpnext.hr.doctype.staffing_plan.staffing_plan.get_active_staffing_plan_and_vacancies",
+ "method": "erpnext.hr.doctype.staffing_plan.staffing_plan.get_active_staffing_plan_details",
args: {
company: frm.doc.company,
designation: frm.doc.designation,
@@ -23,8 +23,8 @@ frappe.ui.form.on('Job Opening', {
},
callback: function (data) {
if(data.message){
- frm.set_value('staffing_plan', data.message[0]);
- frm.set_value('planned_vacancies', data.message[1]);
+ frm.set_value('staffing_plan', data.message[0].name);
+ frm.set_value('planned_vacancies', data.message[0].vacancies);
} else {
frm.set_value('staffing_plan', "");
frm.set_value('planned_vacancies', 0);
diff --git a/erpnext/hr/doctype/job_opening/job_opening.py b/erpnext/hr/doctype/job_opening/job_opening.py
index b579d6f24a..cfe6290049 100644
--- a/erpnext/hr/doctype/job_opening/job_opening.py
+++ b/erpnext/hr/doctype/job_opening/job_opening.py
@@ -8,7 +8,7 @@ import frappe
from frappe.website.website_generator import WebsiteGenerator
from frappe import _
-from erpnext.hr.doctype.staffing_plan.staffing_plan import get_current_employee_count, get_active_staffing_plan_and_vacancies
+from erpnext.hr.doctype.staffing_plan.staffing_plan import get_designation_counts, get_active_staffing_plan_details
class JobOpening(WebsiteGenerator):
website = frappe._dict(
@@ -24,11 +24,11 @@ class JobOpening(WebsiteGenerator):
def validate_current_vacancies(self):
if not self.staffing_plan:
- vacancies = get_active_staffing_plan_and_vacancies(self.company,
+ staffing_plan = get_active_staffing_plan_details(self.company,
self.designation, self.department)
- if vacancies:
- self.staffing_plan = vacancies[0]
- self.planned_vacancies = vacancies[1]
+ if staffing_plan:
+ self.staffing_plan = staffing_plan[0].name
+ self.planned_vacancies = staffing_plan[0].vacancies
elif not self.planned_vacancies:
planned_vacancies = frappe.db.sql("""
select vacancies from `tabStaffing Plan Detail`
@@ -39,14 +39,13 @@ class JobOpening(WebsiteGenerator):
staffing_plan_company = frappe.db.get_value("Staffing Plan", self.staffing_plan, "company")
lft, rgt = frappe.db.get_value("Company", staffing_plan_company, ["lft", "rgt"])
- current_count = get_current_employee_count(self.designation, staffing_plan_company)
- current_count+= frappe.db.sql("""select count(*) from `tabJob Opening` \
- where designation=%s and status='Open'
- and company in (select name from tabCompany where lft>=%s and rgt<=%s)
- """, (self.designation, lft, rgt))[0][0]
+ designation_counts = get_designation_counts(self.designation, self.company)
+ current_count = designation_counts['employee_count'] + designation_counts['job_openings']
if self.planned_vacancies <= current_count:
- frappe.throw(_("Job Openings for designation {0} and company {1} already opened or hiring completed as per Staffing Plan {2}".format(self.designation, staffing_plan_company, self.staffing_plan)))
+ frappe.throw(_("Job Openings for designation {0} already open \
+ or hiring completed as per Staffing Plan {1}"
+ .format(self.designation, self.staffing_plan)))
def get_context(self, context):
context.parents = [{'route': 'jobs', 'title': _('All Jobs') }]
diff --git a/erpnext/hr/doctype/staffing_plan/staffing_plan.js b/erpnext/hr/doctype/staffing_plan/staffing_plan.js
index ca57d9f19d..4fbc6b3089 100644
--- a/erpnext/hr/doctype/staffing_plan/staffing_plan.js
+++ b/erpnext/hr/doctype/staffing_plan/staffing_plan.js
@@ -33,17 +33,22 @@ frappe.ui.form.on('Staffing Plan Detail', {
let child = locals[cdt][cdn]
if(frm.doc.company && child.designation){
frappe.call({
- "method": "erpnext.hr.doctype.staffing_plan.staffing_plan.get_current_employee_count",
+ "method": "erpnext.hr.doctype.staffing_plan.staffing_plan.get_designation_counts",
args: {
designation: child.designation,
company: frm.doc.company
},
callback: function (data) {
if(data.message){
- frappe.model.set_value(cdt, cdn, 'current_count', data.message);
+ frappe.model.set_value(cdt, cdn, 'current_count', data.message.employee_count);
+ frappe.model.set_value(cdt, cdn, 'current_openings', data.message.job_openings);
+ if (child.number_of_positions < (data.message.employee_count + data.message.job_openings)){
+ frappe.model.set_value(cdt, cdn, 'number_of_positions', data.message.employee_count + data.message.job_openings);
+ }
}
else{ // No employees for this designation
frappe.model.set_value(cdt, cdn, 'current_count', 0);
+ frappe.model.set_value(cdt, cdn, 'current_openings', 0);
}
}
});
@@ -67,19 +72,25 @@ frappe.ui.form.on('Staffing Plan Detail', {
var set_vacancies = function(frm, cdt, cdn) {
let child = locals[cdt][cdn]
- if(child.number_of_positions) {
- frappe.model.set_value(cdt, cdn, 'vacancies', child.number_of_positions - child.current_count);
+ if (child.number_of_positions < (child.current_count + child.current_openings)){
+ frappe.throw(__("Number of positions cannot be less then current count of employees"))
+ }
+
+ if(child.number_of_positions > 0) {
+ frappe.model.set_value(cdt, cdn, 'vacancies', child.number_of_positions - (child.current_count + child.current_openings));
}
else{
frappe.model.set_value(cdt, cdn, 'vacancies', 0);
}
+
set_total_estimated_cost(frm, cdt, cdn);
}
// Note: Estimated Cost is calculated on number of Vacancies
+// Validate for > 0 ?
var set_total_estimated_cost = function(frm, cdt, cdn) {
let child = locals[cdt][cdn]
- if(child.number_of_positions && child.estimated_cost_per_position) {
+ if(child.vacancies > 0 && child.estimated_cost_per_position) {
frappe.model.set_value(cdt, cdn, 'total_estimated_cost', child.vacancies * child.estimated_cost_per_position);
}
else {
diff --git a/erpnext/hr/doctype/staffing_plan/staffing_plan.json b/erpnext/hr/doctype/staffing_plan/staffing_plan.json
index 229cc05ddd..9576bc306a 100644
--- a/erpnext/hr/doctype/staffing_plan/staffing_plan.json
+++ b/erpnext/hr/doctype/staffing_plan/staffing_plan.json
@@ -15,6 +15,7 @@
"fields": [
{
"allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -47,6 +48,7 @@
},
{
"allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -79,6 +81,7 @@
},
{
"allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -109,6 +112,7 @@
},
{
"allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -132,7 +136,7 @@
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
- "reqd": 0,
+ "reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
@@ -140,6 +144,7 @@
},
{
"allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -163,7 +168,7 @@
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
- "reqd": 0,
+ "reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
@@ -171,6 +176,7 @@
},
{
"allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -202,6 +208,7 @@
},
{
"allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -234,6 +241,7 @@
},
{
"allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -264,6 +272,7 @@
},
{
"allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -296,6 +305,7 @@
},
{
"allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -336,7 +346,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2018-04-18 19:10:34.394249",
+ "modified": "2018-05-28 18:30:27.041395",
"modified_by": "Administrator",
"module": "HR",
"name": "Staffing Plan",
diff --git a/erpnext/hr/doctype/staffing_plan/staffing_plan.py b/erpnext/hr/doctype/staffing_plan/staffing_plan.py
index 37ff5cbc90..e1a5f8ccb3 100644
--- a/erpnext/hr/doctype/staffing_plan/staffing_plan.py
+++ b/erpnext/hr/doctype/staffing_plan/staffing_plan.py
@@ -6,7 +6,7 @@ from __future__ import unicode_literals
import frappe
from frappe.model.document import Document
from frappe import _
-from frappe.utils import getdate, nowdate
+from frappe.utils import getdate, nowdate, cint, flt
class StaffingPlan(Document):
def validate(self):
@@ -14,32 +14,128 @@ class StaffingPlan(Document):
if self.from_date and self.to_date and self.from_date > self.to_date:
frappe.throw(_("From Date cannot be greater than To Date"))
- # Validate if any submitted Staffing Plan exist for Designations in this plan
- # and spd.vacancies>0 ?
- for detail in self.get("staffing_details"):
- overlap = (frappe.db.sql("""select spd.parent \
- from `tabStaffing Plan Detail` spd join `tabStaffing Plan` sp on spd.parent=sp.name \
- where spd.designation='{0}' and sp.docstatus=1 \
- and sp.to_date >= '{1}' and sp.from_date <='{2}'"""
- .format(detail.designation, self.from_date, self.to_date)))
+ self.total_estimated_budget = 0
- if overlap and overlap [0][0]:
- frappe.throw(_("Staffing Plan {0} already exist for designation {1}"
- .format(overlap[0][0], detail.designation)))
+ for detail in self.get("staffing_details"):
+ self.validate_overlap(detail)
+ self.validate_with_subsidiary_plans(detail)
+ self.validate_with_parent_plan(detail)
+
+ #Set readonly fields
+ designation_counts = get_designation_counts(detail.designation, self.company)
+ detail.current_count = designation_counts['employee_count']
+ detail.current_openings = designation_counts['job_openings']
+
+ if detail.number_of_positions < (detail.current_count + detail.current_openings):
+ frappe.throw(_("Number of positions cannot be less then current count of employees"))
+ elif detail.number_of_positions > 0:
+ detail.vacancies = detail.number_of_positions - (detail.current_count + detail.current_openings)
+ if detail.vacancies > 0 and detail.estimated_cost_per_position:
+ detail.total_estimated_cost = detail.vacancies * detail.estimated_cost_per_position
+ else: detail.total_estimated_cost = 0
+ else: detail.vacancies = detail.number_of_positions = detail.total_estimated_cost = 0
+ self.total_estimated_budget += detail.total_estimated_cost
+
+ def validate_overlap(self, staffing_plan_detail):
+ # Validate if any submitted Staffing Plan exist for any Designations in this plan
+ # and spd.vacancies>0 ?
+ overlap = frappe.db.sql("""select spd.parent
+ from `tabStaffing Plan Detail` spd join `tabStaffing Plan` sp on spd.parent=sp.name
+ where spd.designation=%s and sp.docstatus=1
+ and sp.to_date >= %s and sp.from_date <= %s and sp.company = %s
+ """, (staffing_plan_detail.designation, self.from_date, self.to_date, self.company))
+ if overlap and overlap [0][0]:
+ frappe.throw(_("Staffing Plan {0} already exist for designation {1}"
+ .format(overlap[0][0], staffing_plan_detail.designation)))
+
+ def validate_with_parent_plan(self, staffing_plan_detail):
+ if not frappe.db.get_value("Company", self.company, "parent_company"):
+ return # No parent, nothing to validate
+
+ # Get staffing plan applicable for the company (Parent Company)
+ parent_plan_details = get_active_staffing_plan_details(self.company, staffing_plan_detail.designation)
+ if not parent_plan_details:
+ return #no staffing plan for any parent Company in herarchy
+
+ # Fetch parent company which owns the staffing plan. NOTE: Parent could be higher up in the heirarchy
+ parent_company = frappe.db.get_value("Staffing Plan", parent_plan_details[0].name, "company")
+
+ # Parent plan available, validate with parent, siblings as well as children of staffing plan Company
+ if staffing_plan_detail.vacancies > cint(parent_plan_details[0].vacancies) or \
+ staffing_plan_detail.total_estimated_cost > flt(parent_plan_details[0].total_estimated_cost):
+ frappe.throw(_("You can only plan for upto {0} vacancies and budget {1} \
+ for {2} as per staffing plan {3} for parent company {4}"
+ .format(cint(parent_plan_details[0].vacancies),
+ parent_plan_details[0].total_estimated_cost,
+ frappe.bold(staffing_plan_detail.designation),
+ parent_plan_details[0].name,
+ parent_company)))
+
+ #Get vacanices already planned for all companies down the herarchy of Parent Company
+ lft, rgt = frappe.db.get_value("Company", parent_company, ["lft", "rgt"])
+ all_sibling_details = frappe.db.sql("""select sum(spd.vacancies) as vacancies,
+ sum(spd.total_estimated_cost) as total_estimated_cost
+ from `tabStaffing Plan Detail` spd join `tabStaffing Plan` sp on spd.parent=sp.name
+ where spd.designation=%s and sp.docstatus=1
+ and sp.to_date >= %s and sp.from_date <=%s
+ and sp.company in (select name from tabCompany where lft > %s and rgt < %s)
+ """, (staffing_plan_detail.designation, self.from_date, self.to_date, lft, rgt), as_dict = 1)[0]
+
+ if (cint(parent_plan_details[0].vacancies) < \
+ (staffing_plan_detail.vacancies + cint(all_sibling_details.vacancies))) or \
+ (flt(parent_plan_details[0].total_estimated_cost) < \
+ (staffing_plan_detail.total_estimated_cost + flt(all_sibling_details.total_estimated_cost))):
+ frappe.throw(_("{0} vacancies and {1} budget for {2} already planned for subsidiary companies of {3}. \
+ You can only plan for upto {4} vacancies and and budget {5} as per staffing plan {6} for parent company {3}"
+ .format(cint(all_sibling_details.vacancies),
+ all_sibling_details.total_estimated_cost,
+ frappe.bold(staffing_plan_detail.designation),
+ parent_company,
+ cint(parent_plan_details[0].vacancies),
+ parent_plan_details[0].total_estimated_cost,
+ parent_plan_details[0].name)))
+
+ def validate_with_subsidiary_plans(self, staffing_plan_detail):
+ #Valdate this plan with all child company plan
+ children_details = frappe.db.sql("""select sum(spd.vacancies) as vacancies,
+ sum(spd.total_estimated_cost) as total_estimated_cost
+ from `tabStaffing Plan Detail` spd join `tabStaffing Plan` sp on spd.parent=sp.name
+ where spd.designation=%s and sp.docstatus=1
+ and sp.to_date >= %s and sp.from_date <=%s
+ and sp.company in (select name from tabCompany where parent_company = %s)
+ """, (staffing_plan_detail.designation, self.from_date, self.to_date, self.company), as_dict = 1)[0]
+
+ if children_details and \
+ staffing_plan_detail.vacancies < cint(children_details.vacancies) or \
+ staffing_plan_detail.total_estimated_cost < flt(children_details.total_estimated_cost):
+ frappe.throw(_("Subsidiary companies have already planned for {1} vacancies at a budget of {2}. \
+ Staffing Plan for {0} should allocate more vacancies and budget for {3} than planned for its subsidiary companies"
+ .format(self.company,
+ cint(children_details.vacancies),
+ children_details.total_estimated_cost,
+ frappe.bold(staffing_plan_detail.designation))))
@frappe.whitelist()
-def get_current_employee_count(designation, company):
+def get_designation_counts(designation, company):
if not designation:
return False
+ employee_counts_dict = {}
lft, rgt = frappe.db.get_value("Company", company, ["lft", "rgt"])
- employee_count = frappe.db.sql("""select count(*) from `tabEmployee`
+ employee_counts_dict["employee_count"] = frappe.db.sql("""select count(*) from `tabEmployee`
where designation = %s and status='Active'
and company in (select name from tabCompany where lft>=%s and rgt<=%s)
""", (designation, lft, rgt))[0][0]
- return employee_count
-def get_active_staffing_plan_and_vacancies(company, designation, department=None, date=getdate(nowdate())):
+ employee_counts_dict['job_openings'] = frappe.db.sql("""select count(*) from `tabJob Opening` \
+ where designation=%s and status='Open'
+ and company in (select name from tabCompany where lft>=%s and rgt<=%s)
+ """, (designation, lft, rgt))[0][0]
+
+ return employee_counts_dict
+
+@frappe.whitelist()
+def get_active_staffing_plan_details(company, designation, department=None, date=getdate(nowdate())):
if not company or not designation:
frappe.throw(_("Please select Company and Designation"))
@@ -51,16 +147,16 @@ def get_active_staffing_plan_and_vacancies(company, designation, department=None
conditions += " and '{0}' between sp.from_date and sp.to_date".format(date)
staffing_plan = frappe.db.sql("""
- select sp.name, spd.vacancies
+ select sp.name, spd.vacancies, spd.total_estimated_cost
from `tabStaffing Plan Detail` spd join `tabStaffing Plan` sp on spd.parent=sp.name
where company=%s and spd.designation=%s and sp.docstatus=1 {0}
- """.format(conditions), (company, designation))
+ """.format(conditions), (company, designation), as_dict = 1)
if not staffing_plan:
parent_company = frappe.db.get_value("Company", company, "parent_company")
if parent_company:
- staffing_plan = get_active_staffing_plan_and_vacancies(parent_company,
+ staffing_plan = get_active_staffing_plan_details(parent_company,
designation, department, date)
- # Only a signle staffing plan can be active for a designation on given date
- return staffing_plan[0] if staffing_plan else None
+ # Only a single staffing plan can be active for a designation on given date
+ return staffing_plan if staffing_plan else None
diff --git a/erpnext/hr/doctype/staffing_plan_detail/staffing_plan_detail.json b/erpnext/hr/doctype/staffing_plan_detail/staffing_plan_detail.json
index eb77b43914..f1d16096c0 100644
--- a/erpnext/hr/doctype/staffing_plan_detail/staffing_plan_detail.json
+++ b/erpnext/hr/doctype/staffing_plan_detail/staffing_plan_detail.json
@@ -1,258 +1,297 @@
{
- "allow_copy": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "beta": 0,
- "creation": "2018-04-13 18:04:20.978931",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
+ "allow_copy": 0,
+ "allow_guest_to_view": 0,
+ "allow_import": 0,
+ "allow_rename": 0,
+ "beta": 0,
+ "creation": "2018-04-13 18:04:20.978931",
+ "custom": 0,
+ "docstatus": 0,
+ "doctype": "DocType",
+ "document_type": "",
+ "editable_grid": 1,
+ "engine": "InnoDB",
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "designation",
- "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": "Designation",
- "length": 0,
- "no_copy": 0,
- "options": "Designation",
- "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,
+ "fieldname": "designation",
+ "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": "Designation",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Designation",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 1,
+ "search_index": 0,
+ "set_only_once": 0,
+ "translatable": 0,
"unique": 0
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "number_of_positions",
- "fieldtype": "Int",
- "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": "Number Of Positions",
- "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,
+ "fieldname": "number_of_positions",
+ "fieldtype": "Int",
+ "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": "Number Of Positions",
+ "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_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "estimated_cost_per_position",
- "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": "Estimated Cost Per Position",
- "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,
+ "fieldname": "estimated_cost_per_position",
+ "fieldtype": "Currency",
+ "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": "Estimated Cost Per Position",
+ "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_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "total_estimated_cost",
- "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 Estimated Cost",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "column_break_5",
+ "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_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break_5",
- "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,
+ "fieldname": "current_count",
+ "fieldtype": "Int",
+ "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": "Current Count",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "translatable": 0,
"unique": 0
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "current_count",
- "fieldtype": "Int",
- "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": "Current Count",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "current_openings",
+ "fieldtype": "Int",
+ "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": "Current Openings",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "translatable": 0,
"unique": 0
- },
+ },
{
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "vacancies",
- "fieldtype": "Int",
- "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": "Vacancies",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "vacancies",
+ "fieldtype": "Int",
+ "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": "Vacancies",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "translatable": 0,
"unique": 0
- }
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 1,
- "max_attachments": 0,
- "modified": "2018-04-15 16:09:12.622186",
- "modified_by": "Administrator",
- "module": "HR",
- "name": "Staffing Plan Detail",
- "name_case": "",
- "owner": "Administrator",
- "permissions": [],
- "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "total_estimated_cost",
+ "fieldtype": "Currency",
+ "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": "Total Estimated Cost",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 1,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "translatable": 0,
+ "unique": 0
+ }
+ ],
+ "has_web_view": 0,
+ "hide_heading": 0,
+ "hide_toolbar": 0,
+ "idx": 0,
+ "image_view": 0,
+ "in_create": 0,
+ "is_submittable": 0,
+ "issingle": 0,
+ "istable": 1,
+ "max_attachments": 0,
+ "modified": "2018-06-01 17:03:38.020993",
+ "modified_by": "Administrator",
+ "module": "HR",
+ "name": "Staffing Plan Detail",
+ "name_case": "",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "read_only": 0,
+ "read_only_onload": 0,
+ "show_name_in_global_search": 0,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1,
"track_seen": 0
-}
\ No newline at end of file
+}