From febd6aaefb4d3b0f48ca23552f933b5444ba04f1 Mon Sep 17 00:00:00 2001 From: Anjali Patel Date: Thu, 28 May 2026 15:31:37 +0530 Subject: [PATCH 1/3] fix: prevent unauthorized status change on Shift Request - Add permlevel 1 to status field so only HR Manager/HR User can edit it - Add level 1 permissions for HR Manager, HR User, and read-only for All - Add server-side validate_status_change to block API-level bypass Fixes #4502 --- .../doctype/shift_request/shift_request.json | 18 ++++++++++++++++++ hrms/hr/doctype/shift_request/shift_request.py | 11 +++++++++++ 2 files changed, 29 insertions(+) diff --git a/hrms/hr/doctype/shift_request/shift_request.json b/hrms/hr/doctype/shift_request/shift_request.json index 8e2d152254..998909bf8a 100644 --- a/hrms/hr/doctype/shift_request/shift_request.json +++ b/hrms/hr/doctype/shift_request/shift_request.json @@ -89,6 +89,7 @@ "fieldtype": "Select", "label": "Status", "options": "Draft\nApproved\nRejected", + "permlevel": 1, "reqd": 1 }, { @@ -146,6 +147,23 @@ "share": 1, "submit": 1, "write": 1 + }, + { + "permlevel": 1, + "read": 1, + "role": "All" + }, + { + "permlevel": 1, + "read": 1, + "write": 1, + "role": "HR Manager" + }, + { + "permlevel": 1, + "read": 1, + "write": 1, + "role": "HR User" } ], "sort_field": "creation", diff --git a/hrms/hr/doctype/shift_request/shift_request.py b/hrms/hr/doctype/shift_request/shift_request.py index 2ae9a82f59..a7f7b6217f 100644 --- a/hrms/hr/doctype/shift_request/shift_request.py +++ b/hrms/hr/doctype/shift_request/shift_request.py @@ -44,6 +44,7 @@ def validate(self): self.validate_overlapping_shift_requests() self.validate_approver() self.validate_default_shift() + self.validate_status_change() def on_update(self): share_doc_with_approver(self, self.approver) @@ -154,3 +155,13 @@ def throw_overlap_error(self, shift_details): ) frappe.throw(msg, title=_("Overlapping Shift Requests"), exc=OverlappingShiftRequestError) + + def validate_status_change(self): + if frappe.has_permission("Shift Request", "submit", self): + return + + if self.status != "Draft": + frappe.throw( + _("You do not have permission to change the Status of a Shift Request."), + frappe.PermissionError, + ) From 522756998499a0156feec9c36dbc6918fae5b46b Mon Sep 17 00:00:00 2001 From: Anjali Patel Date: Thu, 4 Jun 2026 21:17:58 +0530 Subject: [PATCH 2/3] fix: remove permlevel restriction from status field in shift_request --- .../doctype/shift_request/shift_request.json | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/hrms/hr/doctype/shift_request/shift_request.json b/hrms/hr/doctype/shift_request/shift_request.json index 998909bf8a..8e2d152254 100644 --- a/hrms/hr/doctype/shift_request/shift_request.json +++ b/hrms/hr/doctype/shift_request/shift_request.json @@ -89,7 +89,6 @@ "fieldtype": "Select", "label": "Status", "options": "Draft\nApproved\nRejected", - "permlevel": 1, "reqd": 1 }, { @@ -147,23 +146,6 @@ "share": 1, "submit": 1, "write": 1 - }, - { - "permlevel": 1, - "read": 1, - "role": "All" - }, - { - "permlevel": 1, - "read": 1, - "write": 1, - "role": "HR Manager" - }, - { - "permlevel": 1, - "read": 1, - "write": 1, - "role": "HR User" } ], "sort_field": "creation", From 01dec19e67c3fbecb4845cedd9402f4f57985794 Mon Sep 17 00:00:00 2001 From: Hemil Sangani Date: Sat, 6 Jun 2026 13:17:49 +0530 Subject: [PATCH 3/3] fix: invalidate salary structure cache on document update --- hrms/payroll/doctype/salary_component/salary_component.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/hrms/payroll/doctype/salary_component/salary_component.py b/hrms/payroll/doctype/salary_component/salary_component.py index bce6314d01..860d74f063 100644 --- a/hrms/payroll/doctype/salary_component/salary_component.py +++ b/hrms/payroll/doctype/salary_component/salary_component.py @@ -187,3 +187,7 @@ def update_salary_structures( "label": _("via Salary Component sync"), } salary_structure.save_version() + # db_update_all() does not invalidate cached Salary Structure documents. + # Clear the cache so salary slip generation picks up updated formulas + # and conditions immediately. + salary_structure.clear_cache()