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

12 — API Mapping (Leave Module)

Exact endpoint contract for the Leave module. Source: leave.controller.ts (routes), leave.service.ts (semantics), DTOs (bodies), schemas (fields), docs/IMPLEMENTATION_PLAN.md ((planned)). Envelope and error conventions: 00-shared/07. All endpoints are under @Controller('leave') with JwtAuthGuard + ApiBearerAuth (leave.controller.ts:25-28); URI prefix /api/v1 per main.ts versioning.


1. Endpoint table

#MethodPathSummarySourceAccess
1POST/api/v1/leave/requestsCreate leave requestleave.controller.ts:32-36any authenticated user
2GET/api/v1/leave/requestsList requests (status, userId filters)leave.controller.ts:38-47own only; all for org_admin (leave.service.ts:163-167)
3PATCH/api/v1/leave/requests/:id/approveApprove / rejectleave.controller.ts:49-53any (server blocks self-decision :179-180); client: admin
4GET/api/v1/leave/balance/:userIdLive balance for userleave.controller.ts:55-59any (no server restriction — gap)
5POST/api/v1/leave/typesCreate leave typeleave.controller.ts:61-65org admin (client)
6GET/api/v1/leave/typesList leave typesleave.controller.ts:67-71any
7POST/api/v1/leave/substitutionsAssign substituteleave.controller.ts:73-77org admin (client)
8GET/api/v1/leave/substitutions/teacher/:idSubstitutions for teacherleave.controller.ts:79-83substitute teacher
9GET/api/v1/leave/calendarApproved leave in rangeleave.controller.ts:85-91any

(planned)IMPLEMENTATION_PLAN.md:153-161 lists the same nine endpoints; no additional leave endpoints are planned in that doc.

2. Request bodies

EndpointDTOFields
1CreateLeaveRequestDto (create-leave-request.dto.ts:4-21)leaveTypeId (mongoId, req), startDate (ISO date, req), endDate (ISO date, req), reason?
3LeaveDecisionDto (leave-decision.dto.ts:9-17)action (approve|reject, enum :4-7, req), note?
5CreateLeaveTypeDto (create-leave-type.dto.ts:4-28)code (str, req), name (str, req), daysPerYear (int ≥ 1, req), carryForward? (bool, default false), maxCarryForward? (int ≥ 0)
7AssignSubstitutionDto (assign-substitution.dto.ts:4-37)leaveRequestId, substituteTeacherId, classId, subjectId (mongoIds, req), date (ISO, req), startTime, endTime (str HH:mm, req), notes?

3. Response shapes

  • 2/3 → created/updated LeaveRequest document: _id, tenantId, userId, leaveTypeId, startDate, endDate, daysRequested, reason?, status, decidedBy?, decidedAt?, decisionNote?, createdAt, updatedAt, version (schema leave-request.schema.ts:16-48 + BaseSchema audit fields).
  • 2 (list)LeaveRequest[] sorted createdAt desc (leave.service.ts:168).
  • 4LeaveBalanceEntry[]: {leaveTypeId, code, name, daysPerYear, carriedForward, daysUsed, daysRemaining} (leave.service.ts:66-74).
  • 6LeaveType[] sorted code asc (leave.service.ts:216).
  • 8Substitution[] sorted date asc (leave.service.ts:275-280).
  • 9LeaveRequest[] (approved only) sorted startDate asc (leave.service.ts:288-295); default range = current month (:283-287).

4. Error contract (all 4xx/5xx in standard envelope, 00-shared/07)

HTTPTriggerMessageSource
400endDate < startDateendDate must be on or after startDate.leave.service.ts:133-134
401missing/invalid JWTleave.controller.ts:27
404unknown leave typeLeave type not found.leave.service.ts:129
404unknown requestLeave request not found.:174
404requester has no teacher recordNo teacher record found for the leave requester.:236-237
409request not pendingLeave request is already <status>.:175-178
409self-decisionYou cannot decide your own leave request.:179-180
409approve when balance insufficientInsufficient leave balance.:188-189
409substitution on non-approved requestLeave request must be approved before assigning a substitution.:227-230
409substitute slot clashSubstitute teacher already assigned in this time slot.:247-248
11000*duplicate leave-type code (Mongo unique (tenantId, code))not mapped server-side — gapleave-type.schema.ts:29

*Surfaces as a generic 500-class error today; client maps duplicate code from the raw key error until server adds a mapper.

5. Events emitted (side effects)

EventPayload (events/leave-events.ts)Emitted at
LeaveRequestedleaveRequestId, userId, leaveTypeCode, startDate, endDate, daysRequested (:1-8)leave.service.ts:154
LeaveApproved / LeaveRejectedleaveRequestId, userId, leaveTypeCode, startDate, endDate, action, note? (:10-18):210
SubstitutionAssignedsubstitutionId, absentTeacherId, substituteTeacherId, classId, date (:20-26):271

Consumers: Notifications (planned, IMPLEMENTATION_PLAN.md:163); audit.

6. Query semantics

  • List (2): status ∈ enum (pending\|approved\|rejected\|cancelled, leave-request.schema.ts:7-12); userId only effective for admins (leave.service.ts:167). Non-admin always receives own rows only.
  • Calendar (9): from/to ISO dates; overlap query startDate ≤ to AND endDate ≥ from (:291-292).

7. Gaps (no endpoint today)

Cancel request (cancelled status unreachable) · edit/withdraw pending request · request detail GET /:id · leave-type update/delete · substitution status transitions (completed/cancelled) · balance for "self" convenience (requires own userId) · leave.* RBAC permissions (permissions.constants.ts:1-97 has none).