feat(data): integrate 9 UK government data sources via Kestra
Some checks failed
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 47s
Build and Push Docker Images / Trigger Portainer Update (push) Has been cancelled
Build and Push Docker Images / Build Frontend (Next.js) (push) Has been cancelled

Adds a full data integration pipeline for enriching school profiles with
supplementary data from Ofsted, GIAS, EES, IDACI, and FBIT.

Backend:
- Bump SCHEMA_VERSION to 3; add 8 new DB tables (ofsted_inspections,
  ofsted_parent_view, school_census, admissions, sen_detail, phonics,
  school_deprivation, school_finance) plus GIAS columns on schools
- Expose all supplementary data via GET /api/schools/{urn}
- Enrich school list responses with ofsted_grade + ofsted_date

Integrator (new service):
- FastAPI HTTP microservice; Kestra calls POST /run/{source}
- 9 source modules: ofsted, gias, parent_view, census, admissions,
  sen_detail, phonics, idaci, finance
- 9 Kestra flow YAMLs with scheduled triggers and 3× retry

Frontend:
- SchoolRow: colour-coded Ofsted badge (Outstanding/Good/RI/Inadequate)
- SchoolDetailView: 7 new sections — Ofsted sub-judgements, Parent View
  survey bars, Admissions, Pupils & Inclusion / SEN, Phonics, Deprivation
  Context, Finances
- types.ts: 8 new interfaces + extended School/SchoolDetailsResponse

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-24 11:44:04 +00:00
parent c49593d4d6
commit dd49ef28b2
36 changed files with 2849 additions and 8 deletions

View File

@@ -12,6 +12,13 @@ import { formatPercentage, formatProgress, calculateTrend } from '@/lib/utils';
import { progressBand } from '@/lib/metrics';
import styles from './SchoolRow.module.css';
const OFSTED_LABELS: Record<number, string> = {
1: 'Outstanding',
2: 'Good',
3: 'Req. Improvement',
4: 'Inadequate',
};
interface SchoolRowProps {
school: School;
isLocationSearch?: boolean;
@@ -46,7 +53,7 @@ export function SchoolRow({
{/* Left: three content lines */}
<div className={styles.rowContent}>
{/* Line 1: School name + type */}
{/* Line 1: School name + type + Ofsted badge */}
<div className={styles.line1}>
<a href={`/school/${school.urn}`} className={styles.schoolName}>
{school.school_name}
@@ -54,6 +61,11 @@ export function SchoolRow({
{school.school_type && (
<span className={styles.schoolType}>{school.school_type}</span>
)}
{school.ofsted_grade && (
<span className={`${styles.ofstedBadge} ${styles[`ofsted${school.ofsted_grade}`]}`}>
{OFSTED_LABELS[school.ofsted_grade]}
</span>
)}
</div>
{/* Line 2: Key stats */}