fix(api): treat "16 plus" as secondary, the way PHASE_GROUPS already does
PR Checks / Frontend Typecheck + Tests (pull_request) Canceled after 9s
PR Checks / Backend Smoke (pull_request) Canceled after 0s
PR Checks / Build Backend (no push) (pull_request) Canceled after 0s
PR Checks / Build Frontend (no push) (pull_request) Canceled after 0s
PR Checks / Build Pipeline (no push) (pull_request) Canceled after 0s
PR Checks / AI Code Review (Claude) (pull_request) Canceled after 0s

GIAS phase 6 is "16 plus", and PHASE_GROUPS deliberately files it in the
secondary group. The payload helper decided the same question with
`"secondary" in phase_text`, which that value does not satisfy — so a
sixth-form college was handed the primary bucket and offered infant schools
as its peers, with the KS2 metric key to label them. No crash; just a page
confidently showing the wrong schools.

The decision now lives in similar_schools.is_secondary_phase, beside the
PHASE_GROUPS bucket it selects from, so the two cannot drift again. A test
pins them together.

The same binary assumption had a second output. computeSchoolFlags tests for
the substring too, so a 16-plus school renders the primary template, and the
composer was labelling the section from the template: "Other primary schools
near <sixth form college>" above a row of secondaries. The section now
derives its noun from the school's own phase, which also removes the
duplicated wording from both composers. A 16-plus school's candidates span
the whole secondary group, so no single noun fits and it gets the honest
general one.

Reported in review on #150.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
TudorandClaude Opus 5 committed 2026-09-22 06:41:49 +01:00
1 parent bd2a6c385b
commit 2175dccb7c
7 files changed
+121 -14

No files matched your search

+7 -6
View File
@@ -41,7 +41,7 @@ from .data_loader import get_data_info as get_db_info
from . import flags
from .places import build_place_index, build_place_registry, places_for_urn
from .schemas import METRIC_DEFINITIONS, PHASE_GROUPS, RANKING_COLUMNS, SCHOOL_COLUMNS
from .similar_schools import select_similar
from .similar_schools import is_secondary_phase, select_similar
from .utils import clean_for_json, convert_to_native
# Values to exclude from filter dropdowns (empty strings, non-applicable labels)
@@ -274,11 +274,12 @@ def _similar_schools_payload(urn: int, phase: str | None) -> list[dict]:
section simply does not render.
"""
try:
phase_text = (phase or "").lower()
# All-through schools render with the primary template, which is what
# decides the metric, so they are not secondary here.
is_secondary = phase_text != "all-through" and "secondary" in phase_text
return select_similar(load_latest_school_data(), int(urn), is_secondary)
# Decided in similar_schools, beside the PHASE_GROUPS bucket it selects
# from, so the two cannot drift. A substring test for "secondary" here
# would miss "16 plus" and hand a sixth-form college the primary bucket.
return select_similar(
load_latest_school_data(), int(urn), is_secondary_phase(phase)
)
except Exception:
import logging