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

01 — Product Overview (Rooms Module)

StudyLyon — multi-tenant ERP / School Management API. This package designs the Rooms module client (Flutter, forward-looking spec) against the implemented NestJS backend. All endpoints, DTO fields, schemas, and wire contracts are derived directly from src/modules/rooms/**, src/modules/rbac/permissions.constants.ts, src/database/base.schema.ts + base.repository.ts, and src/common/dto/pagination-query.dto.ts. No feature is invented; gaps are flagged in §10 and the module Assumptions & Open Questions.


1. Purpose

Rooms is the physical-facility registry of an institution: a tenant-scoped catalog of classrooms, labs, libraries, offices, halls, and other spaces. It is the reference data that future scheduling surfaces (timetable, bookings) will hang off — a room is only bookable if it exists as a document in rooms.

ResponsibilitySource
Room CRUD (name, code, capacity, type, building, facilities)rooms.controller.ts:24-52; rooms.service.ts:18-51
Tenant-scoped storage + soft-delete filteringroom.repository.ts:9-15; base.repository.ts:20-30
Room code uniqueness per tenant (create-time)rooms.service.ts:19-21; room.schema.ts:38
Room type taxonomyroom.schema.ts:7-14 (classroom/lab/library/office/hall/other)
Paginated list contractrooms.service.ts:29-33; pagination-query.dto.ts:32-54
RBAC permissions rooms.read/create/update/delete (declared, not enforced server-side)permissions.constants.ts:50-53
Soft delete (logical, isDeleted + deletedAt, never hard)rooms.service.ts:48-51; base.repository.ts:68-74

2. Business goals

GoalMeasureSource
Every bookable/schedulable space is catalogued once per tenantone rooms document per physical room; unique (tenantId, code)room.schema.ts:38
No cross-tenant data leakagerepository injects tenantId + isDeleted:false on every querybase.repository.ts:20-30
Duplicate codes fail fast with a clear message409 ConflictException "Room code ... already exists."rooms.service.ts:19-21
Deletion is reversiblesoft delete only; list/detail never return deleted docsrooms.service.ts:48-51
Safe growth toward timetable/bookingsrooms are the reference entity; bookings marked (planned) below§9

3. User goals

  • Org Admin / Admin Staff: create, edit, filter, and retire the room catalog; keep codes, types, capacities, buildings, and facilities accurate.
  • Timetable Coordinator (admin staff): browse rooms by type/building/capacity to plan where classes run (timetable module (planned)docs/IMPLEMENTATION_PLAN.md:227).
  • Teacher / staff: look up a room (location, capacity, facilities) before/while using it.
  • Platform Super Admin: cross-tenant visibility only via platform tooling; never operates inside a tenant's room data.

4. Stakeholders

Org Admins, admin staff (timetable coordinator, office staff), teachers, students/parents (via future booking/QR surfaces), facility/estate management, platform ops (tenant isolation), engineering/design/QA consuming these docs.

5. Why this exists

Every class, exam, and (future) booking needs a physical space. Without a room registry, timetable entries would reference free-text room names — no capacity check, no duplicate detection, no facility matching. Rooms is the smallest reference module that makes timetable ((planned)), bookings ((planned)), and exam seating meaningful.

6. Dependencies (module + platform)

DependencyRoleStatus
Auth (JwtAuthGuard)every endpoint requires Bearer JWTimplemented (rooms.controller.ts:19)
RBACrooms.* permissions declared in ALL_PERMISSIONSdeclared (permissions.constants.ts:50-53); guard enforcement (planned) — see OQ-2
Tenant context (TenantContextService)tenant scoping via BaseRepositoryimplemented (base.repository.ts:20-30)
Mongoose (collection rooms)persistence, unique indeximplemented (rooms.module.ts:13; room.schema.ts:38)
Swagger@ApiTags('rooms'), @ApiOperation, DTO @ApiProperty*implemented (rooms.controller.ts:12,17,25; create-room.dto.ts:12-38)
Timetable moduleconsumes rooms as venue reference(planned)IMPLEMENTATION_PLAN.md:227
Bookings moduleroom availability, check-in(planned) — not yet in IMPLEMENTATION_PLAN.md
QR room signage / check-inscan room code → room detail(forward-looking)

7. Success metrics

  • Zero duplicate (tenantId, code) pairs reach the DB (create check + unique index).
  • Room list p95 < 300 ms (paginated find + count).
  • Soft-deleted rooms never appear in list/detail (repository scope).
  • Delete of an unknown id returns 404, never 500.
  • Cross-tenant id access returns 404 (scoped filter), no existence leak.

8. Edge cases

Edge caseBehaviourSource
Duplicate room code on create409 ConflictException Room code "X" already exists.rooms.service.ts:19-21
Duplicate room code on updateNo service check$set runs; unique index {tenantId, code} may raise Mongo 11000 → 500. Gap flagged OQ-1rooms.service.ts:42-46; room.schema.ts:38
PATCH with partial bodyController reuses CreateRoomDto (rooms.controller.ts:44) — name/code are required even on PATCH; missing → 400 VALIDATION_ERRORrooms.controller.ts:44; create-room.dto.ts:12-18
capacity <= 0 or non-integerNo @Min/@IsInt — only @IsNumber; negative/fractional accepted. Client validation (proposed)create-room.dto.ts:20-23
type outside enum400 VALIDATION_ERROR (@IsEnum)create-room.dto.ts:25-28
Invalid ObjectId in :idCastError → 400 VALIDATION_ERROR "Invalid resource identifier."http-exception.filter.ts (shared)
Unknown or soft-deleted id404 RESOURCE_NOT_FOUND (NotFoundException rooms.service.ts:38,44,50)rooms.service.ts:36-51
Delete of a room referenced by timetable/bookingsNo in-use guard today — deletes succeed; consumers must handle missing venue. Guard (planned)rooms.service.ts:48-51
Cross-tenant id accessscoped filter → 404, never leakbase.repository.ts:24-29

9. Assumptions

  1. Client scope flag (matches 00-shared/01 §9): native mobile apps are out of Phase 1 (PRODUCT_REQUIREMENTS_DOCUMENT.md:144); these docs are forward-looking full client specs against the implemented API. Module-specific (forward-looking) marks apply to QR and room check-in surfaces.
  2. Rooms surface is admin-owned (rooms.create/update/delete), read is broader (rooms.read); timetable coordinators and teachers read the catalog.
  3. (planned) items: bookings module, RBAC guard enforcement, in-use delete guard, server-side capacity bounds, update-path duplicate check — flagged in §10.
  4. (forward-looking): QR room signage, room check-in/check-out, availability calendar.
  5. (proposed): analytics events (see 05/09) and client-side validation rules — the backend DTOs impose no min/max on capacity, no length limits on name/code.
  6. The wire contract (envelope, pagination meta, error codes) follows 00-shared/07.

10. Assumptions & Open Questions

#ItemStatus / Impact
OQ-1Update path has no duplicate-code check. update() blindly $sets (rooms.service.ts:42-46); changing code to an existing one hits the unique index (room.schema.ts:38) → Mongo E11000 → generic 500. Pre-check + 409 (planned).Room editor (code change)
OQ-2RBAC not enforced on the controller. Only JwtAuthGuard (rooms.controller.ts:19); rooms.* perms (permissions.constants.ts:50-53) are declared but no @Permissions guard. Client must gate UI; server guard (planned).All screens
OQ-3List has no sort/filter/search. findAll accepts only page/limit (rooms.controller.ts:32); PaginationQueryDto's sort/q (pagination-query.dto.ts:21-29) are unused. Default order is Mongo natural (_id) order — no -createdAt sort. Filters (planned).Room list
OQ-4No in-use delete guard. remove() soft-deletes regardless of timetable/bookings references (rooms.service.ts:48-51). Guard on reference counts (planned) with bookings/timetable modules.Delete dialog
OQ-5No status (operational), floor, or equipment fields — schema is name/code/capacity/type/building/facilities (room.schema.ts:18-34); facilities: string[] is the closest to equipment. Additions (proposed)/(planned); the client must not invent fields the API won't return.Room model
OQ-6No update-room.dto.ts. PATCH reuses CreateRoomDto (rooms.controller.ts:44) so name+code are mandatory on every update. A true partial DTO (planned).Room editor
OQ-7Capacity unvalidated@IsNumber only (create-room.dto.ts:20-23); negative/0/fractional capacities persist. Server @Min(1) (planned); client blocks < 1 (proposed) today.Room form
OQ-8Delete returns no payloadremove() is Promise<void> (rooms.service.ts:48); client reconciles locally.Delete dialog

11. Glossary

TermMeaningSource
RoomTenant-scoped physical space document (rooms collection)room.schema.ts:16-35
Room codeShort unique-per-tenant identifier (e.g. LAB-02, A-101)room.schema.ts:21-22,38
Room typeclassroom/lab/library/office/hall/otherroom.schema.ts:7-14
FacilitiesFree-text feature tags (projector, AC, smartboard …)room.schema.ts:33-34
Soft deleteisDeleted:true + deletedAt; excluded from all queriesbase.schema.ts:19-24; base.repository.ts:20-30
Envelope{success,message,data,meta?,timestamp,requestId}07_API_Conventions.md §2-3
Permissionrooms.read / rooms.create / rooms.update / rooms.deletepermissions.constants.ts:50-53