diff --git a/erpnext/controllers/employee_boarding_controller.py b/erpnext/controllers/employee_boarding_controller.py index 1898222916b3..f43c80416f3b 100644 --- a/erpnext/controllers/employee_boarding_controller.py +++ b/erpnext/controllers/employee_boarding_controller.py @@ -5,7 +5,9 @@ from frappe import _ from frappe.desk.form import assign_to from frappe.model.document import Document -from frappe.utils import flt, unique +from frappe.utils import flt, unique, add_days +from erpnext.hr.doctype.holiday_list.holiday_list import is_holiday +from erpnext.hr.doctype.employee.employee import get_holiday_list_for_employee class EmployeeBoardingController(Document): ''' @@ -41,10 +43,14 @@ def on_submit(self): def create_task_and_notify_user(self): # create the task for the given project and assign to the concerned person + holiday_list = self.get_holiday_list() + for activity in self.activities: if activity.task: continue + dates = self.get_task_dates(activity, holiday_list) + task = frappe.get_doc({ 'doctype': 'Task', 'project': self.project, @@ -52,7 +58,9 @@ def create_task_and_notify_user(self): 'description': activity.description, 'department': self.department, 'company': self.company, - 'task_weight': activity.task_weight + 'task_weight': activity.task_weight, + 'exp_start_date': dates[0], + 'exp_end_date': dates[1] }).insert(ignore_permissions=True) activity.db_set('task', task.name) @@ -79,6 +87,36 @@ def create_task_and_notify_user(self): if users: self.assign_task_to_users(task, users) + def get_holiday_list(self): + if self.doctype == 'Employee Separation': + return get_holiday_list_for_employee(self.employee) + else: + if self.employee: + return get_holiday_list_for_employee(self.employee) + else: + if not self.holiday_list: + frappe.throw(_('Please set the Holiday List.'), frappe.MandatoryError) + else: + return self.holiday_list + + def get_task_dates(self, activity, holiday_list): + start_date = end_date = None + + if activity.begin_on: + start_date = add_days(self.boarding_begins_on, activity.begin_on) + start_date = self.update_if_holiday(start_date, holiday_list) + + if activity.duration: + end_date = add_days(self.boarding_begins_on, activity.begin_on + activity.duration) + end_date = self.update_if_holiday(end_date, holiday_list) + + return [start_date, end_date] + + def update_if_holiday(self, date, holiday_list): + while is_holiday(holiday_list, date): + date = add_days(date, 1) + return date + def assign_task_to_users(self, task, users): for user in users: args = { @@ -103,7 +141,8 @@ def on_cancel(self): @frappe.whitelist() def get_onboarding_details(parent, parenttype): return frappe.get_all('Employee Boarding Activity', - fields=['activity_name', 'role', 'user', 'required_for_employee_creation', 'description', 'task_weight'], + fields=['activity_name', 'role', 'user', 'required_for_employee_creation', + 'description', 'task_weight', 'begin_on', 'duration'], filters={'parent': parent, 'parenttype': parenttype}, order_by= 'idx') diff --git a/erpnext/hr/doctype/employee_boarding_activity/employee_boarding_activity.json b/erpnext/hr/doctype/employee_boarding_activity/employee_boarding_activity.json index 65792b42fb89..044a5a9886b3 100644 --- a/erpnext/hr/doctype/employee_boarding_activity/employee_boarding_activity.json +++ b/erpnext/hr/doctype/employee_boarding_activity/employee_boarding_activity.json @@ -1,4 +1,5 @@ { + "actions": [], "creation": "2018-05-09 05:37:18.439763", "doctype": "DocType", "editable_grid": 1, @@ -7,6 +8,8 @@ "activity_name", "user", "role", + "begin_on", + "duration", "column_break_3", "task", "task_weight", @@ -16,12 +19,16 @@ ], "fields": [ { + "columns": 3, "fieldname": "activity_name", "fieldtype": "Data", "in_list_view": 1, - "label": "Activity Name" + "label": "Activity Name", + "reqd": 1 }, { + "columns": 2, + "depends_on": "eval:!doc.role", "fieldname": "user", "fieldtype": "Link", "in_list_view": 1, @@ -29,9 +36,10 @@ "options": "User" }, { + "columns": 1, + "depends_on": "eval:!doc.user", "fieldname": "role", "fieldtype": "Link", - "in_list_view": 1, "label": "Role", "options": "Role" }, @@ -67,10 +75,25 @@ "fieldname": "description", "fieldtype": "Text Editor", "label": "Description" + }, + { + "columns": 2, + "fieldname": "duration", + "fieldtype": "Int", + "in_list_view": 1, + "label": "Duration (Days)" + }, + { + "columns": 2, + "fieldname": "begin_on", + "fieldtype": "Int", + "in_list_view": 1, + "label": "Begin On (Days)" } ], "istable": 1, - "modified": "2019-06-03 19:22:42.965762", + "links": [], + "modified": "2021-07-30 15:55:22.470102", "modified_by": "Administrator", "module": "HR", "name": "Employee Boarding Activity", diff --git a/erpnext/hr/doctype/employee_onboarding/employee_onboarding.json b/erpnext/hr/doctype/employee_onboarding/employee_onboarding.json index 673e228395e8..fd877a68d857 100644 --- a/erpnext/hr/doctype/employee_onboarding/employee_onboarding.json +++ b/erpnext/hr/doctype/employee_onboarding/employee_onboarding.json @@ -8,20 +8,24 @@ "field_order": [ "job_applicant", "job_offer", - "employee_name", - "employee", - "date_of_joining", - "boarding_status", - "notify_users_by_email", - "column_break_7", "employee_onboarding_template", + "column_break_7", "company", + "boarding_status", + "project", + "details_section", + "employee", + "employee_name", "department", "designation", "employee_grade", - "project", + "holiday_list", + "column_break_13", + "date_of_joining", + "boarding_begins_on", "table_for_activity", "activities", + "notify_users_by_email", "amended_from" ], "fields": [ @@ -58,7 +62,8 @@ "fieldname": "date_of_joining", "fieldtype": "Date", "in_list_view": 1, - "label": "Date of Joining" + "label": "Date of Joining", + "reqd": 1 }, { "allow_on_submit": 1, @@ -90,7 +95,8 @@ "fieldname": "company", "fieldtype": "Link", "label": "Company", - "options": "Company" + "options": "Company", + "reqd": 1 }, { "fieldname": "department", @@ -121,7 +127,8 @@ }, { "fieldname": "table_for_activity", - "fieldtype": "Section Break" + "fieldtype": "Section Break", + "label": "Onboarding Activities" }, { "allow_on_submit": 1, @@ -138,11 +145,32 @@ "options": "Employee Onboarding", "print_hide": 1, "read_only": 1 + }, + { + "fieldname": "details_section", + "fieldtype": "Section Break", + "label": "Employee Details" + }, + { + "fieldname": "column_break_13", + "fieldtype": "Column Break" + }, + { + "fieldname": "boarding_begins_on", + "fieldtype": "Date", + "label": "Onboarding Begins On", + "reqd": 1 + }, + { + "fieldname": "holiday_list", + "fieldtype": "Link", + "label": "Holiday List", + "options": "Holiday List" } ], "is_submittable": 1, "links": [], - "modified": "2021-06-03 18:01:51.097927", + "modified": "2021-07-30 14:55:04.560683", "modified_by": "Administrator", "module": "HR", "name": "Employee Onboarding", diff --git a/erpnext/hr/doctype/employee_onboarding/test_employee_onboarding.py b/erpnext/hr/doctype/employee_onboarding/test_employee_onboarding.py index 0445270b9fff..ea46aa24a6c0 100644 --- a/erpnext/hr/doctype/employee_onboarding/test_employee_onboarding.py +++ b/erpnext/hr/doctype/employee_onboarding/test_employee_onboarding.py @@ -5,8 +5,9 @@ import frappe import unittest -from frappe.utils import nowdate +from frappe.utils import getdate from erpnext.hr.doctype.employee_onboarding.employee_onboarding import make_employee +from erpnext.payroll.doctype.salary_slip.test_salary_slip import make_holiday_list from erpnext.hr.doctype.employee_onboarding.employee_onboarding import IncompleteTaskError from erpnext.hr.doctype.job_offer.test_job_offer import create_job_offer @@ -46,7 +47,7 @@ def test_employee_onboarding_incomplete_task(self): onboarding.reload() employee = make_employee(onboarding.name) employee.first_name = employee.employee_name - employee.date_of_joining = nowdate() + employee.date_of_joining = getdate() employee.date_of_birth = '1990-05-08' employee.gender = 'Female' employee.insert() @@ -82,11 +83,14 @@ def get_job_offer(applicant_name): def create_employee_onboarding(): applicant = get_job_applicant() job_offer = get_job_offer(applicant.name) + holiday_list = make_holiday_list() onboarding = frappe.new_doc('Employee Onboarding') onboarding.job_applicant = applicant.name onboarding.job_offer = job_offer.name + onboarding.date_of_joining = onboarding.boarding_begins_on = getdate() onboarding.company = '_Test Company' + onboarding.holiday_list = holiday_list onboarding.designation = 'Researcher' onboarding.append('activities', { 'activity_name': 'Assign ID Card', diff --git a/erpnext/hr/doctype/employee_onboarding_activity/__init__.py b/erpnext/hr/doctype/employee_onboarding_activity/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/erpnext/hr/doctype/employee_onboarding_activity/employee_onboarding_activity.json b/erpnext/hr/doctype/employee_onboarding_activity/employee_onboarding_activity.json deleted file mode 100644 index 4e91b7238443..000000000000 --- a/erpnext/hr/doctype/employee_onboarding_activity/employee_onboarding_activity.json +++ /dev/null @@ -1,290 +0,0 @@ -{ - "allow_copy": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, - "beta": 0, - "creation": "2018-05-09 05:37:18.439763", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "", - "editable_grid": 1, - "engine": "InnoDB", - "fields": [ - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "activity_name", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Activity Name", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "user", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "User", - "length": 0, - "no_copy": 0, - "options": "User", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "role", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Role", - "length": 0, - "no_copy": 0, - "options": "Role", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_3", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval: doc.parenttype == \"Employee Onboarding\"", - "fieldname": "completed", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Completed", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "required_for_employee_creation", - "fieldtype": "Check", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Required for Employee Creation", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "section_break_6", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "description", - "fieldtype": "Text Editor", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Description", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 1, - "max_attachments": 0, - "modified": "2018-05-09 06:15:41.768236", - "modified_by": "Administrator", - "module": "HR", - "name": "Employee Onboarding Activity", - "name_case": "", - "owner": "Administrator", - "permissions": [], - "quick_entry": 1, - "read_only": 0, - "read_only_onload": 0, - "show_name_in_global_search": 0, - "sort_field": "modified", - "sort_order": "DESC", - "track_changes": 1, - "track_seen": 0 -} \ No newline at end of file diff --git a/erpnext/hr/doctype/employee_onboarding_activity/employee_onboarding_activity.py b/erpnext/hr/doctype/employee_onboarding_activity/employee_onboarding_activity.py deleted file mode 100644 index d17063181918..000000000000 --- a/erpnext/hr/doctype/employee_onboarding_activity/employee_onboarding_activity.py +++ /dev/null @@ -1,10 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors -# For license information, please see license.txt - -from __future__ import unicode_literals -import frappe -from frappe.model.document import Document - -class EmployeeOnboardingActivity(Document): - pass diff --git a/erpnext/hr/doctype/employee_separation/employee_separation.json b/erpnext/hr/doctype/employee_separation/employee_separation.json index c10da5c35e77..c240493e8204 100644 --- a/erpnext/hr/doctype/employee_separation/employee_separation.json +++ b/erpnext/hr/doctype/employee_separation/employee_separation.json @@ -15,6 +15,7 @@ "company", "boarding_status", "resignation_letter_date", + "boarding_begins_on", "project", "table_for_activity", "employee_separation_template", @@ -144,11 +145,17 @@ "options": "Employee Separation", "print_hide": 1, "read_only": 1 + }, + { + "fieldname": "boarding_begins_on", + "fieldtype": "Date", + "label": "Separation Begins On", + "reqd": 1 } ], "is_submittable": 1, "links": [], - "modified": "2021-06-03 18:02:54.007313", + "modified": "2021-07-30 14:03:51.218791", "modified_by": "Administrator", "module": "HR", "name": "Employee Separation", diff --git a/erpnext/hr/doctype/employee_separation/test_employee_separation.py b/erpnext/hr/doctype/employee_separation/test_employee_separation.py index d63501a9314c..2c11cbbe2c73 100644 --- a/erpnext/hr/doctype/employee_separation/test_employee_separation.py +++ b/erpnext/hr/doctype/employee_separation/test_employee_separation.py @@ -4,6 +4,7 @@ from __future__ import unicode_literals import frappe +from frappe.utils import getdate import unittest test_dependencies = ['Employee Onboarding'] @@ -34,9 +35,10 @@ def tearDown(self): doc.delete() def create_employee_separation(): - employee = frappe.db.get_value('Employee', {'status': 'Active'}) + employee = frappe.db.get_value('Employee', {'status': 'Active', 'company': '_Test Company'}) separation = frappe.new_doc('Employee Separation') separation.employee = employee + separation.boarding_begins_on = getdate() separation.company = '_Test Company' separation.append('activities', { 'activity_name': 'Deactivate Employee', diff --git a/erpnext/payroll/doctype/salary_slip/test_salary_slip.py b/erpnext/payroll/doctype/salary_slip/test_salary_slip.py index d730fcf1fa93..636ec0b5a66c 100644 --- a/erpnext/payroll/doctype/salary_slip/test_salary_slip.py +++ b/erpnext/payroll/doctype/salary_slip/test_salary_slip.py @@ -828,7 +828,8 @@ def setup_test(): def make_holiday_list(): fiscal_year = get_fiscal_year(nowdate(), company=erpnext.get_default_company()) - if not frappe.db.get_value("Holiday List", "Salary Slip Test Holiday List"): + holiday_list = frappe.db.exists("Holiday List", "Salary Slip Test Holiday List") + if not holiday_list: holiday_list = frappe.get_doc({ "doctype": "Holiday List", "holiday_list_name": "Salary Slip Test Holiday List", @@ -838,3 +839,6 @@ def make_holiday_list(): }).insert() holiday_list.get_weekly_off_dates() holiday_list.save() + holiday_list = holiday_list.name + + return holiday_list