feat(detail): surface GIAS identity/contact details, drop unwired sections
PR Checks / Frontend Typecheck + Tests (pull_request) Canceled after 58s
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

Add seven school-identity fields to the detail header (both primary and
secondary views): age range, religious character, nursery and sixth-form
indicators as chips; telephone (tel: link), county and parliamentary
constituency as header details. religious_denomination, age_range and
has_sixth_form were already served; telephone, nursery_provision, county
and parliamentary_constituency are newly wired through the marts query
(with a NULL fallback for un-rebuilt marts, mirroring has_sixth_form) and
the school_info API response.

Remove three UI sections the backend never populated (always null): Year 1
Phonics, the SEN "types of additional needs" breakdown, and the average
class-size card — along with their now-dead props, route plumbing, and the
SenDetail/Phonics types + class_size_avg field.

Extend the e2e detail journey to assert the Phonics section is gone and the
new header fields render when the record carries them.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Tudor
2026-07-24 09:23:08 +01:00
co-authored by Claude Opus 4.8
parent d02a323cdc
commit 0186227ced
7 changed files with 141 additions and 93 deletions
+42
View File
@@ -169,6 +169,8 @@ _MAIN_QUERY = text("""
s.total_pupils AS gias_total_pupils,
s.headteacher_name,
s.website,
s.telephone,
s.nursery_provision,
foi.ofsted_grade,
foi.ofsted_date,
foi.ofsted_framework,
@@ -178,6 +180,8 @@ _MAIN_QUERY = text("""
l.address_line1 AS address1,
l.address_line2 AS address2,
l.town,
l.county,
l.parliamentary_constituency,
l.postcode,
l.latitude,
l.longitude,
@@ -301,6 +305,32 @@ for _old, _new in _LEGACY_NAME_REPLACEMENTS:
_MAIN_QUERY_LEGACY_NAMES = _MAIN_QUERY_LEGACY_NAMES.replace(_old, _new)
_MAIN_QUERY_LEGACY_NAMES = text(_MAIN_QUERY_LEGACY_NAMES)
# Fallback used when marts predate the optional GIAS/location detail columns
# (telephone, nursery provision, county, parliamentary constituency) — i.e. the
# nightly dbt pipeline hasn't rebuilt the mart yet on this DB. Keeps each column
# present as NULL so the whole data load degrades gracefully instead of failing.
_EXTRA_OPTIONAL_COLUMNS = (
"telephone",
"nursery_provision",
"county",
"parliamentary_constituency",
)
_MAIN_QUERY_NO_EXTRA_COLS = str(_MAIN_QUERY)
for _col, _tbl in (
("telephone", "s"),
("nursery_provision", "s"),
("county", "l"),
("parliamentary_constituency", "l"),
):
_src = f"{_tbl}.{_col},"
assert _src in _MAIN_QUERY_NO_EXTRA_COLS, (
f"expected {_src!r} to be present in _MAIN_QUERY before replacement"
)
_MAIN_QUERY_NO_EXTRA_COLS = _MAIN_QUERY_NO_EXTRA_COLS.replace(
_src, f"NULL AS {_col},"
)
_MAIN_QUERY_NO_EXTRA_COLS = text(_MAIN_QUERY_NO_EXTRA_COLS)
_GIAS_CODE_COLUMN_NAMES = (
"phase_code",
"school_type_code",
@@ -352,6 +382,18 @@ def load_school_data_as_dataframe() -> pd.DataFrame:
except Exception as exc2:
print(f"Warning: Could not load school data from marts: {exc2}")
return pd.DataFrame()
elif missing in _EXTRA_OPTIONAL_COLUMNS:
logging.getLogger(__name__).warning(
"marts.dim_school/dim_location is missing %s (pipeline hasn't "
"rebuilt the mart yet on this DB) — retrying without the "
"optional detail columns: %s",
missing, exc,
)
try:
df = pd.read_sql(_MAIN_QUERY_NO_EXTRA_COLS, engine)
except Exception as exc2:
print(f"Warning: Could not load school data from marts: {exc2}")
return pd.DataFrame()
else:
print(f"Warning: Could not load school data from marts: {exc}")
return pd.DataFrame()