From 6c68493c17d3ec0da6b2d40a3a9a20d827ecaf2c Mon Sep 17 00:00:00 2001 From: krantheman Date: Tue, 15 Oct 2024 16:45:40 +0530 Subject: [PATCH 1/3] fix(Leave Policy Assignment): calculation of months passed (cherry picked from commit 128ffd7b9a9d8e49ed4024f848d9d3b7e720fe38) --- .../leave_policy_assignment/leave_policy_assignment.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/hrms/hr/doctype/leave_policy_assignment/leave_policy_assignment.py b/hrms/hr/doctype/leave_policy_assignment/leave_policy_assignment.py index 600bbae7aa..1f9c405d7e 100644 --- a/hrms/hr/doctype/leave_policy_assignment/leave_policy_assignment.py +++ b/hrms/hr/doctype/leave_policy_assignment/leave_policy_assignment.py @@ -180,7 +180,11 @@ def _get_months_passed(current_date, from_date, consider_current_month): months_passed += 1 elif current_date.year > from_date.year: - months_passed = (12 - from_date.month) + current_date.month + months_passed = ( + (12 - from_date.month) + + (current_date.year - from_date.year - 1) * 12 + + current_date.month + ) if consider_current_month: months_passed += 1 From de730c60c6c344e85a2111d6a66155c500689ff9 Mon Sep 17 00:00:00 2001 From: krantheman Date: Tue, 15 Oct 2024 17:49:03 +0530 Subject: [PATCH 2/3] test: add test_get_leaves_for_passed_months (cherry picked from commit 9dce0a639df171bee3635fbc36c037c3cb70c75e) --- .../leave_policy_assignment.py | 25 ++++++----- .../test_leave_policy_assignment.py | 44 +++++++++++++++++++ hrms/hr/doctype/leave_type/test_leave_type.py | 7 +-- 3 files changed, 63 insertions(+), 13 deletions(-) diff --git a/hrms/hr/doctype/leave_policy_assignment/leave_policy_assignment.py b/hrms/hr/doctype/leave_policy_assignment/leave_policy_assignment.py index 1f9c405d7e..d9b7863420 100644 --- a/hrms/hr/doctype/leave_policy_assignment/leave_policy_assignment.py +++ b/hrms/hr/doctype/leave_policy_assignment/leave_policy_assignment.py @@ -288,16 +288,7 @@ def create_assignment_for_multiple_employees(employees, data): failed = [] for employee in employees: - assignment = frappe.new_doc("Leave Policy Assignment") - assignment.employee = employee - assignment.assignment_based_on = data.assignment_based_on or None - assignment.leave_policy = data.leave_policy - assignment.effective_from = getdate(data.effective_from) or None - assignment.effective_to = getdate(data.effective_to) or None - assignment.leave_period = data.leave_period or None - assignment.carry_forward = data.carry_forward - assignment.save() - + assignment = create_assignment(employee, data) savepoint = "before_assignment_submission" try: frappe.db.savepoint(savepoint) @@ -315,6 +306,20 @@ def create_assignment_for_multiple_employees(employees, data): return docs_name +@frappe.whitelist() +def create_assignment(employee, data): + assignment = frappe.new_doc("Leave Policy Assignment") + assignment.employee = employee + assignment.assignment_based_on = data.assignment_based_on or None + assignment.leave_policy = data.leave_policy + assignment.effective_from = getdate(data.effective_from) or None + assignment.effective_to = getdate(data.effective_to) or None + assignment.leave_period = data.leave_period or None + assignment.carry_forward = data.carry_forward + assignment.save() + return assignment + + def show_assignment_submission_status(failed): frappe.clear_messages() assignment_list = [get_link_to_form("Leave Policy Assignment", entry) for entry in failed] diff --git a/hrms/hr/doctype/leave_policy_assignment/test_leave_policy_assignment.py b/hrms/hr/doctype/leave_policy_assignment/test_leave_policy_assignment.py index ecece69b48..7c9ddd55ac 100644 --- a/hrms/hr/doctype/leave_policy_assignment/test_leave_policy_assignment.py +++ b/hrms/hr/doctype/leave_policy_assignment/test_leave_policy_assignment.py @@ -6,10 +6,13 @@ from frappe.utils import add_months, get_first_day, get_year_ending, getdate from hrms.hr.doctype.leave_application.test_leave_application import get_employee, get_leave_period +from hrms.hr.doctype.leave_period.test_leave_period import create_leave_period from hrms.hr.doctype.leave_policy.test_leave_policy import create_leave_policy from hrms.hr.doctype.leave_policy_assignment.leave_policy_assignment import ( + create_assignment, create_assignment_for_multiple_employees, ) +from hrms.hr.doctype.leave_type.test_leave_type import create_leave_type test_dependencies = ["Employee"] @@ -20,6 +23,7 @@ def setUp(self): "Leave Period", "Leave Application", "Leave Allocation", + "Leave Policy", "Leave Policy Assignment", "Leave Ledger Entry", ]: @@ -117,6 +121,46 @@ def test_pro_rated_leave_allocation(self): # pro-rated leave allocation for 9 months self.assertEqual(allocation, 9) + # tests no of leaves for passed months if assignment is based on Leave Period / Joining Date + def test_get_leaves_for_passed_months(self): + annual_allocation = 10 + leave_type = create_leave_type(leave_type_name="_Test Earned Leave", is_earned_leave=True) + leave_policy = create_leave_policy(leave_type=leave_type, annual_allocation=annual_allocation) + leave_policy.submit() + + data = { + "assignment_based_on": "Joining Date", + "leave_policy": leave_policy.name, + } + + self.employee.date_of_joining = add_months(getdate(), -6) + self.employee.save() + assignment = create_assignment(self.employee.name, frappe._dict(data)) + new_leaves_allocated = assignment.get_leaves_for_passed_months( + annual_allocation, leave_type, self.employee.date_of_joining + ) + self.assertEqual(new_leaves_allocated, 5) + + self.employee.date_of_joining = add_months(getdate(), -36) + self.employee.save() + assignment = create_assignment(self.employee.name, frappe._dict(data)) + new_leaves_allocated = assignment.get_leaves_for_passed_months( + annual_allocation, leave_type, self.employee.date_of_joining + ) + self.assertEqual(new_leaves_allocated, 30) + + leave_period = create_leave_period(add_months(getdate(), -24), getdate()) + data = { + "assignment_based_on": "Leave Period", + "leave_policy": leave_policy.name, + "leave_period": leave_period.name, + } + assignment = create_assignment(self.employee.name, frappe._dict(data)) + new_leaves_allocated = assignment.get_leaves_for_passed_months( + annual_allocation, leave_type, self.employee.date_of_joining + ) + self.assertEqual(new_leaves_allocated, 20) + def test_pro_rated_leave_allocation_for_custom_date_range(self): leave_type = frappe.get_doc( { diff --git a/hrms/hr/doctype/leave_type/test_leave_type.py b/hrms/hr/doctype/leave_type/test_leave_type.py index 56bf641d26..e765f77ec5 100644 --- a/hrms/hr/doctype/leave_type/test_leave_type.py +++ b/hrms/hr/doctype/leave_type/test_leave_type.py @@ -8,13 +8,14 @@ def create_leave_type(**args): args = frappe._dict(args) - if frappe.db.exists("Leave Type", args.leave_type_name): - frappe.delete_doc("Leave Type", args.leave_type_name, force=True) + leave_type_name = args.leave_type_name or "_Test Leave Type" + if frappe.db.exists("Leave Type", leave_type_name): + frappe.delete_doc("Leave Type", leave_type_name, force=True) leave_type = frappe.get_doc( { "doctype": "Leave Type", - "leave_type_name": args.leave_type_name or "_Test Leave Type", + "leave_type_name": leave_type_name, "include_holiday": args.include_holidays or 1, "allow_encashment": args.allow_encashment or 0, "is_earned_leave": args.is_earned_leave or 0, From 8e1c0267a1eb30b1520518010836a22a35807b0b Mon Sep 17 00:00:00 2001 From: krantheman Date: Thu, 17 Oct 2024 15:24:30 +0530 Subject: [PATCH 3/3] test: fix test condition (cherry picked from commit b7d1f840d11bc769e579c200da0af119472f859b) --- .../test_leave_policy_assignment.py | 11 +++++++---- hrms/hr/doctype/leave_type/test_leave_type.py | 1 + 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/hrms/hr/doctype/leave_policy_assignment/test_leave_policy_assignment.py b/hrms/hr/doctype/leave_policy_assignment/test_leave_policy_assignment.py index 7c9ddd55ac..4416090b87 100644 --- a/hrms/hr/doctype/leave_policy_assignment/test_leave_policy_assignment.py +++ b/hrms/hr/doctype/leave_policy_assignment/test_leave_policy_assignment.py @@ -123,8 +123,11 @@ def test_pro_rated_leave_allocation(self): # tests no of leaves for passed months if assignment is based on Leave Period / Joining Date def test_get_leaves_for_passed_months(self): + first_day = get_first_day(getdate()) annual_allocation = 10 - leave_type = create_leave_type(leave_type_name="_Test Earned Leave", is_earned_leave=True) + leave_type = create_leave_type( + leave_type_name="_Test Earned Leave", is_earned_leave=True, allocate_on_day="First Day" + ) leave_policy = create_leave_policy(leave_type=leave_type, annual_allocation=annual_allocation) leave_policy.submit() @@ -133,7 +136,7 @@ def test_get_leaves_for_passed_months(self): "leave_policy": leave_policy.name, } - self.employee.date_of_joining = add_months(getdate(), -6) + self.employee.date_of_joining = add_months(first_day, -5) self.employee.save() assignment = create_assignment(self.employee.name, frappe._dict(data)) new_leaves_allocated = assignment.get_leaves_for_passed_months( @@ -141,7 +144,7 @@ def test_get_leaves_for_passed_months(self): ) self.assertEqual(new_leaves_allocated, 5) - self.employee.date_of_joining = add_months(getdate(), -36) + self.employee.date_of_joining = add_months(first_day, -35) self.employee.save() assignment = create_assignment(self.employee.name, frappe._dict(data)) new_leaves_allocated = assignment.get_leaves_for_passed_months( @@ -149,7 +152,7 @@ def test_get_leaves_for_passed_months(self): ) self.assertEqual(new_leaves_allocated, 30) - leave_period = create_leave_period(add_months(getdate(), -24), getdate()) + leave_period = create_leave_period(add_months(first_day, -23), first_day) data = { "assignment_based_on": "Leave Period", "leave_policy": leave_policy.name, diff --git a/hrms/hr/doctype/leave_type/test_leave_type.py b/hrms/hr/doctype/leave_type/test_leave_type.py index e765f77ec5..b0aefa73f2 100644 --- a/hrms/hr/doctype/leave_type/test_leave_type.py +++ b/hrms/hr/doctype/leave_type/test_leave_type.py @@ -27,6 +27,7 @@ def create_leave_type(**args): "earning_component": "Leave Encashment", "max_leaves_allowed": args.max_leaves_allowed, "maximum_carry_forwarded_leaves": args.maximum_carry_forwarded_leaves, + "allocate_on_day": args.allocate_on_day or "Last Day", } )