Part 2 of 2 for audit finding H2, with the E2E journeys for C2. Needs #185 merged and school_data_annual_ees run on staging before this merges.
What changes
/api/la-averages serves DfE's own LA averages from marts.fact_ks4_la_averages (built by #185), keyed by our LA name through the GIAS LA code. It used to average every school with an Attainment 8 in the LA, independent and special schools included: Kensington and Chelsea came out at 35.2 against DfE's 54.5, and most LAs about 7 points low. The year is the latest with any school Attainment 8. An LA without a DfE figure (City of London, suppressed values) is left out; no figures for that year, or no mart, give an empty map, so rows show no comparison rather than a wrong one. Response shape unchanged.
Independent schools get no "vs LA avg" on the search row or the map card (isIndependentSchool): DfE's LA average covers state-funded schools, and an independent's Attainment 8 leaves out IGCSEs. Their own Attainment 8 still shows.
E2E: Bishop Stopford's 2023/24 history row shows 64.1 / +1.0 / 91.7% (C2); an independent row in an LA search shows no gap while a state row in the same search shows one (H2); both LA journeys now fail rather than skip when the averages map is empty.
Evidence
backend 5 new tests; CI Python suite 348 passed; tsc clean; Jest 644 passed
New journeys run against staging before#185 and the EES run: both fail for the expected reasons (staging's 2023/24 row is 2023/24----; the independent row still shows a gap, after the state row's gap has rendered); the existing LA journey passes. They pass only once #185's data is on staging and this PR is deployed.
Merge and promotion order
#185 merged → school_data_annual_ees run on staging → merge this.
Production: promote #185 → run the EES DAG on production → promote this. If this arrives first, the endpoint returns an empty map and rows show no LA gap until the DAG has run.
Part 2 of 2 for audit finding **H2**, with the E2E journeys for **C2**. Needs #185 merged **and `school_data_annual_ees` run on staging** before this merges.
## What changes
- **`/api/la-averages`** serves DfE's own LA averages from `marts.fact_ks4_la_averages` (built by #185), keyed by our LA name through the GIAS LA code. It used to average every school with an Attainment 8 in the LA, independent and special schools included: Kensington and Chelsea came out at 35.2 against DfE's 54.5, and most LAs about 7 points low. The year is the latest with any school Attainment 8. An LA without a DfE figure (City of London, suppressed values) is left out; no figures for that year, or no mart, give an empty map, so rows show no comparison rather than a wrong one. Response shape unchanged.
- **Independent schools get no "vs LA avg"** on the search row or the map card (`isIndependentSchool`): DfE's LA average covers state-funded schools, and an independent's Attainment 8 leaves out IGCSEs. Their own Attainment 8 still shows.
- **E2E:** Bishop Stopford's 2023/24 history row shows 64.1 / +1.0 / 91.7% (C2); an independent row in an LA search shows no gap while a state row in the same search shows one (H2); both LA journeys now fail rather than skip when the averages map is empty.
## Evidence
- backend 5 new tests; CI Python suite 348 passed; `tsc` clean; Jest 644 passed
- New journeys run against staging **before** #185 and the EES run: both fail for the expected reasons (staging's 2023/24 row is `2023/24----`; the independent row still shows a gap, after the state row's gap has rendered); the existing LA journey passes. They pass only once #185's data is on staging and this PR is deployed.
## Merge and promotion order
1. #185 merged → `school_data_annual_ees` run on staging → merge this.
2. Production: promote #185 → run the EES DAG on production → promote this. If this arrives first, the endpoint returns an empty map and rows show no LA gap until the DAG has run.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
The journey passed whenever the LA map was empty or not yet rendered. It now
waits for a state school in the same LA to show its gap, and both LA journeys
fail rather than skip on an empty map.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
/api/la-averages now serves DfE's own per-LA Attainment 8 averages from marts.fact_ks4_la_averages, instead of a mean over every school in the dataframe. The year is the latest with any school Attainment 8. A missing mart or no figures for that year gives an empty map. The frontend drops the "vs LA avg" comparison for independent schools, and unit and e2e tests cover both changes. I found no correctness, security, or deploy problems in the diff.
✅ No issues found.
## 🤖 AI Code Review (Claude Code)
`/api/la-averages` now serves DfE's own per-LA Attainment 8 averages from `marts.fact_ks4_la_averages`, instead of a mean over every school in the dataframe. The year is the latest with any school Attainment 8. A missing mart or no figures for that year gives an empty map. The frontend drops the "vs LA avg" comparison for independent schools, and unit and e2e tests cover both changes. I found no correctness, security, or deploy problems in the diff.
✅ No issues found.
tudor
merged commit 2b5e681482 into main2026-10-06 15:07:37 +00:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Part 2 of 2 for audit finding H2, with the E2E journeys for C2. Needs #185 merged and
school_data_annual_eesrun on staging before this merges.What changes
/api/la-averagesserves DfE's own LA averages frommarts.fact_ks4_la_averages(built by #185), keyed by our LA name through the GIAS LA code. It used to average every school with an Attainment 8 in the LA, independent and special schools included: Kensington and Chelsea came out at 35.2 against DfE's 54.5, and most LAs about 7 points low. The year is the latest with any school Attainment 8. An LA without a DfE figure (City of London, suppressed values) is left out; no figures for that year, or no mart, give an empty map, so rows show no comparison rather than a wrong one. Response shape unchanged.isIndependentSchool): DfE's LA average covers state-funded schools, and an independent's Attainment 8 leaves out IGCSEs. Their own Attainment 8 still shows.Evidence
tscclean; Jest 644 passed2023/24----; the independent row still shows a gap, after the state row's gap has rendered); the existing LA journey passes. They pass only once #185's data is on staging and this PR is deployed.Merge and promotion order
school_data_annual_eesrun on staging → merge this.🤖 Generated with Claude Code
🤖 AI Code Review (Claude Code)
/api/la-averagesnow serves DfE's own per-LA Attainment 8 averages frommarts.fact_ks4_la_averages, instead of a mean over every school in the dataframe. The year is the latest with any school Attainment 8. A missing mart or no figures for that year gives an empty map. The frontend drops the "vs LA avg" comparison for independent schools, and unit and e2e tests cover both changes. I found no correctness, security, or deploy problems in the diff.✅ No issues found.