40227-vm/backend/docs/frame-entries.md
2026-06-12 06:55:35 +02:00

2.8 KiB

FRAME Entries Backend

Purpose

frame_entries stores weekly F.R.A.M.E. focus entries per organization. The backend is the source of truth for persisted FRAME data; the frontend never substitutes static samples for it.

Slice Files (by layer)

  • Route: src/routes/frame_entries.ts (thin wiring; GET /, POST /, PUT /:id).
  • Controller: src/api/controllers/frame_entries.controller.ts (custom — not the CRUD factory).
  • Service (BLL): src/services/frame_entries.ts.
  • Repository (DAL): queries run through db.frame_entries inside the service (no separate db/api/frame_entries.ts).
  • Model: src/db/models/frame_entries.ts.
  • Shared used: db/with-transaction.ts (withTransaction), services/shared/access.ts (getOrganizationIdOrGlobal, hasRoleAccess), shared/constants/pagination.ts (resolvePagination), shared/constants/frame.ts (FRAME_EDITOR_ROLE_NAMES), shared/errors/* (ForbiddenError, ValidationError).

API

All routes require JWT authentication.

  • GET /api/frame_entries -> 200 { rows, count } for the current user's organization (paginated via resolvePagination).
  • POST /api/frame_entries -> 201 the created entry DTO.
  • PUT /api/frame_entries/:id -> 200 the updated entry DTO (scoped to the org).

Request body for create/update is wrapped as { data: <FrameEntryInput> }.

Access Rules

  • Read: any authenticated user in the organization, or any user with globalAccess (sees all organizations).
  • Edit (create/update): restricted to roles in FRAME_EDITOR_ROLE_NAMES (director/superintendent capabilities) — super_admin, system_admin, owner, superintendent, director. Enforced by assertCanEdit via hasRoleAccess; a non-editor gets ForbiddenError. Frontend may hide editing controls, but the backend check is authoritative.

Tenant Scope

  • Organization is resolved via getOrganizationIdOrGlobal: users with globalAccess bypass the org filter and see/create entries across all organizations; regular users are bound to their organization.
  • campusId is optional; when omitted it defaults to the current staff profile's campus (currentUser.staff_user[0].campusId) when available, else null.

Data Contract

Required request fields (REQUIRED_FIELDS): week_of, posted_date, formal, recognition, application, management, emotional, author. Optional: campusId. Missing/invalid input raises ValidationError.

Behavior / Notes

  • Create/update run inside withTransaction.
  • List is paginated with the shared defaults (resolvePagination).

Tests

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

  • Frontend: frontend/docs/frame-integration.md.
  • Related slices: user-progress.md (dashboard zone check-ins), staff (campus resolution).