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
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:
@@ -606,17 +606,21 @@ async def get_school_details(request: Request, urn: int):
|
||||
"religious_denomination": latest.get("religious_denomination", ""),
|
||||
"age_range": latest.get("age_range", ""),
|
||||
"has_sixth_form": latest.get("has_sixth_form"),
|
||||
"nursery_provision": latest.get("nursery_provision"),
|
||||
"status": latest.get("status"),
|
||||
"latitude": latest.get("latitude"),
|
||||
"longitude": latest.get("longitude"),
|
||||
"phase": latest.get("phase"),
|
||||
# GIAS fields
|
||||
"website": latest.get("website"),
|
||||
"telephone": latest.get("telephone"),
|
||||
"headteacher_name": latest.get("headteacher_name"),
|
||||
"capacity": latest.get("capacity"),
|
||||
"total_pupils": latest.get("gias_total_pupils"),
|
||||
"trust_name": latest.get("trust_name"),
|
||||
"gender": latest.get("gender"),
|
||||
"county": latest.get("county"),
|
||||
"parliamentary_constituency": latest.get("parliamentary_constituency"),
|
||||
}.items()
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user