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.findAlldirectly (it does not go throughsrc/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 bynameascending.countisrows.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
attributesso 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/).
Related
- Frontend:
frontend/docs/campus-catalog.md. - Related slices: campuses CRUD (authenticated
/api/campuses, routesrc/routes/campuses.ts, repositorysrc/db/api/campuses.ts) for create/update/delete of campus records.