From ac18b900aa60c996b1317ff2243a09bae5515f9f Mon Sep 17 00:00:00 2001 From: Khaled Bin Amir Date: Sun, 3 Aug 2025 12:04:47 +0600 Subject: [PATCH 1/6] Update payroll_settings.json Consider Present on Holidays --- hrms/payroll/doctype/payroll_settings/payroll_settings.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hrms/payroll/doctype/payroll_settings/payroll_settings.json b/hrms/payroll/doctype/payroll_settings/payroll_settings.json index 60224e6a41..5f7b91c2dc 100644 --- a/hrms/payroll/doctype/payroll_settings/payroll_settings.json +++ b/hrms/payroll/doctype/payroll_settings/payroll_settings.json @@ -146,7 +146,7 @@ { "default": "0", "depends_on": "include_holidays_in_total_working_days", - "description": "If enabled, deducts payment days for absent attendance on holidays. By default, holidays are considered as paid", + "description": "Depends on whether holidays are included in total working days. If holidays are included: Deducts pay for 'Absent' attendance on a holiday. If holidays are not included: Credits 'Present' attendance on a holiday against an absent day.", "fieldname": "consider_marked_attendance_on_holidays", "fieldtype": "Check", "label": "Consider Marked Attendance on Holidays" @@ -198,4 +198,4 @@ "sort_order": "ASC", "states": [], "track_changes": 1 -} \ No newline at end of file +} From 938089ca8652e0157d49f702e0dfa1a534798489 Mon Sep 17 00:00:00 2001 From: Khaled Bin Amir Date: Sun, 3 Aug 2025 12:06:50 +0600 Subject: [PATCH 2/6] Update payroll_settings.json --- hrms/payroll/doctype/payroll_settings/payroll_settings.json | 1 - 1 file changed, 1 deletion(-) diff --git a/hrms/payroll/doctype/payroll_settings/payroll_settings.json b/hrms/payroll/doctype/payroll_settings/payroll_settings.json index 5f7b91c2dc..9ef44b1b2a 100644 --- a/hrms/payroll/doctype/payroll_settings/payroll_settings.json +++ b/hrms/payroll/doctype/payroll_settings/payroll_settings.json @@ -145,7 +145,6 @@ }, { "default": "0", - "depends_on": "include_holidays_in_total_working_days", "description": "Depends on whether holidays are included in total working days. If holidays are included: Deducts pay for 'Absent' attendance on a holiday. If holidays are not included: Credits 'Present' attendance on a holiday against an absent day.", "fieldname": "consider_marked_attendance_on_holidays", "fieldtype": "Check", From b2e21e79dd13b5305fe0cf23c6755a7a7baefa2c Mon Sep 17 00:00:00 2001 From: Khaled Bin Amir Date: Sun, 3 Aug 2025 12:48:32 +0600 Subject: [PATCH 3/6] Update salary_slip.py Consider Present on Holidays --- .../doctype/salary_slip/salary_slip.py | 44 ++++++++++++------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/hrms/payroll/doctype/salary_slip/salary_slip.py b/hrms/payroll/doctype/salary_slip/salary_slip.py index b7d026a31d..a513facb32 100644 --- a/hrms/payroll/doctype/salary_slip/salary_slip.py +++ b/hrms/payroll/doctype/salary_slip/salary_slip.py @@ -428,11 +428,16 @@ def get_working_days_details(self, lwp=None, for_preview=0): as_dict=1, ) - consider_marked_attendance_on_holidays = ( + consider_absent_on_holidays = ( payroll_settings.include_holidays_in_total_working_days and payroll_settings.consider_marked_attendance_on_holidays ) + credit_present_on_holidays = ( + not payroll_settings.include_holidays_in_total_working_days + and payroll_settings.consider_marked_attendance_on_holidays + ) + daily_wages_fraction_for_half_day = flt(payroll_settings.daily_wages_fraction_for_half_day) or 0.5 working_days = date_diff(self.end_date, self.start_date) + 1 @@ -456,7 +461,7 @@ def get_working_days_details(self, lwp=None, for_preview=0): if payroll_settings.payroll_based_on == "Attendance": actual_lwp, absent = self.calculate_lwp_ppl_and_absent_days_based_on_attendance( - holidays, daily_wages_fraction_for_half_day, consider_marked_attendance_on_holidays + holidays, daily_wages_fraction_for_half_day, consider_absent_on_holidays, credit_present_on_holidays ) self.absent_days = absent else: @@ -491,10 +496,10 @@ def get_working_days_details(self, lwp=None, for_preview=0): unmarked_days = self.get_unmarked_days( payroll_settings.include_holidays_in_total_working_days, holidays ) - self.absent_days += unmarked_days # will be treated as absent + self.absent_days += unmarked_days self.payment_days -= unmarked_days half_absent_days = self.get_half_absent_days( - consider_marked_attendance_on_holidays, + consider_absent_on_holidays holidays, ) self.absent_days += half_absent_days * daily_wages_fraction_for_half_day @@ -517,7 +522,7 @@ def get_unmarked_days( return unmarked_days - def get_half_absent_days(self, consider_marked_attendance_on_holidays, holidays): + def get_half_absent_days(self, include_holidays_in_total_working_days, consider_absent_on_holidays, holidays): """Calculates the number of half absent days for an employee within a date range""" Attendance = frappe.qb.DocType("Attendance") query = ( @@ -531,7 +536,7 @@ def get_half_absent_days(self, consider_marked_attendance_on_holidays, holidays) & (Attendance.half_day_status == "Absent") ) ) - if (not consider_marked_attendance_on_holidays) and holidays: + if (not consider_absent_on_holidays) and holidays: query = query.where(Attendance.attendance_date.notin(holidays)) return query.run()[0][0] @@ -688,8 +693,7 @@ def get_employee_attendance(self, start_date, end_date): attendance.half_day_status, ) .where( - (attendance.status.isin(["Absent", "Half Day", "On Leave"])) - & (attendance.employee == self.employee) + (attendance.employee == self.employee) & (attendance.docstatus == 1) & (attendance.attendance_date.between(start_date, end_date)) ) @@ -698,7 +702,7 @@ def get_employee_attendance(self, start_date, end_date): return attendance_details def calculate_lwp_ppl_and_absent_days_based_on_attendance( - self, holidays, daily_wages_fraction_for_half_day, consider_marked_attendance_on_holidays + self, holidays, daily_wages_fraction_for_half_day, consider_absent_on_holidays, credit_present_on_holidays ): lwp = 0 absent = 0 @@ -716,15 +720,23 @@ def calculate_lwp_ppl_and_absent_days_based_on_attendance( ): continue - # skip counting absent on holidays - if not consider_marked_attendance_on_holidays and getdate(d.attendance_date) in holidays: - if d.status in ["Absent", "Half Day"] or ( - d.leave_type - and d.leave_type in leave_type_map.keys() - and not leave_type_map[d.leave_type]["include_holiday"] - ): + # Check if attendance date is a holiday + if getdate(d.attendance_date) in holidays: + if credit_present_on_holidays: + if d.status == "Present": + absent -= 1 + elif d.status == "Half Day": + absent -= (1 - daily_wages_fraction_for_half_day) continue + elif not consider_absent_on_holidays: + if d.status in ["Absent", "Half Day"] or ( + d.leave_type + and d.leave_type in leave_type_map.keys() + and not leave_type_map[d.leave_type]["include_holiday"] + ): + continue + if d.leave_type: fraction_of_daily_salary_per_leave = leave_type_map[d.leave_type][ "fraction_of_daily_salary_per_leave" From 2992aaca362d89f65fbfc00b4245f5c6d7cb0336 Mon Sep 17 00:00:00 2001 From: Khaled Bin Amir Date: Sun, 3 Aug 2025 12:58:03 +0600 Subject: [PATCH 4/6] Update salary_slip.py Consider Present on Holiday --- hrms/payroll/doctype/salary_slip/salary_slip.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hrms/payroll/doctype/salary_slip/salary_slip.py b/hrms/payroll/doctype/salary_slip/salary_slip.py index a513facb32..8eb5f1a78e 100644 --- a/hrms/payroll/doctype/salary_slip/salary_slip.py +++ b/hrms/payroll/doctype/salary_slip/salary_slip.py @@ -499,8 +499,8 @@ def get_working_days_details(self, lwp=None, for_preview=0): self.absent_days += unmarked_days self.payment_days -= unmarked_days half_absent_days = self.get_half_absent_days( - consider_absent_on_holidays - holidays, + consider_absent_on_holidays, + holidays ) self.absent_days += half_absent_days * daily_wages_fraction_for_half_day self.payment_days -= half_absent_days * daily_wages_fraction_for_half_day @@ -522,7 +522,7 @@ def get_unmarked_days( return unmarked_days - def get_half_absent_days(self, include_holidays_in_total_working_days, consider_absent_on_holidays, holidays): + def get_half_absent_days(self, consider_absent_on_holidays, holidays): """Calculates the number of half absent days for an employee within a date range""" Attendance = frappe.qb.DocType("Attendance") query = ( From cb9cd3eafa4bc95cfc6c1def602acc0bc7f2905a Mon Sep 17 00:00:00 2001 From: Khaled Bin Amir Date: Sun, 3 Aug 2025 23:38:22 +0600 Subject: [PATCH 5/6] Update salary_slip.py --- .../doctype/salary_slip/salary_slip.py | 38 ++++++++----------- 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/hrms/payroll/doctype/salary_slip/salary_slip.py b/hrms/payroll/doctype/salary_slip/salary_slip.py index 8eb5f1a78e..b2e507c5b9 100644 --- a/hrms/payroll/doctype/salary_slip/salary_slip.py +++ b/hrms/payroll/doctype/salary_slip/salary_slip.py @@ -713,11 +713,7 @@ def calculate_lwp_ppl_and_absent_days_based_on_attendance( ) for d in attendance_details: - if ( - d.status in ("Half Day", "On Leave") - and d.leave_type - and d.leave_type not in leave_type_map.keys() - ): + if d.leave_type and d.leave_type not in leave_type_map.keys(): continue # Check if attendance date is a holiday @@ -731,9 +727,7 @@ def calculate_lwp_ppl_and_absent_days_based_on_attendance( elif not consider_absent_on_holidays: if d.status in ["Absent", "Half Day"] or ( - d.leave_type - and d.leave_type in leave_type_map.keys() - and not leave_type_map[d.leave_type]["include_holiday"] + d.leave_type and not leave_type_map[d.leave_type]["include_holiday"] ): continue @@ -742,22 +736,22 @@ def calculate_lwp_ppl_and_absent_days_based_on_attendance( "fraction_of_daily_salary_per_leave" ] - if d.status == "Half Day" and d.leave_type and d.leave_type in leave_type_map.keys(): - equivalent_lwp = 1 - daily_wages_fraction_for_half_day + if d.status == "Half Day": + equivalent_lwp = 1 - daily_wages_fraction_for_half_day - if leave_type_map[d.leave_type]["is_ppl"]: - equivalent_lwp *= ( - fraction_of_daily_salary_per_leave if fraction_of_daily_salary_per_leave else 1 - ) - lwp += equivalent_lwp + if leave_type_map[d.leave_type]["is_ppl"]: + equivalent_lwp *= ( + fraction_of_daily_salary_per_leave if fraction_of_daily_salary_per_leave else 1 + ) + lwp += equivalent_lwp - elif d.status == "On Leave" and d.leave_type and d.leave_type in leave_type_map.keys(): - equivalent_lwp = 1 - if leave_type_map[d.leave_type]["is_ppl"]: - equivalent_lwp *= ( - fraction_of_daily_salary_per_leave if fraction_of_daily_salary_per_leave else 1 - ) - lwp += equivalent_lwp + elif d.status == "On Leave": + equivalent_lwp = 1 + if leave_type_map[d.leave_type]["is_ppl"]: + equivalent_lwp *= ( + fraction_of_daily_salary_per_leave if fraction_of_daily_salary_per_leave else 1 + ) + lwp += equivalent_lwp elif d.status == "Absent": absent += 1 From 51e3f830ab9dfd974da0c4dddf1024fec6217276 Mon Sep 17 00:00:00 2001 From: Khaled Bin Amir Date: Sun, 3 Aug 2025 23:48:24 +0600 Subject: [PATCH 6/6] Update salary_slip.py --- hrms/payroll/doctype/salary_slip/salary_slip.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hrms/payroll/doctype/salary_slip/salary_slip.py b/hrms/payroll/doctype/salary_slip/salary_slip.py index b2e507c5b9..42bb3013d0 100644 --- a/hrms/payroll/doctype/salary_slip/salary_slip.py +++ b/hrms/payroll/doctype/salary_slip/salary_slip.py @@ -715,7 +715,7 @@ def calculate_lwp_ppl_and_absent_days_based_on_attendance( for d in attendance_details: if d.leave_type and d.leave_type not in leave_type_map.keys(): continue - + # Check if attendance date is a holiday if getdate(d.attendance_date) in holidays: if credit_present_on_holidays: @@ -724,7 +724,7 @@ def calculate_lwp_ppl_and_absent_days_based_on_attendance( elif d.status == "Half Day": absent -= (1 - daily_wages_fraction_for_half_day) continue - + elif not consider_absent_on_holidays: if d.status in ["Absent", "Half Day"] or ( d.leave_type and not leave_type_map[d.leave_type]["include_holiday"]