Skip to main content

Leave Approval

stateDiagram-v2
[*] --> Pending: Employee submits
Pending --> ShiftManagerApproved: ShiftManager approves
Pending --> Rejected: ShiftManager rejects
ShiftManagerApproved --> HRApproved: HR approves
ShiftManagerApproved --> Rejected: HR rejects
HRApproved --> [*]
Rejected --> Overridden: SuperAdmin overrides
Overridden --> [*]

Submission

POST /api/v1/leaves
{
"starts_on": "2026-05-03",
"ends_on": "2026-05-04",
"type": "casual",
"reason": "Family function"
}

Decision

POST /api/v1/leaves/{id}/decide
{
"action": "approve", // approve | reject | override
"comment": "Covered by locum"
}

Server validates the caller's role against the current status:

StatusAllowed actorsAllowed actions
pendingShiftManager, HR (skip), SuperAdminapprove, reject
shift_manager_approvedHR, SuperAdminapprove, reject
hr_approved, overriddenfinal
rejectedSuperAdminoverride

Side Effects

  • On hr_approved (or overridden), the leave dates block the attendance engine — each covered day gets an attendances row with status = leave (no punches needed).
  • If punches already exist for a covered day, AttendanceRecalculator is invoked — the leave status wins over the punch-derived status but the punches remain for audit.
  • Notifications go to the employee on every status change.