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

Exact endpoints per screen. Wire contract per 00-shared/07: base /api/v1, Bearer JWT, success {success:true,message:"OK",data,meta?,timestamp,requestId}, error envelope with codes. Only shapes in code are used. (planned)/(forward-looking) marked.


E1 — Create room

EndpointPOST /api/v1/rooms (rooms.controller.ts:24-28)
GuardJwtAuthGuard only (rooms.controller.ts:19); RBAC rooms.create not enforced server-side (OQ-2, permissions.constants.ts:51); client gates UI
RequestCreateRoomDto (create-room.dto.ts:11-38) — name, code required; capacity, type (enum, default classroom), building, facilities optional
Response201 envelope, data = saved room doc (rooms.service.ts:18-23); tenantId injected from context, never from body (base.repository.ts:32-36)
Errors400 VALIDATION_ERROR (missing name/code, bad type); 409 ConflictException "Room code "X" already exists." (rooms.service.ts:19-21); 401; 429 RATE_LIMITED; 5xx
ClientS3 create; on success → detail + snackbar; 409 → inline under code field
Cachenone (write); on success invalidate list cache key

E2 — List rooms

EndpointGET /api/v1/rooms?page&limit (rooms.controller.ts:30-34)
Paramspage ≥ 1 default 1; limit default 20 (rooms.controller.ts:32); no sort, q, or filters in codePaginationQueryDto.sort/q (pagination-query.dto.ts:21-29) unused on this route (OQ-3); order = Mongo natural (_id) order
Response200 envelope: data: Room[] + meta {page, limit, totalItems, totalPages, hasNext, hasPrevious} (rooms.service.ts:25-34; pagination-query.dto.ts:32-39,41-54)
Errors401; 429; 5xx
ClientS1; infinite scroll on hasNext; pull-to-refresh; client-side filter/search (proposed) until server params (planned)
Cacheclient paginated cache sl:{tenantId}:rooms:{page}:{limit} TTL 5 min; invalidated on E1/E4/E5 success

E3 — Get room by ID

EndpointGET /api/v1/rooms/:id (rooms.controller.ts:36-40)
Response200 envelope, data = room doc (rooms.service.ts:36-40)
Errors400 VALIDATION_ERROR (invalid ObjectId → CastError mapping, shared filter); 404 RESOURCE_NOT_FOUND "Room not found." (rooms.service.ts:38); cross-tenant id → 404, no existence leak (base.repository.ts:24-29); 401; 429
ClientS2 detail + S3 edit prefill; stale-while-revalidate OK

E4 — Update room

EndpointPATCH /api/v1/rooms/:id (rooms.controller.ts:42-46)
RequestCreateRoomDto (rooms.controller.ts:44) — there is no update-room.dto.ts (OQ-6); name+code remain required on PATCH; partial body → 400
BehaviourupdateById$set: dto + $inc: {version: 1}, returns updated doc (rooms.service.ts:42-46; base.repository.ts:57-66)
Errors400 (missing required fields, bad enum); 404 (rooms.service.ts:44); duplicate-code update → uncaught E11000 unique-index error → 500 (OQ-1) (room.schema.ts:38); 401; 429
ClientS3 edit; success → detail reconcile from response; client-side duplicate warning (proposed); server pre-check (planned) OQ-1
Cacheinvalidate list + detail keys on success

E5 — Delete room (soft)

EndpointDELETE /api/v1/rooms/:id (rooms.controller.ts:48-52)
Behavioursoft delete: isDeleted:true, deletedAt, deletedBy + version (rooms.service.ts:48-51; base.repository.ts:68-74); returns 200, no payload (void handler)
Errors404 (rooms.service.ts:50); 401; 429
Gapsno in-use guard (OQ-4) — succeeds even if referenced by timetable/bookings; hard purge not scheduled (rooms never hard-deleted in code)
ClientS4 typed-confirm dialog; on success remove row locally + snackbar; 404 → "already deleted"
AuditdeletedAt/deletedBy recorded (base.schema.ts:23-27) — future audit surface (planned) (IMPLEMENTATION_PLAN.md Phase 5)

Client contract summary (all screens)

ConcernRule
AuthBearer JWT; 401 → single-flight refresh → replay; fail → session expiry (00-shared/06 §3.6)
RBACserver does not enforce rooms.* today (OQ-2); client gates by permission list from permissions.constants.ts:50-53; when server guard lands, treat 403 as route-hide
Optimisticnone for mutations — server result always shown (delete is void; local removal after 200)
IdempotencyPATCH/DELETE retry-safe; no Idempotency-Key support confirmed
Offlinereads from last-good cache + banner; writes blocked (no module offline queue)
Paginationpage/limit + meta exact (pagination-query.dto.ts:5-54); infinite scroll driven by hasNext
Filteringclient-side (proposed); server params (planned) OQ-3
Realtimeno WS topics today; (forward-looking) rooms.updated for multi-device sync
Error mapping00-shared/06 §5: 400 field errors, 403 hide/deny, 404 empty/not-found, 409 inline duplicate, 429 backoff, 5xx generic+requestId

Endpoint → screen matrix

EndpointS1 ListS2 DetailS3 EditorS4 Delete
POST /roomscreate submit
GET /rooms?page&limitload/load-more/refreshduplicate hint (proposed)
GET /rooms/:idloadedit prefill
PATCH /rooms/:idreconcileedit submit
DELETE /rooms/:idrow removemenu triggerconfirm submit