Merge branch 'develop' into issue_25414
diff --git a/erpnext/payroll/doctype/salary_slip/salary_slip.py b/erpnext/payroll/doctype/salary_slip/salary_slip.py
index 1922329..6a7f72b 100644
--- a/erpnext/payroll/doctype/salary_slip/salary_slip.py
+++ b/erpnext/payroll/doctype/salary_slip/salary_slip.py
@@ -375,13 +375,19 @@
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
@@ -407,10 +413,10 @@
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
diff --git a/erpnext/payroll/doctype/salary_slip/test_salary_slip.py b/erpnext/payroll/doctype/salary_slip/test_salary_slip.py
index 869ea83..1bc3741 100644
--- a/erpnext/payroll/doctype/salary_slip/test_salary_slip.py
+++ b/erpnext/payroll/doctype/salary_slip/test_salary_slip.py
@@ -128,6 +128,72 @@
},
)
def test_payment_days_for_mid_joinee_including_holidays(self):
+ 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()
@@ -135,12 +201,6 @@
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)
- frappe.db.set_value(
- "Employee",
- new_emp_id,
- {"date_of_joining": joining_date, "relieving_date": relieving_date, "status": "Left"},
- )
-
holidays = 0
for days in range(date_diff(relieving_date, joining_date) + 1):
@@ -150,6 +210,12 @@
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",