HR Leave Management
Why this is a workflow problem, not a form problem
Tracking employee leave with spreadsheets creates a cascade of failures: managers lose requests in email, HR has no audit trail, employees wait days for a simple approval, and nobody can see real-time team availability. The fix is not a better form — it is a state machine that enforces transitions, a multi-level approval chain that routes by org position, and a permission model that shows each person exactly and only their slice of the data.
AuraBoot expresses all of that as configuration: two models, a state graph, a set of commands, and role scopes — no custom backend code required.
Data model summary
The HR Essentials solution ships two cooperating models inside a single plugin:
hr_employee— Master record with department, position, hire date, and status (active/inactive). Auto-generated code pattern:EMP-{seq}.hr_leave_request— Leave request anchoring the approval workflow. Auto-generated code pattern:LV-{yyyyMMdd}-{seq}. Links back tohr_employeevia a reference field.hr_leave_balance— Per-employee, per-leave-type quota tracking (annual days granted vs. days consumed). Updated automatically when a request transitions toapprovedorcancelled.
Key fields on hr_leave_request:
| Field | Type | Notes |
|---|---|---|
hr_lv_employee_id | REFERENCE | Picker linking to hr_employee |
hr_lv_leave_type | ENUM | annual / sick / personal / maternity / bereavement |
hr_lv_start_date | DATE | Must precede hr_lv_end_date |
hr_lv_end_date | DATE | Validated on submit |
hr_lv_days | DECIMAL | Positive value required |
hr_lv_reason | TEXT | Required on rejection; optional on submission |
hr_lv_status | ENUM | draft / pending / approved / rejected / cancelled |
Key commands
Five commands cover the full lifecycle:
| Command | Shape | Who triggers it |
|---|---|---|
hr.leave.request.submit | StateTransition draft → pending | Employee |
hr.leave.request.approve | StateTransition pending → approved | Direct manager or dept head |
hr.leave.request.reject | StateTransition pending → rejected | Approver (reason required) |
hr.leave.request.resubmit | StateTransition rejected → pending | Employee after editing |
hr.leave.request.cancel | StateTransition approved → cancelled | Employee (before leave date) |
The reject command carries a guard: #payload['reason'] != null. Attempting to reject without a reason fails validation before the state transition fires — no custom controller code needed.
Approval process
Multi-level approvals run through a BPM process bound to hr_leave_request. Each stage maps to a command:
Employee submits
|
v
+-------------------+
| Direct Manager | <- hr.leave.request.approve / reject
+-------------------+
| approved
v
+-------------------+
| Dept Head | <- hr.leave.request.approve / reject
+-------------------+
| approved (escalated or long leave)
v
+-------------------+
| HR Administrator | <- hr.leave.request.approve / reject
+-------------------+
|
v
Approved / Rejected
(audit trail on every transition)
Short leave requests (under 3 days, not maternity) route through direct manager only. Requests over 5 days or of type maternity escalate to dept head and then HR. BPM gateway conditions are declarative; the state machine only cares that the final command fires with the right from-state.
Permission example
A realistic HR deployment uses four role layers simultaneously:
- Employee — Layer 3 self-scope:
hr.leave.request.viewrestricted tocreated_by = current_user. Sees own leave history and balance; cannot see colleagues' records. Salary fields on the employee detail are masked. - Direct manager — Layer 2 ReBAC org-reports relation:
hr.leave.request.viewandhr.leave.request.approvescoped toemployee.manager_id = current_user. Sees only direct reports' requests; salary fields still masked. - HR Administrator — Layer 1 RBAC:
hr.leave.request.*with no data-scope restriction. Sees all employees across all departments. Salary and compensation fields visible. - Field-level mask —
hr_em_salaryandhr_em_compensation_gradeare field-level-permission-gated. Non-HR roles receive"***"on read; the field is hidden on create/edit forms entirely.
All four layers evaluate in order on every request. No branching logic lives in application code.
Agent integration
Two command classes are intentionally agent-accessible:
- Read commands (
hr.leave.balance.summary,hr.leave.request.list_pending) — read-only, idempotent. An AI assistant can answer "how many annual leave days do I have left?" or surface overdue approval tasks in a daily digest. - Draft command (
hr.leave.request.submit) — write, idempotent. An agent can pre-fill a leave request from a natural-language instruction ("book three days off next week for personal reasons"); the employee reviews and confirms via the existing state-transition form.
Commands marked riskLevel: write, irreversible: false are exposed. The cancel command on an already-approved future leave is marked agentHint: "Confirm with user before executing" — the agent must show a confirmation step.
How to get it
- Community: build it yourself. The models, state graph, and command pipeline are open-source; the HR Essentials plugin bundle is not included.
- Standard: use the base platform; build your own HR-shaped plugin on top.
- Professional: get the HR Essentials plugin — pre-wired models, menus, roles, balance tracking, and BPM approval chain.
- Enterprise: same package plus org-hierarchy-aware role seeding, payroll system integration connectors, and SLA-backed support.
See Pricing for the full edition comparison.
Enterprise note — Multi-level BPM approval chains with org-hierarchy-aware routing, ReBAC org-reports scoping at runtime, field-level salary masking, and payroll connector integration are available in Professional and Enterprise editions. The open-core state machine, commands, and basic RBAC are the same in every edition.
Next steps
- System overview — how plugins, commands, and the runtime fit together
- Command pipeline — the execution contract behind every state transition
- Permissions — the five-layer model covering RBAC, ReBAC, and field-level masking
- Plugin manifest — how a solution package declares its plugin dependencies
- Agent readiness — designing
agentHintand risk fields for safe execution