40227-vm/backend/docs/campus-catalog.md
2026-06-10 18:27:19 +02:00

3.3 KiB

Campus Catalog Backend

Purpose

This slice is the public, read-only surface for campus records: it returns the active campuses with their branding tokens so the frontend can render them without shipping campus rows as runtime constants. The database is the source of truth for campuses. Authenticated campus create/update/delete lives in a separate slice (see "campuses CRUD" below); this slice does not write.

Slice Files (by layer)

  • Route: src/routes/public_campuses.ts (thin wiring; GET /).
  • Controller: src/api/controllers/public_campuses.controller.ts (custom — not the CRUD factory).
  • Service (BLL): src/services/campus_catalog.ts.
  • Repository (DAL): the catalog service queries db.campuses.findAll directly (it does not go through src/db/api/campuses.ts; that repository serves the authenticated campuses CRUD slice).
  • Model: src/db/models/campuses.ts.
  • Shared used: none beyond db/models.

API

The slice is mounted at /api/public/campuses in src/index.ts. Unlike the authenticated routes, this mount is registered before the jwt guard and has no authentication middleware — it is a public endpoint.

  • GET /api/public/campuses -> 200 { rows, count }. No request parameters are read (the controller ignores the request). Each row is the campus catalog DTO below; rows are ordered by name ascending. count is rows.length.

Access Rules

Public. No JWT, no role check, no per-user gating. Only campuses with active = true are returned.

Tenant Scope

None. The query filters solely on active = true and is not scoped to any organization or campus — it returns active campuses across all organizations.

Data Contract

Campus catalog DTO (toCampusCatalogDto, also reflected in the service's selected attributes): id, name, code, mascot, color, bgGradient, borderColor, textColor, bgLight, description, isOnline. Other campus columns (address, phone, email, organizationId, audit fields) are intentionally not exposed by this endpoint.

Relevant campuses model fields: id (UUID PK), name (TEXT, not null), code (TEXT, not null), address / phone / email (TEXT, nullable), mascot, color, bgGradient, borderColor, textColor, bgLight, description (all TEXT, nullable), isOnline (BOOLEAN, not null, default false), active (BOOLEAN, not null, default false), importHash (unique, nullable), organizationId (UUID, nullable), audit fields createdById / updatedById, and createdAt / updatedAt / deletedAt. The model is paranoid (soft delete) with freezeTableName. Associations include belongsTo organization, createdBy, updatedBy, and hasMany students, staff, classes, timetables, attendance_sessions, invoices, messages, documents (all keyed on campusId).

Behavior / Notes

  • The service selects only the catalog attributes so the SQL fetches just the columns the DTO needs.
  • Because the filter is { active: true } with no tenant scope, inactive campuses are never returned and the result is not paginated.

Tests

None yet (no campus_catalog / public_campuses unit/e2e test in src/).

  • Frontend: frontend/docs/campus-catalog.md.
  • Related slices: campuses CRUD (authenticated /api/campuses, route src/routes/campuses.ts, repository src/db/api/campuses.ts) for create/update/delete of campus records.