Skip to content

Commit

Permalink
Merge pull request #330 from frappe/version-14-hotfix
Browse files Browse the repository at this point in the history
  • Loading branch information
ruchamahabal authored Feb 16, 2023
2 parents b29a458 + a0eaf18 commit c1f7072
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 76 deletions.
2 changes: 1 addition & 1 deletion hrms/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "14.0.1"
__version__ = "14.0.2"
10 changes: 7 additions & 3 deletions hrms/hr/doctype/leave_allocation/test_earned_leaves.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
calculate_pro_rated_leaves,
create_assignment_for_multiple_employees,
)
from hrms.hr.utils import allocate_earned_leaves
from hrms.hr.utils import allocate_earned_leaves, round_earned_leaves
from hrms.payroll.doctype.salary_slip.test_salary_slip import make_holiday_list
from hrms.tests.test_utils import get_first_sunday

Expand Down Expand Up @@ -260,7 +260,9 @@ def test_allocate_on_date_of_joining(self):
self.employee, allocate_on_day="Date of Joining", start_date=start_date
)
leaves_allocated = get_allocated_leaves(leave_policy_assignments[0])
pro_rated_leave = calculate_pro_rated_leaves(1, doj, start_date, end_date)
pro_rated_leave = round_earned_leaves(
calculate_pro_rated_leaves(1, doj, start_date, end_date), "0.5"
)
self.assertEqual(leaves_allocated, pro_rated_leave)

# Case 2: Doesn't allocate before the current month's doj (via scheduler)
Expand Down Expand Up @@ -308,7 +310,9 @@ def test_pro_rated_allocation_via_scheduler(self):
frappe.flags.current_date = add_days(doj, -1)
allocate_earned_leaves()
leaves_allocated = get_allocated_leaves(leave_policy_assignments[0])
pro_rated_leave = calculate_pro_rated_leaves(1, doj, start_date, get_last_day(start_date))
pro_rated_leave = round_earned_leaves(
calculate_pro_rated_leaves(1, doj, start_date, get_last_day(start_date)), "0.5"
)
self.assertEqual(leaves_allocated, pro_rated_leave)

@set_holiday_list("Salary Slip Test Holiday List", "_Test Company")
Expand Down
110 changes: 59 additions & 51 deletions hrms/hr/doctype/leave_policy_assignment/leave_policy_assignment.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,10 +136,10 @@ def get_new_leaves(self, new_leaves_allocated, leave_details, date_of_joining):
)

# Earned Leaves and Compensatory Leaves are allocated by scheduler, initially allocate 0
if leave_details.is_compensatory == 1:
if leave_details.is_compensatory:
new_leaves_allocated = 0

elif leave_details.is_earned_leave == 1:
elif leave_details.is_earned_leave:
if not self.assignment_based_on:
new_leaves_allocated = 0
else:
Expand All @@ -148,86 +148,94 @@ def get_new_leaves(self, new_leaves_allocated, leave_details, date_of_joining):
new_leaves_allocated, leave_details, date_of_joining
)

new_leaves_allocated = self.get_pro_rated_leaves(
date_of_joining, leave_details, new_leaves_allocated
)
else:
# calculate pro-rated leaves for other leave types
new_leaves_allocated = calculate_pro_rated_leaves(
new_leaves_allocated,
date_of_joining,
self.effective_from,
self.effective_to,
is_earned_leave=False,
)

return flt(new_leaves_allocated, precision)

def get_leaves_for_passed_months(self, new_leaves_allocated, leave_details, date_of_joining):
from hrms.hr.utils import get_monthly_earned_leave

current_date = frappe.flags.current_date or getdate()
if current_date > getdate(self.effective_to):
current_date = getdate(self.effective_to)
def _get_current_and_from_date():
current_date = frappe.flags.current_date or getdate()
if current_date > getdate(self.effective_to):
current_date = getdate(self.effective_to)

from_date = getdate(self.effective_from)
if getdate(date_of_joining) > from_date:
from_date = getdate(date_of_joining)

return current_date, from_date

from_date = getdate(self.effective_from)
if getdate(date_of_joining) > from_date:
from_date = getdate(date_of_joining)
def _get_months_passed(current_date, from_date, consider_current_month):
months_passed = 0
if current_date.year == from_date.year and current_date.month >= from_date.month:
months_passed = current_date.month - from_date.month
if consider_current_month:
months_passed += 1

months_passed = 0
elif current_date.year > from_date.year:
months_passed = (12 - from_date.month) + current_date.month
if consider_current_month:
months_passed += 1

if current_date.year == from_date.year and current_date.month >= from_date.month:
months_passed = current_date.month - from_date.month
if is_earned_leave_applicable_for_current_month(date_of_joining, leave_details.allocate_on_day):
months_passed += 1
return months_passed

elif current_date.year > from_date.year:
months_passed = (12 - from_date.month) + current_date.month
if is_earned_leave_applicable_for_current_month(date_of_joining, leave_details.allocate_on_day):
months_passed += 1
def _get_pro_rata_period_end_date(consider_current_month):
# for earned leave, pro-rata period ends on the last day of the month
date = getdate(frappe.flags.current_date) or getdate()
if consider_current_month:
period_end_date = get_last_day(date)
else:
period_end_date = get_last_day(add_months(date, -1))

return period_end_date

consider_current_month = is_earned_leave_applicable_for_current_month(
date_of_joining, leave_details.allocate_on_day
)
current_date, from_date = _get_current_and_from_date()
months_passed = _get_months_passed(current_date, from_date, consider_current_month)

if months_passed > 0:
period_end_date = _get_pro_rata_period_end_date(consider_current_month)
monthly_earned_leave = get_monthly_earned_leave(
date_of_joining,
new_leaves_allocated,
leave_details.earned_leave_frequency,
leave_details.rounding,
self.effective_from,
period_end_date,
)
new_leaves_allocated = monthly_earned_leave * months_passed
else:
new_leaves_allocated = 0

return new_leaves_allocated

def get_pro_rated_leaves(self, date_of_joining, leave_details, new_leaves_allocated):
"""
Calculates pro-rated leaves for the months passed
for employees joining after the beginning of the given leave period
"""
# no need to prorate if employee joined before the leave period
if not new_leaves_allocated or getdate(date_of_joining) <= getdate(self.effective_from):
return new_leaves_allocated

# for earned leave, pro-rata period ends on the last day of the month
date = getdate(frappe.flags.current_date) or getdate()

if leave_details.is_earned_leave:
if is_earned_leave_applicable_for_current_month(date_of_joining, leave_details.allocate_on_day):
period_end_date = get_last_day(date)
else:
period_end_date = get_last_day(add_months(date, -1))
else:
period_end_date = self.effective_to

new_leaves_allocated = calculate_pro_rated_leaves(
new_leaves_allocated, date_of_joining, self.effective_from, period_end_date
)

# don't round earned leaves
if not leave_details.is_earned_leave:
new_leaves_allocated = ceil(new_leaves_allocated)

return new_leaves_allocated

def calculate_pro_rated_leaves(
leaves, date_of_joining, period_start_date, period_end_date, is_earned_leave=False
):
if not leaves or getdate(date_of_joining) <= getdate(period_start_date):
return leaves

def calculate_pro_rated_leaves(leaves, date_of_joining, period_start_date, period_end_date):
precision = cint(frappe.db.get_single_value("System Settings", "float_precision", cache=True))
actual_period = date_diff(period_end_date, date_of_joining) + 1
complete_period = date_diff(period_end_date, period_start_date) + 1

leaves *= actual_period / complete_period

return flt(leaves, precision)
if is_earned_leave:
return flt(leaves, precision)
return ceil(leaves)


def is_earned_leave_applicable_for_current_month(date_of_joining, allocate_on_day):
Expand Down
54 changes: 33 additions & 21 deletions hrms/hr/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -334,21 +334,9 @@ def allocate_earned_leaves():


def update_previous_leave_allocation(allocation, annual_allocation, e_leave_type, date_of_joining):
def _calculate_pro_rated_leaves(earned_leaves):
today_date = frappe.flags.current_date or getdate()
period_end_date = get_last_day(today_date)
period_start_date = get_first_day(today_date)

if period_start_date <= date_of_joining <= period_end_date:
return calculate_pro_rated_leaves(
earned_leaves, date_of_joining, period_start_date, period_end_date
)
return earned_leaves

earned_leaves = get_monthly_earned_leave(
annual_allocation, e_leave_type.earned_leave_frequency, e_leave_type.rounding
date_of_joining, annual_allocation, e_leave_type.earned_leave_frequency, e_leave_type.rounding
)
earned_leaves = _calculate_pro_rated_leaves(earned_leaves)

allocation = frappe.get_doc("Leave Allocation", allocation.name)
new_allocation = flt(allocation.total_leaves_allocated) + flt(earned_leaves)
Expand All @@ -372,18 +360,42 @@ def _calculate_pro_rated_leaves(earned_leaves):
allocation.add_comment(comment_type="Info", text=text)


def get_monthly_earned_leave(annual_leaves, frequency, rounding):
def get_monthly_earned_leave(
date_of_joining,
annual_leaves,
frequency,
rounding,
period_start_date=None,
period_end_date=None,
):
earned_leaves = 0.0
divide_by_frequency = {"Yearly": 1, "Half-Yearly": 2, "Quarterly": 4, "Monthly": 12}
if annual_leaves:
earned_leaves = flt(annual_leaves) / divide_by_frequency[frequency]
if rounding:
if rounding == "0.25":
earned_leaves = round(earned_leaves * 4) / 4
elif rounding == "0.5":
earned_leaves = round(earned_leaves * 2) / 2
else:
earned_leaves = round(earned_leaves)

if not (period_start_date or period_end_date):
today_date = frappe.flags.current_date or getdate()
period_end_date = get_last_day(today_date)
period_start_date = get_first_day(today_date)

earned_leaves = calculate_pro_rated_leaves(
earned_leaves, date_of_joining, period_start_date, period_end_date, is_earned_leave=True
)
earned_leaves = round_earned_leaves(earned_leaves, rounding)

return earned_leaves


def round_earned_leaves(earned_leaves, rounding):
if not rounding:
return earned_leaves

if rounding == "0.25":
earned_leaves = round(earned_leaves * 4) / 4
elif rounding == "0.5":
earned_leaves = round(earned_leaves * 2) / 2
else:
earned_leaves = round(earned_leaves)

return earned_leaves

Expand Down

0 comments on commit c1f7072

Please sign in to comment.