Skip to content

Commit

Permalink
fix: payment days calculation for employees joining/leaving mid-month (
Browse files Browse the repository at this point in the history
…#30863)

(cherry picked from commit 924cf77)
  • Loading branch information
ruchamahabal authored and mergify[bot] committed May 3, 2022
1 parent 4db588e commit bc2f1fc
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 6 deletions.
14 changes: 10 additions & 4 deletions erpnext/payroll/doctype/salary_slip/salary_slip.py
Original file line number Diff line number Diff line change
Expand Up @@ -376,13 +376,19 @@ def get_unmarked_days(self, include_holidays_in_total_working_days):
if joining_date and (getdate(self.start_date) < joining_date <= getdate(self.end_date)):
start_date = joining_date
unmarked_days = self.get_unmarked_days_based_on_doj_or_relieving(
unmarked_days, include_holidays_in_total_working_days, self.start_date, joining_date
unmarked_days,
include_holidays_in_total_working_days,
self.start_date,
add_days(joining_date, -1),
)

if relieving_date and (getdate(self.start_date) <= relieving_date < getdate(self.end_date)):
end_date = relieving_date
unmarked_days = self.get_unmarked_days_based_on_doj_or_relieving(
unmarked_days, include_holidays_in_total_working_days, relieving_date, self.end_date
unmarked_days,
include_holidays_in_total_working_days,
add_days(relieving_date, 1),
self.end_date,
)

# exclude days for which attendance has been marked
Expand All @@ -408,10 +414,10 @@ def get_unmarked_days_based_on_doj_or_relieving(
from erpnext.hr.doctype.employee.employee import is_holiday

if include_holidays_in_total_working_days:
unmarked_days -= date_diff(end_date, start_date)
unmarked_days -= date_diff(end_date, start_date) + 1
else:
# exclude only if not holidays
for days in range(date_diff(end_date, start_date)):
for days in range(date_diff(end_date, start_date) + 1):
date = add_days(end_date, -days)
if not is_holiday(self.employee, date):
unmarked_days -= 1
Expand Down
70 changes: 68 additions & 2 deletions erpnext/payroll/doctype/salary_slip/test_salary_slip.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,19 +128,79 @@ def test_payment_days_based_on_attendance(self):
},
)
def test_payment_days_for_mid_joinee_including_holidays(self):
from erpnext.hr.doctype.holiday_list.holiday_list import is_holiday

no_of_days = self.get_no_of_days()
month_start_date, month_end_date = get_first_day(nowdate()), get_last_day(nowdate())

new_emp_id = make_employee("test_payment_days_based_on_joining_date@salary.com")
joining_date, relieving_date = add_days(month_start_date, 3), add_days(month_end_date, -5)

for days in range(date_diff(month_end_date, month_start_date) + 1):
date = add_days(month_start_date, days)
mark_attendance(new_emp_id, date, "Present", ignore_validate=True)

# Case 1: relieving in mid month
frappe.db.set_value(
"Employee",
new_emp_id,
{"date_of_joining": month_start_date, "relieving_date": relieving_date, "status": "Active"},
)

new_ss = make_employee_salary_slip(
"test_payment_days_based_on_joining_date@salary.com",
"Monthly",
"Test Payment Based On Attendence",
)
self.assertEqual(new_ss.payment_days, no_of_days[0] - 5)

# Case 2: joining in mid month
frappe.db.set_value(
"Employee",
new_emp_id,
{"date_of_joining": joining_date, "relieving_date": month_end_date, "status": "Active"},
)

frappe.delete_doc("Salary Slip", new_ss.name, force=True)
new_ss = make_employee_salary_slip(
"test_payment_days_based_on_joining_date@salary.com",
"Monthly",
"Test Payment Based On Attendence",
)
self.assertEqual(new_ss.payment_days, no_of_days[0] - 3)

# Case 3: joining and relieving in mid-month
frappe.db.set_value(
"Employee",
new_emp_id,
{"date_of_joining": joining_date, "relieving_date": relieving_date, "status": "Left"},
)

frappe.delete_doc("Salary Slip", new_ss.name, force=True)
new_ss = make_employee_salary_slip(
"test_payment_days_based_on_joining_date@salary.com",
"Monthly",
"Test Payment Based On Attendence",
)

self.assertEqual(new_ss.total_working_days, no_of_days[0])
self.assertEqual(new_ss.payment_days, no_of_days[0] - 8)

@change_settings(
"Payroll Settings",
{
"payroll_based_on": "Attendance",
"consider_unmarked_attendance_as": "Absent",
"include_holidays_in_total_working_days": True,
},
)
def test_payment_days_for_mid_joinee_including_holidays_and_unmarked_days(self):
# tests mid month joining and relieving along with unmarked days
from erpnext.hr.doctype.holiday_list.holiday_list import is_holiday

no_of_days = self.get_no_of_days()
month_start_date, month_end_date = get_first_day(nowdate()), get_last_day(nowdate())

new_emp_id = make_employee("test_payment_days_based_on_joining_date@salary.com")
joining_date, relieving_date = add_days(month_start_date, 3), add_days(month_end_date, -5)
holidays = 0

for days in range(date_diff(relieving_date, joining_date) + 1):
Expand All @@ -150,6 +210,12 @@ def test_payment_days_for_mid_joinee_including_holidays(self):
else:
holidays += 1

frappe.db.set_value(
"Employee",
new_emp_id,
{"date_of_joining": joining_date, "relieving_date": relieving_date, "status": "Left"},
)

new_ss = make_employee_salary_slip(
"test_payment_days_based_on_joining_date@salary.com",
"Monthly",
Expand Down

0 comments on commit bc2f1fc

Please sign in to comment.