Rucha Mahabal | 357657f | 2021-06-24 13:00:50 +0530 | [diff] [blame] | 1 | # Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors |
| 2 | # License: GNU General Public License v3. See license.txt |
| 3 | |
Rucha Mahabal | 357657f | 2021-06-24 13:00:50 +0530 | [diff] [blame] | 4 | import frappe |
| 5 | from frappe import _ |
| 6 | from frappe.desk.form import assign_to |
| 7 | from frappe.model.document import Document |
Chillar Anand | 915b343 | 2021-09-02 16:44:59 +0530 | [diff] [blame] | 8 | from frappe.utils import add_days, flt, unique |
| 9 | |
Rucha Mahabal | 3fe2ef6 | 2022-06-15 12:43:45 +0530 | [diff] [blame] | 10 | from erpnext.setup.doctype.employee.employee import get_holiday_list_for_employee |
| 11 | from erpnext.setup.doctype.holiday_list.holiday_list import is_holiday |
Chillar Anand | 915b343 | 2021-09-02 16:44:59 +0530 | [diff] [blame] | 12 | |
Rucha Mahabal | 357657f | 2021-06-24 13:00:50 +0530 | [diff] [blame] | 13 | |
| 14 | class EmployeeBoardingController(Document): |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 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 | |
Rucha Mahabal | 357657f | 2021-06-24 13:00:50 +0530 | [diff] [blame] | 20 | def validate(self): |
| 21 | # remove the task if linked before submitting the form |
| 22 | if self.amended_from: |
| 23 | for activity in self.activities: |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 24 | activity.task = "" |
Rucha Mahabal | 357657f | 2021-06-24 13:00:50 +0530 | [diff] [blame] | 25 | |
| 26 | def on_submit(self): |
| 27 | # create the project for the given employee onboarding |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 28 | project_name = _(self.doctype) + " : " |
| 29 | if self.doctype == "Employee Onboarding": |
Rucha Mahabal | 357657f | 2021-06-24 13:00:50 +0530 | [diff] [blame] | 30 | project_name += self.job_applicant |
| 31 | else: |
| 32 | project_name += self.employee |
| 33 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 34 | project = frappe.get_doc( |
| 35 | { |
| 36 | "doctype": "Project", |
| 37 | "project_name": project_name, |
| 38 | "expected_start_date": self.date_of_joining |
| 39 | if self.doctype == "Employee Onboarding" |
| 40 | else self.resignation_letter_date, |
| 41 | "department": self.department, |
| 42 | "company": self.company, |
| 43 | } |
| 44 | ).insert(ignore_permissions=True, ignore_mandatory=True) |
Rucha Mahabal | 357657f | 2021-06-24 13:00:50 +0530 | [diff] [blame] | 45 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 46 | self.db_set("project", project.name) |
| 47 | self.db_set("boarding_status", "Pending") |
Rucha Mahabal | 357657f | 2021-06-24 13:00:50 +0530 | [diff] [blame] | 48 | self.reload() |
| 49 | self.create_task_and_notify_user() |
| 50 | |
| 51 | def create_task_and_notify_user(self): |
| 52 | # create the task for the given project and assign to the concerned person |
Rucha Mahabal | 71b7c63 | 2021-08-27 11:12:24 +0530 | [diff] [blame] | 53 | holiday_list = self.get_holiday_list() |
| 54 | |
Rucha Mahabal | 357657f | 2021-06-24 13:00:50 +0530 | [diff] [blame] | 55 | for activity in self.activities: |
| 56 | if activity.task: |
| 57 | continue |
| 58 | |
Rucha Mahabal | 71b7c63 | 2021-08-27 11:12:24 +0530 | [diff] [blame] | 59 | dates = self.get_task_dates(activity, holiday_list) |
| 60 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 61 | task = frappe.get_doc( |
| 62 | { |
| 63 | "doctype": "Task", |
| 64 | "project": self.project, |
| 65 | "subject": activity.activity_name + " : " + self.employee_name, |
| 66 | "description": activity.description, |
| 67 | "department": self.department, |
| 68 | "company": self.company, |
| 69 | "task_weight": activity.task_weight, |
| 70 | "exp_start_date": dates[0], |
| 71 | "exp_end_date": dates[1], |
| 72 | } |
| 73 | ).insert(ignore_permissions=True) |
| 74 | activity.db_set("task", task.name) |
Rucha Mahabal | 357657f | 2021-06-24 13:00:50 +0530 | [diff] [blame] | 75 | |
| 76 | users = [activity.user] if activity.user else [] |
| 77 | if activity.role: |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 78 | user_list = frappe.db.sql_list( |
| 79 | """ |
Rucha Mahabal | 357657f | 2021-06-24 13:00:50 +0530 | [diff] [blame] | 80 | SELECT |
| 81 | DISTINCT(has_role.parent) |
| 82 | FROM |
| 83 | `tabHas Role` has_role |
| 84 | LEFT JOIN `tabUser` user |
| 85 | ON has_role.parent = user.name |
| 86 | WHERE |
| 87 | has_role.parenttype = 'User' |
| 88 | AND user.enabled = 1 |
| 89 | AND has_role.role = %s |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 90 | """, |
| 91 | activity.role, |
| 92 | ) |
Rucha Mahabal | 357657f | 2021-06-24 13:00:50 +0530 | [diff] [blame] | 93 | users = unique(users + user_list) |
| 94 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 95 | if "Administrator" in users: |
| 96 | users.remove("Administrator") |
Rucha Mahabal | 357657f | 2021-06-24 13:00:50 +0530 | [diff] [blame] | 97 | |
| 98 | # assign the task the users |
| 99 | if users: |
| 100 | self.assign_task_to_users(task, users) |
| 101 | |
Rucha Mahabal | 71b7c63 | 2021-08-27 11:12:24 +0530 | [diff] [blame] | 102 | def get_holiday_list(self): |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 103 | if self.doctype == "Employee Separation": |
Rucha Mahabal | 71b7c63 | 2021-08-27 11:12:24 +0530 | [diff] [blame] | 104 | return get_holiday_list_for_employee(self.employee) |
| 105 | else: |
| 106 | if self.employee: |
| 107 | return get_holiday_list_for_employee(self.employee) |
| 108 | else: |
| 109 | if not self.holiday_list: |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 110 | frappe.throw(_("Please set the Holiday List."), frappe.MandatoryError) |
Rucha Mahabal | 71b7c63 | 2021-08-27 11:12:24 +0530 | [diff] [blame] | 111 | else: |
| 112 | return self.holiday_list |
| 113 | |
| 114 | def get_task_dates(self, activity, holiday_list): |
| 115 | start_date = end_date = None |
| 116 | |
Rucha Mahabal | 4738367 | 2022-02-21 22:54:46 +0530 | [diff] [blame] | 117 | if activity.begin_on is not None: |
Rucha Mahabal | 71b7c63 | 2021-08-27 11:12:24 +0530 | [diff] [blame] | 118 | start_date = add_days(self.boarding_begins_on, activity.begin_on) |
| 119 | start_date = self.update_if_holiday(start_date, holiday_list) |
| 120 | |
Rucha Mahabal | 4738367 | 2022-02-21 22:54:46 +0530 | [diff] [blame] | 121 | if activity.duration is not None: |
Rucha Mahabal | 71b7c63 | 2021-08-27 11:12:24 +0530 | [diff] [blame] | 122 | end_date = add_days(self.boarding_begins_on, activity.begin_on + activity.duration) |
| 123 | end_date = self.update_if_holiday(end_date, holiday_list) |
| 124 | |
| 125 | return [start_date, end_date] |
| 126 | |
| 127 | def update_if_holiday(self, date, holiday_list): |
| 128 | while is_holiday(holiday_list, date): |
| 129 | date = add_days(date, 1) |
| 130 | return date |
| 131 | |
Rucha Mahabal | 357657f | 2021-06-24 13:00:50 +0530 | [diff] [blame] | 132 | def assign_task_to_users(self, task, users): |
| 133 | for user in users: |
| 134 | args = { |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 135 | "assign_to": [user], |
| 136 | "doctype": task.doctype, |
| 137 | "name": task.name, |
| 138 | "description": task.description or task.subject, |
| 139 | "notify": self.notify_users_by_email, |
Rucha Mahabal | 357657f | 2021-06-24 13:00:50 +0530 | [diff] [blame] | 140 | } |
| 141 | assign_to.add(args) |
| 142 | |
| 143 | def on_cancel(self): |
| 144 | # delete task project |
Rucha Mahabal | 36882f3 | 2022-01-29 15:27:36 +0530 | [diff] [blame] | 145 | project = self.project |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 146 | for task in frappe.get_all("Task", filters={"project": project}): |
| 147 | frappe.delete_doc("Task", task.name, force=1) |
| 148 | frappe.delete_doc("Project", project, force=1) |
| 149 | self.db_set("project", "") |
Rucha Mahabal | 357657f | 2021-06-24 13:00:50 +0530 | [diff] [blame] | 150 | for activity in self.activities: |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 151 | activity.db_set("task", "") |
Rucha Mahabal | 357657f | 2021-06-24 13:00:50 +0530 | [diff] [blame] | 152 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 153 | frappe.msgprint( |
| 154 | _("Linked Project {} and Tasks deleted.").format(project), alert=True, indicator="blue" |
| 155 | ) |
Rucha Mahabal | 36882f3 | 2022-01-29 15:27:36 +0530 | [diff] [blame] | 156 | |
Rucha Mahabal | 357657f | 2021-06-24 13:00:50 +0530 | [diff] [blame] | 157 | |
| 158 | @frappe.whitelist() |
| 159 | def get_onboarding_details(parent, parenttype): |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 160 | return frappe.get_all( |
| 161 | "Employee Boarding Activity", |
| 162 | fields=[ |
| 163 | "activity_name", |
| 164 | "role", |
| 165 | "user", |
| 166 | "required_for_employee_creation", |
| 167 | "description", |
| 168 | "task_weight", |
| 169 | "begin_on", |
| 170 | "duration", |
| 171 | ], |
| 172 | filters={"parent": parent, "parenttype": parenttype}, |
| 173 | order_by="idx", |
| 174 | ) |
Rucha Mahabal | 357657f | 2021-06-24 13:00:50 +0530 | [diff] [blame] | 175 | |
| 176 | |
| 177 | def update_employee_boarding_status(project): |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 178 | employee_onboarding = frappe.db.exists("Employee Onboarding", {"project": project.name}) |
| 179 | employee_separation = frappe.db.exists("Employee Separation", {"project": project.name}) |
Rucha Mahabal | 357657f | 2021-06-24 13:00:50 +0530 | [diff] [blame] | 180 | |
| 181 | if not (employee_onboarding or employee_separation): |
| 182 | return |
| 183 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 184 | status = "Pending" |
Rucha Mahabal | 357657f | 2021-06-24 13:00:50 +0530 | [diff] [blame] | 185 | if flt(project.percent_complete) > 0.0 and flt(project.percent_complete) < 100.0: |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 186 | status = "In Process" |
Rucha Mahabal | 357657f | 2021-06-24 13:00:50 +0530 | [diff] [blame] | 187 | elif flt(project.percent_complete) == 100.0: |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 188 | status = "Completed" |
Rucha Mahabal | 357657f | 2021-06-24 13:00:50 +0530 | [diff] [blame] | 189 | |
| 190 | if employee_onboarding: |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 191 | frappe.db.set_value("Employee Onboarding", employee_onboarding, "boarding_status", status) |
Rucha Mahabal | 357657f | 2021-06-24 13:00:50 +0530 | [diff] [blame] | 192 | elif employee_separation: |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 193 | frappe.db.set_value("Employee Separation", employee_separation, "boarding_status", status) |