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