blob: f43c80416f3b729ebfad55a341f8f21091338544 [file] [log] [blame]
Rucha Mahabal357657f2021-06-24 13:00:50 +05301# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors
2# License: GNU General Public License v3. See license.txt
3
Rucha Mahabal357657f2021-06-24 13:00:50 +05304import frappe
5from frappe import _
6from frappe.desk.form import assign_to
7from frappe.model.document import Document
Rucha Mahabal71b7c632021-08-27 11:12:24 +05308from frappe.utils import flt, unique, add_days
9from erpnext.hr.doctype.holiday_list.holiday_list import is_holiday
10from erpnext.hr.doctype.employee.employee import get_holiday_list_for_employee
Rucha Mahabal357657f2021-06-24 13:00:50 +053011
12class EmployeeBoardingController(Document):
13 '''
14 Create the project and the task for the boarding process
15 Assign to the concerned person and roles as per the onboarding/separation template
16 '''
17 def validate(self):
18 # remove the task if linked before submitting the form
19 if self.amended_from:
20 for activity in self.activities:
21 activity.task = ''
22
23 def on_submit(self):
24 # create the project for the given employee onboarding
25 project_name = _(self.doctype) + ' : '
26 if self.doctype == 'Employee Onboarding':
27 project_name += self.job_applicant
28 else:
29 project_name += self.employee
30
31 project = frappe.get_doc({
32 'doctype': 'Project',
33 'project_name': project_name,
34 'expected_start_date': self.date_of_joining if self.doctype == 'Employee Onboarding' else self.resignation_letter_date,
35 'department': self.department,
36 'company': self.company
37 }).insert(ignore_permissions=True, ignore_mandatory=True)
38
39 self.db_set('project', project.name)
40 self.db_set('boarding_status', 'Pending')
41 self.reload()
42 self.create_task_and_notify_user()
43
44 def create_task_and_notify_user(self):
45 # create the task for the given project and assign to the concerned person
Rucha Mahabal71b7c632021-08-27 11:12:24 +053046 holiday_list = self.get_holiday_list()
47
Rucha Mahabal357657f2021-06-24 13:00:50 +053048 for activity in self.activities:
49 if activity.task:
50 continue
51
Rucha Mahabal71b7c632021-08-27 11:12:24 +053052 dates = self.get_task_dates(activity, holiday_list)
53
Rucha Mahabal357657f2021-06-24 13:00:50 +053054 task = frappe.get_doc({
55 'doctype': 'Task',
56 'project': self.project,
57 'subject': activity.activity_name + ' : ' + self.employee_name,
58 'description': activity.description,
59 'department': self.department,
60 'company': self.company,
Rucha Mahabal71b7c632021-08-27 11:12:24 +053061 'task_weight': activity.task_weight,
62 'exp_start_date': dates[0],
63 'exp_end_date': dates[1]
Rucha Mahabal357657f2021-06-24 13:00:50 +053064 }).insert(ignore_permissions=True)
65 activity.db_set('task', task.name)
66
67 users = [activity.user] if activity.user else []
68 if activity.role:
69 user_list = frappe.db.sql_list('''
70 SELECT
71 DISTINCT(has_role.parent)
72 FROM
73 `tabHas Role` has_role
74 LEFT JOIN `tabUser` user
75 ON has_role.parent = user.name
76 WHERE
77 has_role.parenttype = 'User'
78 AND user.enabled = 1
79 AND has_role.role = %s
80 ''', activity.role)
81 users = unique(users + user_list)
82
83 if 'Administrator' in users:
84 users.remove('Administrator')
85
86 # assign the task the users
87 if users:
88 self.assign_task_to_users(task, users)
89
Rucha Mahabal71b7c632021-08-27 11:12:24 +053090 def get_holiday_list(self):
91 if self.doctype == 'Employee Separation':
92 return get_holiday_list_for_employee(self.employee)
93 else:
94 if self.employee:
95 return get_holiday_list_for_employee(self.employee)
96 else:
97 if not self.holiday_list:
98 frappe.throw(_('Please set the Holiday List.'), frappe.MandatoryError)
99 else:
100 return self.holiday_list
101
102 def get_task_dates(self, activity, holiday_list):
103 start_date = end_date = None
104
105 if activity.begin_on:
106 start_date = add_days(self.boarding_begins_on, activity.begin_on)
107 start_date = self.update_if_holiday(start_date, holiday_list)
108
109 if activity.duration:
110 end_date = add_days(self.boarding_begins_on, activity.begin_on + activity.duration)
111 end_date = self.update_if_holiday(end_date, holiday_list)
112
113 return [start_date, end_date]
114
115 def update_if_holiday(self, date, holiday_list):
116 while is_holiday(holiday_list, date):
117 date = add_days(date, 1)
118 return date
119
Rucha Mahabal357657f2021-06-24 13:00:50 +0530120 def assign_task_to_users(self, task, users):
121 for user in users:
122 args = {
123 'assign_to': [user],
124 'doctype': task.doctype,
125 'name': task.name,
126 'description': task.description or task.subject,
127 'notify': self.notify_users_by_email
128 }
129 assign_to.add(args)
130
131 def on_cancel(self):
132 # delete task project
133 for task in frappe.get_all('Task', filters={'project': self.project}):
134 frappe.delete_doc('Task', task.name, force=1)
135 frappe.delete_doc('Project', self.project, force=1)
136 self.db_set('project', '')
137 for activity in self.activities:
138 activity.db_set('task', '')
139
140
141@frappe.whitelist()
142def get_onboarding_details(parent, parenttype):
143 return frappe.get_all('Employee Boarding Activity',
Rucha Mahabal71b7c632021-08-27 11:12:24 +0530144 fields=['activity_name', 'role', 'user', 'required_for_employee_creation',
145 'description', 'task_weight', 'begin_on', 'duration'],
Rucha Mahabal357657f2021-06-24 13:00:50 +0530146 filters={'parent': parent, 'parenttype': parenttype},
147 order_by= 'idx')
148
149
150def update_employee_boarding_status(project):
151 employee_onboarding = frappe.db.exists('Employee Onboarding', {'project': project.name})
152 employee_separation = frappe.db.exists('Employee Separation', {'project': project.name})
153
154 if not (employee_onboarding or employee_separation):
155 return
156
157 status = 'Pending'
158 if flt(project.percent_complete) > 0.0 and flt(project.percent_complete) < 100.0:
159 status = 'In Process'
160 elif flt(project.percent_complete) == 100.0:
161 status = 'Completed'
162
163 if employee_onboarding:
164 frappe.db.set_value('Employee Onboarding', employee_onboarding, 'boarding_status', status)
165 elif employee_separation:
166 frappe.db.set_value('Employee Separation', employee_separation, 'boarding_status', status)