brotherton-erpnext/erpnext/hr/report/employee_exits/employee_exits.py
2021-12-14 22:03:44 +05:30

231 lines
6.2 KiB
Python

# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
# License: MIT. See LICENSE
import frappe
from frappe import _
from frappe.query_builder import Order
from frappe.utils import getdate
def execute(filters=None):
columns = get_columns()
data = get_data(filters)
chart = get_chart_data(data)
report_summary = get_report_summary(data)
return columns, data, None, chart, report_summary
def get_columns():
return [
{
'label': _('Employee'),
'fieldname': 'employee',
'fieldtype': 'Link',
'options': 'Employee',
'width': 150
},
{
'label': _('Employee Name'),
'fieldname': 'employee_name',
'fieldtype': 'Data',
'width': 150
},
{
'label': _('Date of Joining'),
'fieldname': 'date_of_joining',
'fieldtype': 'Date',
'width': 120
},
{
'label': _('Relieving Date'),
'fieldname': 'relieving_date',
'fieldtype': 'Date',
'width': 120
},
{
'label': _('Exit Interview'),
'fieldname': 'exit_interview',
'fieldtype': 'Link',
'options': 'Exit Interview',
'width': 150
},
{
'label': _('Interview Status'),
'fieldname': 'interview_status',
'fieldtype': 'Data',
'width': 130
},
{
'label': _('Final Decision'),
'fieldname': 'employee_status',
'fieldtype': 'Data',
'width': 150
},
{
'label': _('Full and Final Statement'),
'fieldname': 'full_and_final_statement',
'fieldtype': 'Link',
'options': 'Full and Final Statement',
'width': 180
},
{
'label': _('Department'),
'fieldname': 'department',
'fieldtype': 'Link',
'options': 'Department',
'width': 120
},
{
'label': _('Designation'),
'fieldname': 'designation',
'fieldtype': 'Link',
'options': 'Designation',
'width': 120
},
{
'label': _('Reports To'),
'fieldname': 'reports_to',
'fieldtype': 'Link',
'options': 'Employee',
'width': 120
}
]
def get_data(filters):
employee = frappe.qb.DocType('Employee')
interview = frappe.qb.DocType('Exit Interview')
fnf = frappe.qb.DocType('Full and Final Statement')
query = (
frappe.qb.from_(employee)
.left_join(interview).on(interview.employee == employee.name)
.left_join(fnf).on(fnf.employee == employee.name)
.select(
employee.name.as_('employee'), employee.employee_name.as_('employee_name'),
employee.date_of_joining.as_('date_of_joining'), employee.relieving_date.as_('relieving_date'),
employee.department.as_('department'), employee.designation.as_('designation'),
employee.reports_to.as_('reports_to'), interview.name.as_('exit_interview'),
interview.status.as_('interview_status'), interview.employee_status.as_('employee_status'),
interview.reference_document_name.as_('questionnaire'), fnf.name.as_('full_and_final_statement'))
.distinct()
.where(
((employee.relieving_date.isnotnull()) | (employee.relieving_date != ''))
& ((interview.name.isnull()) | ((interview.name.isnotnull()) & (interview.docstatus != 2)))
& ((fnf.name.isnull()) | ((fnf.name.isnotnull()) & (fnf.docstatus != 2)))
).orderby(employee.relieving_date, order=Order.asc)
)
query = get_conditions(filters, query, employee, interview, fnf)
result = query.run(as_dict=True)
return result
def get_conditions(filters, query, employee, interview, fnf):
if filters.get('from_date') and filters.get('to_date'):
query = query.where(employee.relieving_date[getdate(filters.get('from_date')):getdate(filters.get('to_date'))])
elif filters.get('from_date'):
query = query.where(employee.relieving_date >= filters.get('from_date'))
elif filters.get('to_date'):
query = query.where(employee.relieving_date <= filters.get('to_date'))
if filters.get('company'):
query = query.where(employee.company == filters.get('company'))
if filters.get('department'):
query = query.where(employee.department == filters.get('department'))
if filters.get('designation'):
query = query.where(employee.designation == filters.get('designation'))
if filters.get('employee'):
query = query.where(employee.name == filters.get('employee'))
if filters.get('reports_to'):
query = query.where(employee.reports_to == filters.get('reports_to'))
if filters.get('interview_status'):
query = query.where(interview.status == filters.get('interview_status'))
if filters.get('final_decision'):
query = query.where(interview.employee_status == filters.get('final_decision'))
if filters.get('exit_interview_pending'):
query = query.where((interview.name == '') | (interview.name.isnull()))
if filters.get('questionnaire_pending'):
query = query.where((interview.reference_document_name == '') | (interview.reference_document_name.isnull()))
if filters.get('fnf_pending'):
query = query.where((fnf.name == '') | (fnf.name.isnull()))
return query
def get_chart_data(data):
if not data:
return None
retained = 0
exit_confirmed = 0
pending = 0
for entry in data:
if entry.employee_status == 'Employee Retained':
retained += 1
elif entry.employee_status == 'Exit Confirmed':
exit_confirmed += 1
else:
pending += 1
chart = {
'data': {
'labels': [_('Retained'), _('Exit Confirmed'), _('Decision Pending')],
'datasets': [{'name': _('Employee Status'), 'values': [retained, exit_confirmed, pending]}]
},
'type': 'donut',
'colors': ['green', 'red', 'blue'],
}
return chart
def get_report_summary(data):
if not data:
return None
total_resignations = len(data)
interviews_pending = len([entry.name for entry in data if not entry.exit_interview])
fnf_pending = len([entry.name for entry in data if not entry.full_and_final_statement])
questionnaires_pending = len([entry.name for entry in data if not entry.questionnaire])
return [
{
'value': total_resignations,
'label': _('Total Resignations'),
'indicator': 'Red' if total_resignations > 0 else 'Green',
'datatype': 'Int',
},
{
'value': interviews_pending,
'label': _('Pending Interviews'),
'indicator': 'Blue' if interviews_pending > 0 else 'Green',
'datatype': 'Int',
},
{
'value': fnf_pending,
'label': _('Pending FnF'),
'indicator': 'Blue' if fnf_pending > 0 else 'Green',
'datatype': 'Int',
},
{
'value': questionnaires_pending,
'label': _('Pending Questionnaires'),
'indicator': 'Blue' if questionnaires_pending > 0 else 'Green',
'datatype': 'Int'
},
]