Staffing Plan - validations, get employee count on designation change, calc estimated cost

This commit is contained in:
Ranjith 2018-05-07 13:54:49 +05:30
parent 95c5c055f8
commit e4cda0380a
4 changed files with 228 additions and 68 deletions

View File

@ -2,7 +2,91 @@
// For license information, please see license.txt // For license information, please see license.txt
frappe.ui.form.on('Staffing Plan', { frappe.ui.form.on('Staffing Plan', {
refresh: function(frm) { setup: function(frm) {
frm.set_query("designation", "staffing_details", function() {
let designations = [];
$.each(frm.doc.staffing_details, function(index, staff_detail) {
if(staff_detail.designation){
designations.push(staff_detail.designation)
}
})
// Filter out designations already selected in Staffing Plan Detail
return {
filters: [
['Designation', 'name', 'not in', designations],
]
}
});
} }
}); });
frappe.ui.form.on('Staffing Plan Detail', {
designation: function(frm, cdt, cdn) {
let child = locals[cdt][cdn]
if(child.designation){
frappe.call({
"method": "erpnext.hr.doctype.staffing_plan.staffing_plan.get_current_employee_count",
args: {
designation: child.designation
},
callback: function (data) {
if(data.message){
frappe.model.set_value(cdt, cdn, 'current_count', data.message);
}
else{ // No employees for this designation
frappe.model.set_value(cdt, cdn, 'current_count', 0);
}
}
});
}
},
number_of_positions: function(frm, cdt, cdn) {
set_vacancies(frm, cdt, cdn);
},
current_count: function(frm, cdt, cdn) {
set_vacancies(frm, cdt, cdn);
},
estimated_cost_per_position: function(frm, cdt, cdn) {
let child = locals[cdt][cdn];
set_total_estimated_cost(frm, cdt, cdn);
}
});
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);
}
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
var set_total_estimated_cost = function(frm, cdt, cdn) {
let child = locals[cdt][cdn]
if(child.number_of_positions && child.estimated_cost_per_position) {
frappe.model.set_value(cdt, cdn, 'total_estimated_cost', child.vacancies * child.estimated_cost_per_position);
}
else {
frappe.model.set_value(cdt, cdn, 'total_estimated_cost', 0);
}
set_total_estimated_budget(frm);
};
var set_total_estimated_budget = function(frm) {
let estimated_budget = 0.0
if(frm.doc.staffing_details) {
$.each(frm.doc.staffing_details, function(index, staff_detail) {
if(staff_detail.total_estimated_cost){
estimated_budget += staff_detail.total_estimated_cost
}
})
frm.set_value('total_estimated_budget', estimated_budget);
}
}

View File

@ -268,6 +268,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"default": "0.00",
"fieldname": "total_estimated_budget", "fieldname": "total_estimated_budget",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 0, "hidden": 0,
@ -284,7 +285,7 @@
"precision": "", "precision": "",
"print_hide": 0, "print_hide": 0,
"print_hide_if_no_value": 0, "print_hide_if_no_value": 0,
"read_only": 0, "read_only": 1,
"remember_last_selected_value": 0, "remember_last_selected_value": 0,
"report_hide": 0, "report_hide": 0,
"reqd": 0, "reqd": 0,
@ -335,7 +336,7 @@
"issingle": 0, "issingle": 0,
"istable": 0, "istable": 0,
"max_attachments": 0, "max_attachments": 0,
"modified": "2018-04-13 18:45:16.729979", "modified": "2018-04-18 19:10:34.394249",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "HR", "module": "HR",
"name": "Staffing Plan", "name": "Staffing Plan",

View File

@ -5,6 +5,51 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import frappe import frappe
from frappe.model.document import Document from frappe.model.document import Document
from frappe import _
from frappe.utils import getdate, nowdate
class StaffingPlan(Document): class StaffingPlan(Document):
pass def validate(self):
# Validate Dates
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)))
if overlap and overlap [0][0]:
frappe.throw(_("Staffing Plan {0} already exist for designation {1}".format(overlap[0][0], detail.designation)))
@frappe.whitelist()
def get_current_employee_count(designation):
if not designation:
return False
employee_count = frappe.db.sql("""select count(*) from `tabEmployee` where \
designation = '{0}' and status='Active'""".format(designation))[0][0]
return employee_count
@frappe.whitelist()
def get_active_staffing_plan_and_vacancies(company, designation, department=None, date=getdate(nowdate())):
if not company or not designation:
frappe.throw(_("Please select Company and Designation"))
conditions = "spd.designation='{0}' and sp.docstatus=1 and \
sp.company='{1}'".format(designation, company)
if(department): #Department is an optional field
conditions += " and sp.department='{0}'".format(department)
if(date): #ToDo: Date should be mandatory?
conditions += " and '{0}' between sp.from_date and sp.to_date".format(date)
staffing_plan = frappe.db.sql("""select spd.parent, spd.vacancies \
from `tabStaffing Plan Detail` spd join `tabStaffing Plan` sp on spd.parent=sp.name
where {0}""".format(conditions))
# Only a signle staffing plan can be active for a designation on given date
return staffing_plan[0] if staffing_plan else False

View File

@ -75,68 +75,6 @@
"translatable": 0, "translatable": 0,
"unique": 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": 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": "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": 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_bulk_edit": 0,
"allow_on_submit": 0, "allow_on_submit": 0,
@ -190,6 +128,36 @@
"precision": "", "precision": "",
"print_hide": 0, "print_hide": 0,
"print_hide_if_no_value": 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": "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, "read_only": 0,
"remember_last_selected_value": 0, "remember_last_selected_value": 0,
"report_hide": 0, "report_hide": 0,
@ -198,6 +166,68 @@
"set_only_once": 0, "set_only_once": 0,
"translatable": 0, "translatable": 0,
"unique": 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,
"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,
"unique": 0
} }
], ],
"has_web_view": 0, "has_web_view": 0,
@ -210,7 +240,7 @@
"issingle": 0, "issingle": 0,
"istable": 1, "istable": 1,
"max_attachments": 0, "max_attachments": 0,
"modified": "2018-04-13 18:39:52.783341", "modified": "2018-04-15 16:09:12.622186",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "HR", "module": "HR",
"name": "Staffing Plan Detail", "name": "Staffing Plan Detail",