diff --git a/erpnext/payroll/doctype/salary_slip/salary_slip.py b/erpnext/payroll/doctype/salary_slip/salary_slip.py index 302c0d2853a..966df76c6ee 100644 --- a/erpnext/payroll/doctype/salary_slip/salary_slip.py +++ b/erpnext/payroll/doctype/salary_slip/salary_slip.py @@ -315,7 +315,7 @@ class SalarySlip(TransactionBase): ) working_days = date_diff(self.end_date, self.start_date) + 1 - working_days_list = [add_days(self.start_date, i) for i in range(working_days)] + working_days_list = [add_days(self.start_date)for i in range(working_days)] if for_preview: self.total_working_days = working_days @@ -324,6 +324,8 @@ class SalarySlip(TransactionBase): holidays = self.get_holidays_for_employee(self.start_date, self.end_date) + joining_date, relieving_date = self.get_joining_and_relieving_date() + if not cint(include_holidays_in_total_working_days): working_days -= len(holidays) working_days_list = [cstr(day) for day in working_days_list if cstr(day) not in holidays] @@ -335,10 +337,10 @@ class SalarySlip(TransactionBase): frappe.throw(_("Please set Payroll based on in Payroll settings")) if payroll_based_on == "Attendance": - actual_lwp, absent = self.calculate_lwp_ppl_and_absent_days_based_on_attendance(holidays) + actual_lwp, absent = self.calculate_lwp_ppl_and_absent_days_based_on_attendance(holidays, relieving_date) self.absent_days = absent else: - actual_lwp = self.calculate_lwp_or_ppl_based_on_leave_application(holidays, working_days_list) + actual_lwp = self.calculate_lwp_or_ppl_based_on_leave_application(holidays, working_days_list, relieving_date) if not lwp: lwp = actual_lwp @@ -461,7 +463,7 @@ class SalarySlip(TransactionBase): def get_holidays_for_employee(self, start_date, end_date): return get_holiday_dates_for_employee(self.employee, start_date, end_date) - def calculate_lwp_or_ppl_based_on_leave_application(self, holidays, working_days_list): + def calculate_lwp_or_ppl_based_on_leave_application(self, holidays, working_days_list, relieving_date=None): lwp = 0 daily_wages_fraction_for_half_day = ( @@ -469,6 +471,9 @@ class SalarySlip(TransactionBase): ) for d in working_days_list: + if relieving_date and getdate(d) > getdate(relieving_date): + break + leave = get_lwp_or_ppl_for_date(d, self.employee, holidays) if leave: @@ -488,10 +493,15 @@ class SalarySlip(TransactionBase): return lwp - def calculate_lwp_ppl_and_absent_days_based_on_attendance(self, holidays): + def calculate_lwp_ppl_and_absent_days_based_on_attendance(self, holidays, relieving_date=None): lwp = 0 absent = 0 + end_date = self.end_date + + if relieving_date: + end_date = relieving_date + daily_wages_fraction_for_half_day = ( flt(frappe.db.get_value("Payroll Settings", None, "daily_wages_fraction_for_half_day")) or 0.5 ) @@ -516,7 +526,7 @@ class SalarySlip(TransactionBase): AND docstatus = 1 AND attendance_date between %s and %s """, - values=(self.employee, self.start_date, self.end_date), + values=(self.employee, self.start_date, end_date), as_dict=1, ) diff --git a/erpnext/payroll/doctype/salary_slip/test_salary_slip.py b/erpnext/payroll/doctype/salary_slip/test_salary_slip.py index 32d0c7ed08f..84f436a03b6 100644 --- a/erpnext/payroll/doctype/salary_slip/test_salary_slip.py +++ b/erpnext/payroll/doctype/salary_slip/test_salary_slip.py @@ -1129,6 +1129,35 @@ class TestSalarySlip(FrappeTestCase): self.assertEqual(deduction.amount, rounded(monthly_tax_amount)) + @change_settings("Payroll Settings", {"payroll_based_on": "Leave"}) + def test_lwp_calculation_based_on_relieving_date(self): + emp_id = make_employee("test_lwp_based_on_relieving_date@salary.com") + frappe.db.set_value("Employee", emp_id, {"relieving_date": None, "status": "Active"}) + frappe.db.set_value("Leave Type", "Leave Without Pay", "include_holiday", 0) + + month_start_date = get_first_day(nowdate()) + first_sunday = get_first_sunday(for_date=month_start_date) + relieving_date = add_days(first_sunday, 10) + leave_start_date = add_days(first_sunday, 16) + leave_end_date = add_days(leave_start_date, 2) + + make_leave_application(emp_id, leave_start_date, leave_end_date, "Leave Without Pay") + + frappe.db.set_value("Employee", emp_id, {"relieving_date": relieving_date, "status": "Left"}) + + ss = make_employee_salary_slip( + "test_lwp_based_on_relieving_date@salary.com", + "Monthly", + "Test Payment Based On Leave Application", + ) + + holidays = ss.get_holidays_for_employee(month_start_date, relieving_date) + days_between_start_and_relieving = date_diff(relieving_date, month_start_date) + 1 + + self.assertEqual(ss.leave_without_pay, 0) + + self.assertEqual(ss.payment_days, (days_between_start_and_relieving - len(holidays))) + def get_no_of_days(): no_of_days_in_month = calendar.monthrange(getdate(nowdate()).year, getdate(nowdate()).month) no_of_holidays_in_month = len(