fix(list/map): report-card schools badged as Report Card, not their old grade #63

Merged
tudor merged 2 commits from fix/list-map-report-card-signal into main 2026-07-18 20:28:20 +00:00
Owner

Extends the report-card detection fix (#62) to the list/map surface for consistency.

What was wrong

Search-result cards (buildOfstedListBadge) and map pins (buildPopupBadge) detected report cards with ofsted_framework === 'ReportCard' — but the API sets ofsted_framework to the raw event grouping ("Schools - S5"), so that never matched. Worse, ofsted_grade (the carried-forward legacy grade) was checked first and won. So report-card schools were badged by their old grade: Barclay's pin and card read "Outstanding · 2021" instead of "Report Card · 2026". Same root cause as #62, different surface.

Fix

  • Backend: expose ofsted_rc_date on the list serialization — the report-card inspection date, non-null only when the latest inspection carries report-card grades. It joins from fact_ofsted_inspection.rc_inspection_date; the fallback queries inherit it via the existing string-replacement derivation.
  • Frontend: both badge builders now treat a present ofsted_rc_date as winning over any grade, labelling "Report Card · {rc year}". Removed the dead framework === 'ReportCard' branches.

Tests

  • Unit: buildOfstedListBadge now asserts the ofsted_rc_date path and, crucially, that a report card wins over a carried-forward legacy grade (the Barclay case). 102 frontend + 52 backend green.
  • e2e: searching a real report-card school asserts its result card shows a "Report Card ·" badge (precondition-guarded on the list exposing ofsted_rc_date).

Note

Two full-object helpers in lib/utils.ts (buildOfstedHeroChip, buildSchoolSummary) still branch on framework === 'ReportCard', but both are dead code (no consumers) — left untouched rather than expand scope; worth deleting in a cleanup.

🤖 Generated with Claude Code

https://claude.ai/code/session_0146VHeLAWjDVE2B5uU67jCB

Extends the report-card detection fix (#62) to the list/map surface for consistency. ## What was wrong Search-result cards (`buildOfstedListBadge`) and map pins (`buildPopupBadge`) detected report cards with `ofsted_framework === 'ReportCard'` — but the API sets `ofsted_framework` to the raw event grouping (`"Schools - S5"`), so that never matched. Worse, `ofsted_grade` (the **carried-forward legacy grade**) was checked first and won. So report-card schools were badged by their old grade: Barclay's pin and card read **"Outstanding · 2021"** instead of **"Report Card · 2026"**. Same root cause as #62, different surface. ## Fix - **Backend:** expose `ofsted_rc_date` on the list serialization — the report-card inspection date, non-null only when the latest inspection carries report-card grades. It joins from `fact_ofsted_inspection.rc_inspection_date`; the fallback queries inherit it via the existing string-replacement derivation. - **Frontend:** both badge builders now treat a present `ofsted_rc_date` as **winning over any grade**, labelling "Report Card · {rc year}". Removed the dead `framework === 'ReportCard'` branches. ## Tests - Unit: `buildOfstedListBadge` now asserts the `ofsted_rc_date` path and, crucially, that **a report card wins over a carried-forward legacy grade** (the Barclay case). 102 frontend + 52 backend green. - e2e: searching a real report-card school asserts its result card shows a "Report Card ·" badge (precondition-guarded on the list exposing `ofsted_rc_date`). ## Note Two full-object helpers in `lib/utils.ts` (`buildOfstedHeroChip`, `buildSchoolSummary`) still branch on `framework === 'ReportCard'`, but both are **dead code** (no consumers) — left untouched rather than expand scope; worth deleting in a cleanup. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_0146VHeLAWjDVE2B5uU67jCB
tudor added 1 commit 2026-07-18 20:15:18 +00:00
fix(list/map): badge report-card schools as Report Card, not their carried-forward grade
PR Checks / Frontend Typecheck + Tests (pull_request) Successful in 1m5s
PR Checks / Backend Smoke (pull_request) Successful in 7s
PR Checks / Build Backend (no push) (pull_request) Successful in 17s
PR Checks / Build Frontend (no push) (pull_request) Successful in 47s
PR Checks / Build Pipeline (no push) (pull_request) Successful in 10s
PR Checks / AI Code Review (Claude) (pull_request) Successful in 2m48s
5ec4f3f7cd
The search-result cards and map pins keyed report-card detection off
ofsted_framework === 'ReportCard', but the API sets ofsted_framework to the
raw event grouping ('Schools - S5'); worse, ofsted_grade (the carried-forward
legacy grade) was checked first and won. So report-card schools were badged
by their old grade — Barclay's pin/card read 'Outstanding · 2021' instead of
'Report Card · 2026'. Same root cause as the detail-page fix, different
surface.

Expose ofsted_rc_date on the list serialization (the report-card inspection
date, non-null only for report cards) and make both badge builders treat a
present rc-date as winning over any grade, using its year. Removes the dead
framework === 'ReportCard' branches.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0146VHeLAWjDVE2B5uU67jCB

🤖 AI Code Review (Claude Code)

This PR plumbs a new ofsted_rc_date field from the marts.fact_ofsted_inspection mart through the backend query/schema and into the list/map frontend, so report-card schools are badged 'Report Card · YYYY' instead of showing their stale carried-forward legacy grade. I traced the SQL, the dbt mart/staging models, and the frontend badge logic (utils.ts, LeafletMapInner.tsx) and the fix is correct and consistent with how the detail page already surfaces rc_inspection_date; only minor test-quality and doc-staleness issues remain.

🟡 Minor

  • e2e/tests/journeys.spec.ts: The new e2e test's precondition check (test.skip(!barclay?.ofsted_rc_date, ...)) causes the test to silently skip rather than fail if the backend ever stops exposing ofsted_rc_date for this school — masking exactly the regression the test is meant to catch.
  • e2e/tests/journeys.spec.ts: The precondition API call uses per_page=5, which is not a parameter the backend recognizes (it's page_size); the request silently falls back to the default page size instead of limiting results.
  • nextjs-app/lib/utils.ts: The docstring above buildOfstedListBadge still says report cards are detected via ofsted_framework === 'ReportCard', which is the bug this PR fixes — the comment was not updated to describe the new ofsted_rc_date-based check.
## 🤖 AI Code Review (Claude Code) This PR plumbs a new `ofsted_rc_date` field from the `marts.fact_ofsted_inspection` mart through the backend query/schema and into the list/map frontend, so report-card schools are badged 'Report Card · YYYY' instead of showing their stale carried-forward legacy grade. I traced the SQL, the dbt mart/staging models, and the frontend badge logic (utils.ts, LeafletMapInner.tsx) and the fix is correct and consistent with how the detail page already surfaces rc_inspection_date; only minor test-quality and doc-staleness issues remain. ### 🟡 Minor - **e2e/tests/journeys.spec.ts**: The new e2e test's precondition check (`test.skip(!barclay?.ofsted_rc_date, ...)`) causes the test to silently skip rather than fail if the backend ever stops exposing ofsted_rc_date for this school — masking exactly the regression the test is meant to catch. - **e2e/tests/journeys.spec.ts**: The precondition API call uses `per_page=5`, which is not a parameter the backend recognizes (it's `page_size`); the request silently falls back to the default page size instead of limiting results. - **nextjs-app/lib/utils.ts**: The docstring above buildOfstedListBadge still says report cards are detected via `ofsted_framework === 'ReportCard'`, which is the bug this PR fixes — the comment was not updated to describe the new ofsted_rc_date-based check.
tudor added 1 commit 2026-07-18 20:24:11 +00:00
test/docs: harden report-card list e2e + correct badge docstring
PR Checks / Frontend Typecheck + Tests (pull_request) Successful in 1m2s
PR Checks / Backend Smoke (pull_request) Successful in 6s
PR Checks / Build Backend (no push) (pull_request) Successful in 17s
PR Checks / Build Frontend (no push) (pull_request) Successful in 48s
PR Checks / Build Pipeline (no push) (pull_request) Successful in 9s
PR Checks / AI Code Review (Claude) (pull_request) Failing after 1m4s
b2b2cad5ac
Review fixes on the list/map report-card PR:
- e2e precondition now hard-asserts ofsted_rc_date instead of test.skip, so
  the backend dropping the field fails loudly (that's the regression under
  test), not silently skips.
- Use page_size=5 (the real backend param); per_page was ignored and fell
  back to the default page size.
- Update buildOfstedListBadge docstring to describe the ofsted_rc_date-based,
  report-card-wins-first detection instead of the removed framework check.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0146VHeLAWjDVE2B5uU67jCB
tudor merged commit a2c63b3cda into main 2026-07-18 20:28:20 +00:00
Sign in to join this conversation.
No Reviewers
No labels
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: tudor/school_compare#63