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 (Teachers Module)

Exact wire contract per 00-shared/07. Base /api/v1; envelope {success,message,data,meta?,timestamp,requestId}. Global guards: RateLimitGuard → JwtAuthGuard → RbacGuard (app.module.ts:129-131); no teachers endpoint carries RBAC metadata (rbac.guard.ts:29 → JWT-only). Bearer JWT; tenantId from token only (base.repository.ts:33-35).


0. Module-wide request envelope & client policy

AspectContract
HeadersAuthorization: Bearer; x-request-id client UUID; Content-Type: application/json
Tenancynever in body; server injects tenantId + isDeleted:false scope (base.repository.ts:20-30)
Cachingreference catalogs (departments, designations, subjects, classes, years) 24 h TTL; teacher lists 5 min TTL (00-shared/06 §3.3)
Offlinereads last-good cache + banner; writes blocked (no offline queue for this module)
Retrybackoff on 5xx/network; no auto-retry on 429
Idempotencycreate is retry-safe via 409 duplicate guards (teacher.service.ts:27-38); Idempotency-Key optional (B6 shared ledger)

1. Teachers CRUD — module core

GET /teachers — list (S1)

  • Query: page (1-based, default 1), limit (1–100, default 20), sort (-field), q (pagination-query.dto.ts:5-30).
  • Derived caveat: TeacherService.find ignores sort and q (teacher.service.ts:66-78); no status/department filters exist.
  • Success: data: Teacher[], meta: {page,limit,totalItems,totalPages,hasNext,hasPrevious} (buildPaginationMeta, pagination-query.dto.ts:41-55).
  • Errors: 400 (bad page/limit), 401, 429, 5xx.

GET /teachers/:id — detail (S2)

  • Success: data: Teacher (raw schema doc, refs as ObjectIds).
  • 404 RESOURCE_NOT_FOUND "Teacher not found." (teacher.service.ts:54-58).

POST /teachers — create (S5)

  • Body: CreateTeacherDto (create-teacher.dto.ts:4-52, F1).
  • 201→200 data: Teacher. 409 DUPLICATE_RESOURCE (user profile exists, teacher.service.ts:27-31; employeeNumber exists, :32-38). 400 validation.
  • Side-effects: TeacherCreatedin-app job teacher-created (event-queue-map.ts:31) → notification (inapp.worker.ts:46-53); search index (search-indexer.service.ts:10).

PATCH /teachers/:id — update (S6)

  • Body: UpdateTeacherDto (update-teacher.dto.ts:4-53, F2); $set merge (teacher.service.ts:80-93); userId immutable.
  • 200 data: Teacher; 404 (missing or soft-deleted); 400.
  • Side-effects: TeacherUpdatedaudit-write log-teacher-updated (event-queue-map.ts:32); search re-index (search-indexer.service.ts:17).

DELETE /teachers/:id — deactivate (S8)

  • 200 data absent (void); soft-delete isDeleted/deletedAt/deletedBy + version+1 (base.repository.ts:68-74).
  • 404 "Teacher not found." (teacher.service.ts:95-97).
  • Side-effects: TeacherDeletedaudit-write log-teacher-deleted (event-queue-map.ts:33); search index removal (search-indexer.service.ts:24,52-59).

2. Subject assignments — teaching matrix (S3/S7)

POST /subject-assignments — create (S7)

  • Body: CreateSubjectAssignmentDto (create-subject-assignment.dto.ts:4-19, F3).
  • 200 data: SubjectAssignment. 400 validation. No 404/409 paths — no existence or duplicate checks (subject-assignment.service.ts:13-17) (OQ-2).

GET /subject-assignments/by-teacher/:teacherId?academicYearId= (S3)

  • academicYearId required in practice (missing → [] since filter includes it, subject-assignment.service.ts:26-31).
  • Success: data: SubjectAssignment[]non-paginated array, no meta.
  • Sort: insertion order (no index sort).

GET /subject-assignments/by-class/:classId?academicYearId= (coordinator view)

  • Same shape; filter {classId, academicYearId} (subject-assignment.service.ts:19-24).

DELETE /subject-assignments/:id — remove

  • Soft-delete (subject-assignment.service.ts:33-36); 404 "Assignment not found.".
  • Caveat: subject_assignments has no timestamps: true (subject-assignment.schema.ts:7) and isDeleted scoping comes from BaseSchema.

3. Supporting catalogs (read-only for this module)

EndpointUsed bySource
GET /departments (paginated)F1/F2 department picker, S1 filterdepartment.controller.ts:29-31
GET /designations (paginated)F1/F2 designation pickerdesignation.controller.ts
GET /subjects (paginated)F1 subjects multi, S7 subject pickersubject.controller.ts:27-29
GET /classes (+ by-year/:academicYearId)F1 classTeacherFor multi, S7 class pickerclass.controller.ts:27-33
GET /academic-yearsS3/S7 year picker (isCurrent flag)academic-year.controller.ts:27-30
GET /timetable?teacherId=S4 scheduletimetable.controller.ts:21-27
GET /dashboard/overviewteachers.total KPIdashboard.service.ts:32,52
GET /usersF5 user pickerUsers module

4. Loading / streaming / realtime

ScreenLoadingRealtime
S1 listskeleton rows— (teacher.created WS event (planned))
S2/S3/S4 detailskeleton card / rowsrefresh on notification.new for own tenant (planned)
S5/S6/S7 formssubmit spinner only
S8 dialogbutton spinner

5. Client error mapping table (module)

ScreenCodeUI
S1/S2/S3401silent refresh; fail → sessionExpired
S1/S2/S3403403 screen (future server enforcement)
S2/S3/S8404"Teacher not found or removed" → back
S3 remove404treat as removed locally
S5409inline conflict banner, keep form
S5/S6/S7400per-field errors
all429"Try again in a moment", no auto-retry
all5xxgeneric + requestId + retry

6. Pagination summary

  • GET /teachers: paginated (page/limit/meta) — infinite scroll.
  • GET /subject-assignments/by-*, GET /timetable, catalogs: non-paginated arrays except catalogs which paginate via PaginationQueryDto — client treats catalogs as page-through (limit 100) or caches 24 h.
  • GET /departments//designations paginate — client loads with limit=100 and caches.

7. Optimistic / undo

  • List refresh + detail refresh: server-first (read-after-write on navigation back).
  • Status change (F2) is a $set — safe; client applies after 200 only (no rollback complexity).
  • No destructive op is optimistic (00-shared/06 §3.5); UNDO snackbar not offered for deactivate (irreversible by design) — offering undo would be inventing an API surface (no reactivation endpoint).