Urgent -Employee Permission Issue


Root Cause from Migration Guide

In Frappe v16, has_permission hooks now need to explicitly return True. Previously returning None or any non-False value was enough to allow the user — this no longer works.

Looking at the core permissions.py you shared earlier, this is the critical function:

def has_controller_permissions(doc, ptype, user=None, debug=False) -> bool:
    hooks = frappe.get_hooks("has_permission")
    methods = hooks.get(doc.doctype, []) + hooks.get("*", [])

    for method in reversed(methods):
        controller_permission = frappe.call(method, doc=doc, ptype=ptype, user=user)
        if not controller_permission:
            return bool(controller_permission)  # None = False = DENIED ❌

    return True

Any hook returning None = access denied in v16.


Your hooks.py has this — "*" wildcard hook

Check if HRMS app (not your custom app) has a has_permission hook registered for "*" (all doctypes). Run this:

bench --site yoursite.com console

import frappe
print(frappe.get_hooks("has_permission"))


Also — Add has_permission to your custom_app hooks.py

Open your hooks file:

/home/frappe/frappe-bench/apps/custom_app/custom_app/hooks.py

Add this block:

has_permission = {
    "Employee": "custom_app.custom_app.employee.has_permission"
}

Then create the function in your employee.py:

def has_permission(doc, ptype, user):
    """
    Explicitly return True for v16 compatibility.
    In v16, returning None is treated as False (denied).
    """
    # Allow employee to access their own record
    employee_user = frappe.db.get_value("Employee", doc.name, "user_id")
    if employee_user == user:
        return True

    # Allow HR roles full access
    user_roles = frappe.get_roles(user)
    if any(role in user_roles for role in ["HR Manager", "HR User", "System Manager"]):
        return True

    # Must explicitly return True (not None) for v16
    return True


Apply the fix

bench --site yoursite.com clear-cache
bench restart


Most importantly — paste the output of:

print(frappe.get_hooks("has_permission"))

This will show exactly which app is registering a has_permission hook and causing the denial.

@Hemil_Sangani Can yiu check It is ok or not . Can i Proceed with same
please check sir.