fix(setup): let HR re-enable a user that an employee status change disabled

The Version log shows who last changed the user's enabled flag. If that
user cannot write Users, the disable came from the Employee status sync,
so re-enabling only undoes it.

(cherry picked from commit b1d23522b2)
This commit is contained in:
Mihir Kandoi
2026-10-28 07:53:21 +00:00
committed by Mergify
parent 8e949368d4
commit 121ab0fec0
+22 -4
View File
@@ -201,8 +201,7 @@ class Employee(NestedSet):
if user.enabled == enable:
return
# Re-enabling restores access, so it needs write access on the User; disabling does not.
if enable and not user.has_permission("write"):
if enable and not self.can_reenable_user(user):
frappe.msgprint(
_("User {0} is disabled. Only a user who can edit Users can enable it.").format(
frappe.bold(self.user_id)
@@ -211,8 +210,27 @@ class Employee(NestedSet):
return
user.enabled = enable
# Keep linked User status in sync from the Employee lifecycle and record the audit log.
user.save(ignore_permissions=True)
# Keep linked User status in sync from the Employee lifecycle and record the audit log,
# which can_reenable_user reads.
user.save(ignore_permissions=True, ignore_version=False)
def can_reenable_user(self, user):
"""Allow if the session user can edit the User, or if an Employee status change disabled it last."""
if user.has_permission("write"):
return True
last_change = frappe.get_all(
"Version",
filters={"ref_doctype": "User", "docname": user.name, "data": ("like", '%"enabled"%')},
pluck="owner",
order_by="creation desc",
limit=1,
)
# Without User write access, the only way to disable a User is an Employee status change.
# Every user has their own User shared with them, so check role permissions only.
return bool(last_change) and not frappe.has_permission(
"User", "write", user=last_change[0], ignore_share_permissions=True
)
def validate_duplicate_user_id(self):
Employee = frappe.qb.DocType("Employee")