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
| Model | Purpose |
|---|---|
ReportGroup | Container for a term's reports (Draft -> Finalized) |
GeneratedReport | Individual student PDF with calculatedScores JSONB snapshot |
GeneratedReportScore | Write-once score rows captured at generation time |
TeacherRemark | Class teacher and principal remarks per student per period |
ReportGroupAuditLog | Audit trail for report group state changes |
Report Generation Flow
Critical Rules
- JSONB immutability:
GeneratedReport.calculatedScoresis 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
| Method | Path | Purpose |
|---|---|---|
| GET/POST | /api/admin/report-groups | List / create report groups |
| GET/PATCH | /api/admin/report-groups/[id] | Detail / update |
| POST | /api/admin/report-groups/[id]/finalize | Finalize (locks data) |
| POST | /api/admin/report-groups/[id]/generate | Trigger PDF generation |
| GET | /api/admin/report-groups/[id]/preview/[studentId] | Preview single report |
| GET/PUT | /api/admin/teacher-remarks | List / upsert remarks |
Key Files
src/lib/services/report-generation.ts--buildStudentReportData,generateAndSaveReportsrc/lib/sqs.ts-- SQS message sendingsrc/components/pdf/ReportDocument.tsx-- PDF template (@react-pdf/renderer)src/app/admin/reports/-- Report management UI