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",