Staffing Plan (#14346)
* validate staffing plan * staffing plan docs * get_active_staffing_plan_and_vacancies now returns dict, mandatory fields set * validate with parent and child company plans, plan now considers open job openings * Failure details in validate error messages * Fixed sql injection
This commit is contained in:
parent
4fa600a8dd
commit
d580c92377
BIN
erpnext/docs/assets/img/human-resources/staffing-plan-detail.png
Normal file
BIN
erpnext/docs/assets/img/human-resources/staffing-plan-detail.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 39 KiB |
BIN
erpnext/docs/assets/img/human-resources/staffing-plan.png
Normal file
BIN
erpnext/docs/assets/img/human-resources/staffing-plan.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 111 KiB |
18
erpnext/docs/user/manual/en/human-resources/staffing-plan.md
Normal file
18
erpnext/docs/user/manual/en/human-resources/staffing-plan.md
Normal file
@ -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
|
||||
|
||||
<img class="screenshot" alt="Staffing Plan"
|
||||
src="{{docs_base_url}}/assets/img/human-resources/staffing-plan.png">
|
||||
|
||||
- **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.
|
||||
|
||||
<img class="screenshot" alt="Staffing Plan Detail"
|
||||
src="{{docs_base_url}}/assets/img/human-resources/staffing-plan-detail.png">
|
||||
|
||||
**Total Estimated Budget** Once you enter the recruitment plan for all the designations, Staffing Plan will draw up the total estimated budget.
|
@ -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);
|
||||
|
@ -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') }]
|
||||
|
@ -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 {
|
||||
|
@ -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",
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user