Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

02 — User Personas (Leave Module)

Derived from role.schema.ts:8-65 (system roles), users/schemas/user.schema.ts:14-79, and the leave service semantics (leave.service.ts). Behaviors that the API enforces are cited; anything else is product expectation (proposed).


Legend

P = permission/authority from source · F = friction/behavior note.


1. The Teacher — "Sneha, Grade 8 Science"

FieldDetail
Roleteacher (role.schema.ts:26-32) — permissions student.read, attendance.mark, attendance.edit
ContextFull-time faculty; 30+ contact hours/week; mobile-first; marks attendance in app daily
Leave needsSick days, casual time off, planned earned leave; must find a substitute before admin approves
Key actionsRequest leave (type, dates, reason); check balance before asking; watch request status; see substitutions assigned for their own classes
API pathPOST /leave/requests (leave.controller.ts:32-36); GET /leave/requests (own only, leave.service.ts:166-167); GET /leave/balance/:userId (:55-59)
FrustrationsApprovals that stall; balance surprises (weekend days count, leave.service.ts:310-312); no edit/withdraw path (gap)
Success metric (proposed)Request-to-decision median < 24 h; zero requests rejected for "insufficient balance" after the user checked balance

2. The Org Admin / HR — "Ramesh, Administrator"

FieldDetail
Roleorg_adminALL_PERMISSIONS (role.schema.ts:18-24); detected inline in service via ctx.roles.includes('org_admin') (leave.service.ts:163)
ContextRuns the institution's staffing; approves or rejects leave; configures leave types; assigns substitutes
Key actionsApprovals queue (all requests, filter by status/userId, leave.controller.ts:38-47); decide with optional note (PATCH /leave/requests/:id/approve, :49-53); create leave types (POST /leave/types, :61-65); assign substitutes (POST /leave/substitutions, :73-77); view calendar of approved leave (GET /leave/calendar, :85-91)
Decision rules enforced by APIOnly pending can be decided (leave.service.ts:175-178); cannot approve own request (:179-180); approval blocked at 409 if balance insufficient (:188-189)
FrustrationsSelf-approval impossible by design (must delegate); no batch decisions; no leave-type edit/delete
Success metric (proposed)Approvals resolved same-day; substitution assigned within 24 h of approval for multi-day leave

3. The Substitute Teacher — "Imran, Part-time Relief"

FieldDetail
Roleteacher with a Teacher record (teacherRepo.findOne, leave.service.ts:232-238)
ContextCovers classes for absent teachers; paid per covered slot
Key actionsView assigned substitutions: GET /leave/substitutions/teacher/:id (leave.controller.ts:79-83) — list sorted by date ascending (leave.service.ts:275-280)
API constraintsAdmin assigns; substitute does not accept/decline (no endpoint); slot clash is rejected at assignment time (leave.service.ts:241-250)
FrustrationsNo accept/decline flow; no conflict visibility beyond admin checks; substitution status is stuck at assigned (no completed/cancelled transition in service)
Success metric (proposed)Substitution discovery < 30 s after open; no-show rate tracked via Timetable (planned, IMPLEMENTATION_PLAN.md:163)

4. Staff (non-teaching) — "Priya, Office Coordinator"

FieldDetail
Rolestaff (role.schema.ts:33-40, permission student.read)
ContextOffice staff; needs casual/sick leave like teachers; no substitution mechanics apply (no Teacher record → 404 on substitution, leave.service.ts:232-238)
Key actionsRequest leave; check balance; track status — same endpoints as Teacher
NoteAny authenticated user can create a request (userId from tenant context, leave.service.ts:138); nothing in code restricts leave to staff/teachers (gap: student/parent roles are not excluded)

5. System actors (non-human)

ActorBehavior
Event busLeaveRequested, LeaveApproved/LeaveRejected, SubstitutionAssigned payloads (events/leave-events.ts:1-26) → notification workers (planned)
Audit logAll writes carry createdBy/updatedBy via BaseSchema; decision writes decidedBy, decidedAt, decisionNote (leave-request.schema.ts:41-48)
Timetable (planned)Substitution creates a Timetable entry + notifies substitute and students (IMPLEMENTATION_PLAN.md:163)

6. Persona priority

  1. Teacher (highest volume — requests + balance)
  2. Org Admin (decisions + substitutions)
  3. Substitute teacher
  4. Staff