diff --git a/erpnext/hr/report/recruitment_analytics/__init__.py b/erpnext/hr/report/recruitment_analytics/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/hr/report/recruitment_analytics/recruitment_analytics.js b/erpnext/hr/report/recruitment_analytics/recruitment_analytics.js new file mode 100644 index 0000000000..9620f52000 --- /dev/null +++ b/erpnext/hr/report/recruitment_analytics/recruitment_analytics.js @@ -0,0 +1,23 @@ +// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt +/* eslint-disable */ + +frappe.query_reports["Recruitment Analytics"] = { + "filters": [ + { + "fieldname":"company", + "label": __("Company"), + "fieldtype": "Link", + "options": "Company", + "default": frappe.defaults.get_user_default("Company"), + "reqd": 1 + }, + { + "fieldname":"on_date", + "label": __("On Date"), + "fieldtype": "Date", + "default": frappe.datetime.now_date(), + "reqd": 1, + }, + ] +}; \ No newline at end of file diff --git a/erpnext/hr/report/recruitment_analytics/recruitment_analytics.json b/erpnext/hr/report/recruitment_analytics/recruitment_analytics.json new file mode 100644 index 0000000000..30a8e17eb8 --- /dev/null +++ b/erpnext/hr/report/recruitment_analytics/recruitment_analytics.json @@ -0,0 +1,27 @@ +{ + "add_total_row": 0, + "creation": "2020-05-14 16:28:45.743869", + "disable_prepared_report": 0, + "disabled": 0, + "docstatus": 0, + "doctype": "Report", + "idx": 0, + "is_standard": "Yes", + "modified": "2020-05-14 16:28:45.743869", + "modified_by": "Administrator", + "module": "HR", + "name": "Recruitment Analytics", + "owner": "Administrator", + "prepared_report": 0, + "ref_doctype": "Staffing Plan", + "report_name": "Recruitment Analytics", + "report_type": "Script Report", + "roles": [ + { + "role": "HR Manager" + }, + { + "role": "HR User" + } + ] +} \ No newline at end of file diff --git a/erpnext/hr/report/recruitment_analytics/recruitment_analytics.py b/erpnext/hr/report/recruitment_analytics/recruitment_analytics.py new file mode 100644 index 0000000000..867209436c --- /dev/null +++ b/erpnext/hr/report/recruitment_analytics/recruitment_analytics.py @@ -0,0 +1,188 @@ +# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +from __future__ import unicode_literals +import frappe +from frappe import _ + +def execute(filters=None): + + if not filters: filters = {} + filters = frappe._dict(filters) + + columns = get_columns() + + data = get_data(filters) + + return columns, data + + +def get_columns(): + return [ + { + "label": _("Staffing Plan"), + "fieldtype": "Link", + "fieldname": "staffing_plan", + "options": "Staffing Plan", + "width": 150 + }, + { + "label": _("Job Opening"), + "fieldtype": "Link", + "fieldname": "job_opening", + "options": "Job Opening", + "width": 100 + }, + { + "label": _("Job Applicant"), + "fieldtype": "Link", + "fieldname": "job_applicant", + "options": "Job Applicant", + "width": 150 + }, + { + "label": _("Applicant name"), + "fieldtype": "data", + "fieldname": "applicant_name", + "width": 120 + }, + { + "label": _("Application Status"), + "fieldtype": "Data", + "fieldname": "application_status", + "width": 100 + }, + { + "label": _("Job Offer"), + "fieldtype": "Link", + "fieldname": "job_offer", + "options": "job Offer", + "width": 150 + }, + { + "label": _("Designation"), + "fieldtype": "Data", + "fieldname": "designation", + "width": 100 + }, + { + "label": _("Offer Date"), + "fieldtype": "date", + "fieldname": "offer_date", + "width": 100 + }, + { + "label": _("Job Offer status"), + "fieldtype": "Data", + "fieldname": "job_offer_status", + "width": 150 + } + ] + +def get_data(filters): + data = [] + staffing_plan_details = get_staffing_plan(filters) + staffing_plan_list = list(set([details["name"] for details in staffing_plan_details])) + sp_jo_map , jo_list = get_job_opening(staffing_plan_list) + jo_ja_map , ja_list = get_job_applicant(jo_list) + ja_joff_map = get_job_offer(ja_list) + + for sp in sp_jo_map.keys(): + parent_row = get_parent_row(sp_jo_map, sp, jo_ja_map, ja_joff_map) + data += parent_row + + return data + + +def get_parent_row(sp_jo_map, sp, jo_ja_map, ja_joff_map): + data = [] + for jo in sp_jo_map[sp]: + row = { + "staffing_plan" : sp, + "job_opening" : jo["name"], + } + data.append(row) + child_row = get_child_row( jo["name"], jo_ja_map, ja_joff_map) + data += child_row + return data + +def get_child_row(jo, jo_ja_map, ja_joff_map): + data = [] + for ja in jo_ja_map[jo]: + row = { + "indent":1, + "job_applicant": ja.name, + "applicant_name": ja.applicant_name, + "application_status": ja.status, + } + if ja.name in ja_joff_map.keys(): + jo_detail =ja_joff_map[ja.name][0] + row["job_offer"] = jo_detail.name + row["job_offer_status"] = jo_detail.status + row["offer_date"]= jo_detail.offer_date.strftime("%d-%m-%Y") + row["designation"] = jo_detail.designation + + data.append(row) + return data + +def get_staffing_plan(filters): + + staffing_plan = frappe.db.sql(""" + select + sp.name, sp.department, spd.designation, spd.vacancies, spd.current_count, spd.parent, sp.to_date + from + `tabStaffing Plan Detail` spd , `tabStaffing Plan` sp + where + spd.parent = sp.name + And + sp.to_date > '{0}' + """.format(filters.on_date), as_dict = 1) + + return staffing_plan + +def get_job_opening(sp_list): + + job_openings = frappe.get_all("Job Opening", filters = [["staffing_plan", "IN", sp_list]], fields =["name", "staffing_plan"]) + + sp_jo_map = {} + jo_list = [] + + for openings in job_openings: + if openings.staffing_plan not in sp_jo_map.keys(): + sp_jo_map[openings.staffing_plan] = [openings] + else: + sp_jo_map[openings.staffing_plan].append(openings) + + jo_list.append(openings.name) + + return sp_jo_map, jo_list + +def get_job_applicant(jo_list): + + jo_ja_map = {} + ja_list =[] + + applicants = frappe.get_all("Job Applicant", filters = [["job_title", "IN", jo_list]], fields =["name", "job_title","applicant_name", 'status']) + + for applicant in applicants: + if applicant.job_title not in jo_ja_map.keys(): + jo_ja_map[applicant.job_title] = [applicant] + else: + jo_ja_map[applicant.job_title].append(applicant) + + ja_list.append(applicant.name) + + return jo_ja_map , ja_list + +def get_job_offer(ja_list): + ja_joff_map = {} + + offers = frappe.get_all("Job offer", filters = [["job_applicant", "IN", ja_list]], fields =["name", "job_applicant", "status", 'offer_date', 'designation']) + + for offer in offers: + if offer.job_applicant not in ja_joff_map.keys(): + ja_joff_map[offer.job_applicant] = [offer] + else: + ja_joff_map[offer.job_applicant].append(offer) + + return ja_joff_map \ No newline at end of file