diff --git a/jey_theme/hooks.py b/jey_theme/hooks.py index cca47ec..bea3f9d 100644 --- a/jey_theme/hooks.py +++ b/jey_theme/hooks.py @@ -28,8 +28,12 @@ has_permission = { "*": "jey_theme.access_control.has_permission", } -# Idempotent setup of the custom Taxes workspace (see setup/taxes_workspace.py). -after_migrate = ["jey_theme.setup.taxes_workspace.setup"] +# Idempotent setup of the custom Taxes workspace (see setup/taxes_workspace.py) +# and the Employees /desk icon under Frappe HR (see setup/employees_icon.py). +after_migrate = [ + "jey_theme.setup.taxes_workspace.setup", + "jey_theme.setup.employees_icon.setup", +] # override_doctype_class = { # "Report": "jey_theme.custom_report.CustomReport" diff --git a/jey_theme/setup/employees_icon.py b/jey_theme/setup/employees_icon.py new file mode 100644 index 0000000..5e72390 --- /dev/null +++ b/jey_theme/setup/employees_icon.py @@ -0,0 +1,101 @@ +"""Idempotent setup of an 'Employees' /desk icon under the Frappe HR folder. + +HRMS v16 dropped the old 'Employee Lifecycle' workspace (see +hrms/patches/v16_0/delete_old_workspaces.py), which removed its desktop +icon from the Frappe HR folder on /desk. This re-adds an icon that goes +straight to the Employee DocType list, owned by jey_theme so HRMS stays +untouched. + +Frappe's DesktopIcon.is_permitted (frappe/desk/doctype/desktop_icon/ +desktop_icon.py) requires a Workspace Sidebar named after the icon's +label to exist, otherwise the icon is filtered out of bootinfo even when +link_type='External'. So we also create a minimal Workspace Sidebar with +one item — a DocType Link to Employee — that get_route_for_icon picks up +and routes to /app/employee. No Workspace page is created. +""" + +import frappe + +DESKTOP_ICON_LABEL = "Employees" +DESKTOP_ICON_PARENT = "Frappe HR" +DESKTOP_ICON_ICON = "users" +DESKTOP_ICON_IDX = 0 + +SIDEBAR_NAME = "Employees" +TARGET_DOCTYPE = "Employee" + + +def ensure_workspace_sidebar() -> str: + item = { + "type": "Link", + "label": TARGET_DOCTYPE, + "link_type": "DocType", + "link_to": TARGET_DOCTYPE, + "icon": DESKTOP_ICON_ICON, + } + + if frappe.db.exists("Workspace Sidebar", SIDEBAR_NAME): + sb = frappe.get_doc("Workspace Sidebar", SIDEBAR_NAME) + sb.title = SIDEBAR_NAME + sb.header_icon = DESKTOP_ICON_ICON + sb.app = "jey_theme" + sb.standard = 1 + sb.items = [] + sb.append("items", item) + sb.save(ignore_permissions=True) + return f"updated Workspace Sidebar {SIDEBAR_NAME!r}" + + sb = frappe.get_doc({ + "doctype": "Workspace Sidebar", + "name": SIDEBAR_NAME, + "title": SIDEBAR_NAME, + "header_icon": DESKTOP_ICON_ICON, + "app": "jey_theme", + "standard": 1, + "items": [item], + }) + sb.insert(ignore_permissions=True) + return f"created Workspace Sidebar {SIDEBAR_NAME!r}" + + +def ensure_desktop_icon() -> str: + existing = frappe.db.exists("Desktop Icon", {"label": DESKTOP_ICON_LABEL}) + if existing: + icon = frappe.get_doc("Desktop Icon", existing) + icon.icon = DESKTOP_ICON_ICON + icon.icon_type = "Link" + icon.link_type = "Workspace Sidebar" + icon.link_to = SIDEBAR_NAME + icon.link = None + icon.parent_icon = DESKTOP_ICON_PARENT + icon.app = "jey_theme" + icon.standard = 1 + icon.hidden = 0 + icon.idx = DESKTOP_ICON_IDX + icon.save(ignore_permissions=True) + return f"updated Desktop Icon {DESKTOP_ICON_LABEL!r}" + + icon = frappe.get_doc({ + "doctype": "Desktop Icon", + "label": DESKTOP_ICON_LABEL, + "icon": DESKTOP_ICON_ICON, + "icon_type": "Link", + "link_type": "Workspace Sidebar", + "link_to": SIDEBAR_NAME, + "parent_icon": DESKTOP_ICON_PARENT, + "app": "jey_theme", + "standard": 1, + "hidden": 0, + "idx": DESKTOP_ICON_IDX, + }) + icon.insert(ignore_permissions=True) + return f"created Desktop Icon {DESKTOP_ICON_LABEL!r}" + + +def setup(): + """Entry point — safe to call repeatedly (e.g. from after_migrate).""" + results = [ensure_workspace_sidebar(), ensure_desktop_icon()] + frappe.db.commit() + for r in results: + if r: + print(r)