5.5 KiB
5.5 KiB
Walk-Through Check-Ins Backend
Purpose
walkthrough_checkins stores structured classroom-observation ("walk-through") records for
director-level staff. Each record captures the observed teacher, classroom, observing director,
date/time, seven rated categories with optional per-category comments, and overall notes. The
backend owns tenant scope, campus scope, creator ownership, validation, and role-gated access.
Slice Files (by layer)
- Route:
src/routes/walkthrough_checkins.ts(thin wiring;GET /,POST /,DELETE /:id). - Controller:
src/api/controllers/walkthrough_checkins.controller.ts(custom — not the CRUD factory; usesparamStrfor the id param). - Service (BLL):
src/services/walkthrough_checkins.ts(+walkthrough_checkins.types.tsforWalkthroughInput/WalkthroughFilter). - Repository (DAL): queries run through
db.walkthrough_checkinsinside the service (no separatedb/api/walkthrough_checkins.ts). - Model:
src/db/models/walkthrough_checkins.ts. - Shared used:
services/shared/validate.ts(nullableString);db/with-transaction.ts(withTransaction);shared/constants/pagination.ts(resolvePagination);shared/constants/walkthrough.ts(WALKTHROUGH_MANAGER_ROLE_NAMES,WALKTHROUGH_TENANT_WIDE_ROLE_NAMES);services/shared/access.ts(getOrganizationIdOrGlobal,hasGlobalAccess,hasRoleAccess,requireUserId);shared/errors/*(ForbiddenError,ValidationError). Note: the service defines a module-localgetCampusIdandcampusScope(staff-profile campus only), not the shared access helpers.
API
All routes require JWT authentication. Base path mounted at /api/walkthrough_checkins.
GET /api/walkthrough_checkins->200{ rows, count }. Optional queryteacher_name, pluslimit/page(paginated viaresolvePagination). Returns check-ins visible to the current manager, ordered bycheck_in_datedesc thencreatedAtdesc.POST /api/walkthrough_checkins->201. Request body wrapped as{ data: <WalkthroughInput> }. Returns the created check-in DTO.DELETE /api/walkthrough_checkins/:id->200{ deletedCount }. Deletes one check-in visible to the current manager.
Access Rules
- All operations require a role in
WALKTHROUGH_MANAGER_ROLE_NAMES(Super Administrator,Administrator,Platform Owner,Tenant Director,Campus Manager) orglobalAccess, enforced byassertCanManage(which also requires an authenticated user); otherwiseForbiddenError. Users withglobalAccessare always allowed. - Campus visibility: roles in
WALKTHROUGH_TENANT_WIDE_ROLE_NAMES(Super Administrator,Administrator,Platform Owner,Tenant Director) orglobalAccesssee all org records; other managers (e.g.Campus Manager) are restricted to their own staff campus onlistanddeleteviacampusScope.
Tenant Scope
- Organization is resolved via
getOrganizationIdOrGlobal: global access users bypass the org filter and see check-ins across all organizations; regular users are bound to their org. campusIdis resolved from the module-localgetCampusId— the current staff profile's campus only (currentUser.staff_user[0].campusId), elsenull; it never falls back to the user's owncampusId.- On create,
createdByIdis required from the current user (requireUserId);updatedByIdfrom the current user.
Data Contract
- Required mutation fields:
teacher_name,classroom,director_name,check_in_date,check_in_time(non-empty strings); and the seven rating fieldsattitude_rating,classroom_management_rating,cleanliness_rating,vibes_rating,team_dynamics_rating,emergency_exit_rating,lesson_plan_rating(finite numbers). Invalid input raisesValidationError. - Optional mutation fields: the matching per-category comments (
attitude_comment,classroom_management_comment,cleanliness_comment,vibes_comment,team_dynamics_comment,emergency_exit_comment,lesson_plan_comment) andoverall_notes. Comments are normalized vianullableString(trimmed, blank ->null). - DTO fields:
id, the five required strings, the seven*_ratingand matching*_commentfields,overall_notes,organizationId,campusId,createdById,updatedById,createdAt,updatedAt. - Model columns: the five required strings are TEXT not null except
check_in_date(DATEONLY) andcheck_in_time(TIME); the seven*_ratingare INTEGER not null; the seven*_commentandoverall_notesare TEXT nullable;importHash(unique). Tenant/audit columns:organizationId(not null),createdById(not null),campusId(nullable),updatedById(nullable). The model isparanoid(soft delete viadeletedAt) and usesfreezeTableName. - Associations:
belongsToorganizations (organization), campuses (campus), users (createdBy,updatedBy). Note: there is nouserassociation on this model.
Behavior / Notes
createruns insidewithTransaction; required string fields are trimmed before persistence.listis paginated with shared defaults (resolvePagination).removeis a harddestroyscoped byid+ organization +campusScope, returning the number of rows deleted (no transaction wrapper).
Tests
None yet (no walkthrough_checkins unit/e2e test in src/).
Related
- Frontend:
frontend/docs/walkthrough-integration.md. - Related slices:
frame-entries.md(similar editor-role-gated, campus-resolved director workflow),safety-quiz-results.md,personality-quiz-results.md.