Skip to main content

Phase 5: Reports

Phase 5 delivers report group management, PDF report generation via SQS/Lambda, teacher remarks, and the report generation service.

Purpose

Manage the end-of-term workflow: collect teacher remarks, finalize report groups, and generate individual PDF report cards at scale (500--1,500 students) via Lambda fan-out.

Key Models

ModelPurpose
ReportGroupContainer for a term's reports (Draft -> Finalized)
GeneratedReportIndividual student PDF with calculatedScores JSONB snapshot
GeneratedReportScoreWrite-once score rows captured at generation time
TeacherRemarkClass teacher and principal remarks per student per period
ReportGroupAuditLogAudit trail for report group state changes

Report Generation Flow

Critical Rules

  • JSONB immutability: GeneratedReport.calculatedScores is written once and never updated. Reprints use the stored snapshot.
  • GeneratedReportScore write-once: On regeneration, delete existing rows and insert new ones in a single transaction.
  • One PDF per Lambda invocation: renderToBuffer() is never called in a loop. See ADR-003.
  • Finalize permission: Only ADMIN, PRINCIPAL, or VICE_PRINCIPAL can finalize report groups.

API Endpoints

MethodPathPurpose
GET/POST/api/admin/report-groupsList / create report groups
GET/PATCH/api/admin/report-groups/[id]Detail / update
POST/api/admin/report-groups/[id]/finalizeFinalize (locks data)
POST/api/admin/report-groups/[id]/generateTrigger PDF generation
GET/api/admin/report-groups/[id]/preview/[studentId]Preview single report
GET/PUT/api/admin/teacher-remarksList / upsert remarks

Key Files

  • src/lib/services/report-generation.ts -- buildStudentReportData, generateAndSaveReport
  • src/lib/sqs.ts -- SQS message sending
  • src/components/pdf/ReportDocument.tsx -- PDF template (@react-pdf/renderer)
  • src/app/admin/reports/ -- Report management UI