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

Exact wire contract for every screen → endpoint. Base /api/v1; envelope per 00-shared/07. All endpoints from attendance.controller.ts, biometric.controller.ts, reports.controller.ts, dashboard.controller.ts; business rules from the services. Global guard chain: RateLimitGuard → JwtAuthGuard → RbacGuard (app.module.ts:129-131); attendance controller adds no per-endpoint @Permissions (OQ-5).


0. Module-wide request envelope & client policy

AspectContract
Basehttps://api.<domain>/api/v1
HeadersAuthorization: Bearer <accessToken>; x-request-id; Content-Type: application/json; Idempotency-Key (UUID) on offline writes
Success{success,message,data,meta?,timestamp,requestId}
Error{success,message,error:{code,details?},timestamp,requestId}
TenancytenantId from JWT claim — never in body (00-shared/07 §6)
Cachingattendance lists: last-good cache, SWR, TTL 5 min (00-shared/06 §3.3)
Offlinereads cached; writes queued (this module defines an offline queue — 00-shared/06 §3.7)
Retrybackoff on 5xx/network; no auto-retry on 429

Pagination note (OQ-4): none of the attendance GETs paginate — data is a bare array, no meta. Client strategy: treat as full lists; history views page client-side.


1. Mark one student — S2 (single row)

EndpointPOST /attendance (attendance.controller.ts:25-27)
RequestMarkAttendanceDto: {studentId, classId, date('YYYY-MM-DD'), status, checkIn?, checkOut?, source?, remarks?} (mark-attendance.dto.ts:11-49)
Success201 → data = attendance doc (_id, studentId,classId,date,status,source,checkIn?,checkOut?,remarks?,markedBy?,version,createdAt,updatedAt)
Businessidempotent upsert by (tenantId, studentId, date) (attendance.repository.ts:17-37); emits AttendanceMarked {studentId,status,date} (attendance.service.ts:37-44); unique index attendance.schema.ts:59-62
Errors400 VALIDATION_ERROR (invalid status/date/ids — e2e p1-operations.e2e-spec.ts:222-228); 404 upstream refs; 409 race; 429; 5xx
Sourceattendance.service.ts:24-46
Offlinequeue locally; flush with Idempotency-Key

2. Batch mark — S2/S3

EndpointPOST /attendance/bulk (attendance.controller.ts:28-30)
RequestBulkMarkAttendanceDto {records: MarkAttendanceDto[]} (mark-attendance.dto.ts:51-54)
Successdata = array of docs, order preserved; one AttendanceMarked per record (attendance.service.ts:48-54)
Errors400 if any record invalid (sequential loop throws on first bad record — earlier records may already be saved, OQ-2); 409/429/5xx
Sourceattendance.service.ts:48-54; END_TO_END_USER_FLOWS.md:269-270,288
Offlineflush in chunks ≤ 100 records

3. Class-by-date roster — S2/S4

EndpointGET /attendance/class/:classId?date=YYYY-MM-DD (attendance.controller.ts:31-36)
Successdata = array of docs for that class+date (empty if none)
Errors400 missing date; 404 cross-tenant class; 429
Sourceattendance.service.ts:56-61; attendance.repository.ts:39-44; e2e p1-operations.e2e-spec.ts:211-220
Noteused per day; S4 month = 1 call/day (cache; OQ-4)

4. Student history — S7

EndpointGET /attendance/student/:studentId?startDate&endDate (both optional) (attendance.controller.ts:37-43)
Successdata = array of docs, date-range filtered (unfiltered = full history)
Errors404 cross-tenant; 429
Sourceattendance.service.ts:63-73; attendance.repository.ts:46-58; END_TO_END_USER_FLOWS.md:324-325,348,378-379,401
Noteparent/student gating open (OQ-7)

5. Class summary — S5 (live tile)

EndpointGET /attendance/summary?classId&startDate&endDate (all required) (attendance.controller.ts:44-50)
Successdata = {total, summary:{status:count}} (attendance.service.ts:103-113)
Errors400 missing params; 429
Sourceattendance.service.ts:103-113
Notein-memory aggregation (OQ-8)

6. Single record — S2 popover prefill / S7 edit

EndpointGET /attendance/:id (attendance.controller.ts:51-53)
Successdata = doc
Errors404 RESOURCE_NOT_FOUND "Attendance record not found." (attendance.service.ts:77)
Sourceattendance.service.ts:75-79

7. Update / correct — S4/S7

EndpointPATCH /attendance/:id (attendance.controller.ts:54-59)
RequestUpdateAttendanceDto {status?, checkIn?, checkOut?, remarks?} (update-attendance.dto.ts:4-22)
Successdata = updated doc (version +1, base.repository.ts:57-66); emits AttendanceUpdated {attendanceId, studentId, changes:[keys]} (attendance.service.ts:88-99)
Errors404 missing; 400; OQ-6 (no enum validation on status — client restricts); 429
Sourceattendance.service.ts:81-101
Notechanges keys → UI "what changed" toast; audit trail via event map (event-queue-map.ts:18-21)

8. Biometric ingest — S8 (machine→API)

EndpointPOST /biometric/ingest (biometric.controller.ts:14-18)
RequestCreateBiometricLogDto {studentId, deviceId, timestamp, mode?} (create-biometric-log.dto.ts:4-21)
Successdata = raw log doc (biometric-log.schema.ts:7-27) — stored only, not applied to attendance (OQ-3)
Sourcebiometric.service.ts:14-16
Notebiometric-sync cron */15 (scheduler.service.ts:71-76) has no worker today; deviceId unvalidated against biometric_devices (biometric-device.schema.ts:15-31)

9. Async attendance report — S5/S6

EndpointPOST /reports/generate (reports.controller.ts:14-18)
Request{type:'attendance_summary', classId?, startDate?, endDate?} (report-job.schema.ts:8-9)
Successdata = {jobId, status:'queued'} (reports.service.ts:28-44)
PollGET /reports/:jobId → `data = {type, status(queued
Errors404 unknown job; 400 bad type; 429
Sourcereports.service.ts:110-137; report.worker.ts:7
Noteteacher role lacks report.* (role.schema.ts:31) — admin-only today (OQ)

10. Dashboard attendance KPI — home

EndpointGET /dashboard/overview (dashboard.service.ts:18-71)
KPIattendance: {total, summary, rate} — rate = round(present/total × 100) (dashboard.service.ts:57-64)
Tapdeep link to S2 for today's class

11. Scheduler & events (context, not client endpoints)

ItemSource
AttendanceMarked / AttendanceUpdated → queue attendance-process, job process-attendanceevent-queue-map.ts:14-21
attendance-process worker: absence watch (all absent docs ≥ 3 → log), bulk-import branchattendance.worker.ts:16,45-54,57-102
Repeatable attendance-report-daily 07:00 UTC → report-generatescheduler.service.ts:99-104; attendance-report.job.ts:13-24
Repeatable biometric-sync */15 → biometric-sync queue (no worker)scheduler.service.ts:71-76; queue.constants.ts:7
Permissions availableattendance.mark, attendance.edit (permissions.constants.ts:29-30); report.generate, report.read (39-40); biometric.log.create/read, biometric.device.manage (41-43)

12. Client error mapping (module)

CodeAttendance-specific UX
400 VALIDATION_ERRORfield errors (§08_Form_Specifications.md §6); bulk → pre-validate client-side
401 UNAUTHENTICATEDrefresh once; else session expiry flow (00-shared/06 §5)
403 PERMISSION_DENIEDhide grid actions; batch bar disabled
404 RESOURCE_NOT_FOUNDrefresh roster; "record no longer exists" state
409 DUPLICATE_RESOURCEgrid refresh (upsert race); offline flush collision preview
422 BUSINESS_RULE_VIOLATIONcontext banner (not currently emitted by attendance service — future use)
429 RATE_LIMITEDbackoff, no auto-retry, countdown
5xxgeneric + requestId; retry offered