Repository: frappe/erpnext
Pull request: fix: wrong payment days in salary slip for employees joining/leaving during mid payroll dates
In case an employee joins/leaves mid payroll dates, their payment days would be calculated wrong.
This PR aims to consider joining and relieving dates while calculating payment days.

Closes #27943 

Salary slip of an employee who joined 3 days after payroll start date and was present for the rest of the month:
<details>
<summary>Payroll Settings:</summary>

![image](https://user-images.githubusercontent.com/52111700/151705856-0ec7e7bf-20e8-40c1-8bfd-657ce074e24f.png)
</details>

<details>
<summary>Before:</summary>

Absent days: 3
![image](https://user-images.githubusercontent.com/52111700/151705873-cbf46633-b893-44d3-b90b-373bbc76b7ac.png)
</details>

<details>
<summary>After:</summary>

Absent days: 0
![image](https://user-images.githubusercontent.com/52111700/151709677-29c5b6aa-d1c9-488f-8944-615e5b32e1b3.png)
</details>

Total working days remain unaffected as it it based on payroll processing dates and many components are calculated on it's basis.

Problem statement:
In Salary Slip, negative payment days issue for Left Employees.
**Description Of the Issue:**
In version 13.11.1  , When we created the salary slip against the left employees it shows negative payment days and Earning & Deduction table is not fetched for respective left employees.
**Version:**
version 13.11.1

Hints from issue discussion:
![Screenshot 2021-10-25 at 3 10 07 PM](https://user-images.githubusercontent.com/75108667/138673302-37c6c6bc-5d72-4bdd-bef3-9d70d38074fd.png)



DESCRIPTION:
1)The employee is relieved in the date of 09-07-2021 , payment days for that employee is two days only , instead  it shows -19 (negative value of payment days).

![Screenshot 2021-10-25 at 3 24 38 PM](https://user-images.githubusercontent.com/75108667/138674894-796f6f79-8a8d-4399-aa13-aacdc18307a0.png)
2)Then Earnings and Deduction table is also not fetched.

Commit message: chore: optimize comparission logic

Patch to review:
diff --git a/erpnext/payroll/doctype/salary_slip/salary_slip.py b/erpnext/payroll/doctype/salary_slip/salary_slip.py
index b035292c0b6a..542d5c809833 100644
--- a/erpnext/payroll/doctype/salary_slip/salary_slip.py
+++ b/erpnext/payroll/doctype/salary_slip/salary_slip.py
@@ -321,13 +321,25 @@ def get_working_days_details(self, joining_date=None, relieving_date=None, lwp=N
 			self.payment_days = 0
 
 	def get_unmarked_days(self):
-		marked_days = frappe.get_all("Attendance", filters = {
-					"attendance_date": ["between", [self.start_date, self.end_date]],
-					"employee": self.employee,
-					"docstatus": 1
-				}, fields = ["COUNT(*) as marked_days"])[0].marked_days
+		unmarked_days = self.total_working_days
+		joining_date, relieving_date = frappe.get_cached_value("Employee", self.employee,
+			["date_of_joining", "relieving_date"])
+
+		if joining_date:
+			if getdate(self.start_date) < joining_date <= getdate(self.end_date):
+				unmarked_days -= date_diff(joining_date, self.start_date)
+
+		if relieving_date:
+			if getdate(self.start_date) <= relieving_date < getdate(self.end_date):
+				unmarked_days -= date_diff(relieving_date, self.end_date)
+
+		unmarked_days -= frappe.get_all("Attendance", filters = {
+			"attendance_date": ["between", [self.start_date, self.end_date]],
+			"employee": self.employee,
+			"docstatus": 1
+		}, fields = ["COUNT(*) as marked_days"])[0].marked_days
 
-		return self.total_working_days - marked_days
+		return unmarked_days
 
 
 	def get_payment_days(self, joining_date, relieving_date, include_holidays_in_total_working_days):


Code review comments:
diff_hunk: @@ -321,13 +321,25 @@ def get_working_days_details(self, joining_date=None, relieving_date=None, lwp=N
 			self.payment_days = 0
 
 	def get_unmarked_days(self):
-		marked_days = frappe.get_all("Attendance", filters = {
-					"attendance_date": ["between", [self.start_date, self.end_date]],
-					"employee": self.employee,
-					"docstatus": 1
-				}, fields = ["COUNT(*) as marked_days"])[0].marked_days
+		unmarked_days = self.total_working_days
+		joining_date, relieving_date = frappe.get_cached_value("Employee", self.employee,
+			["date_of_joining", "relieving_date"])
+
+		if joining_date:
+			if getdate(self.start_date) < joining_date <= getdate(self.end_date):
+				unmarked_days -= date_diff(joining_date, self.start_date)
+
+		if relieving_date:
+			if getdate(self.start_date) <= relieving_date < getdate(self.end_date):
+				unmarked_days -= date_diff(relieving_date, self.end_date)
path: erpnext/payroll/doctype/salary_slip/salary_slip.py
text: @user1:
```suggestion
				unmarked_days -= date_diff(self.end_date, relieving_date)
```

`date_diff` calculates difference as `end_date - start_date`:

https://github.com/frappe/frappe/blob/acac60d061bbb1ee4957ca613c92e1526098aa3b/frappe/utils/data.py#L166-L167

So in this case since `end_date` would be after `relieving_date` its the end date

@user1:
Thanks for the fix. 

- Can you also add separate tests for both these cases: Date of Joining and Relieving Date. 
- Also, the description is fairly understandable, but can you update the description with a screenshot depicting the before (negative days calculated) and after (payment days calculation working fine).

@author:
Sure, will do.