feat(api): name each school's type group, and send search its nursery provision
The school page and the search rows now print a school's type in the search
filter's terms ("State school", "Independent school") instead of GIAS's 34
establishment types. The list, place and detail payloads carry type_group,
computed with the filter's own type_group_for, so the two never disagree; a
type in no group stays null and the page prints the register's name.
Search rows flag a nursery class, so nursery_provision joins SCHOOL_COLUMNS.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
e344298440
commit
62a6bfaf0c
3 files changed
+102
-7
No files matched your search
+20
-7
@@ -634,6 +634,18 @@ def _with_whole_school_pupils(rows: pd.DataFrame, source: pd.DataFrame) -> pd.Da
|
||||
return rows.assign(total_pupils=whole)
|
||||
|
||||
|
||||
def _with_type_group(rows: pd.DataFrame) -> pd.DataFrame:
|
||||
"""Name each row's search-filter type group, or None for a type in no group.
|
||||
|
||||
The school page and the search rows print it ("State school") in place of
|
||||
the GIAS establishment type, and an independent school gets a Fee-paying
|
||||
flag from it.
|
||||
"""
|
||||
if "school_type" not in rows.columns:
|
||||
return rows
|
||||
return rows.assign(type_group=rows["school_type"].map(type_group_for))
|
||||
|
||||
|
||||
# Input validation helpers
|
||||
def _names_in_group(names: pd.Series, in_group) -> set:
|
||||
"""The distinct names in a column that a group predicate accepts.
|
||||
@@ -965,7 +977,7 @@ async def get_schools(
|
||||
total = len(schools_df)
|
||||
start_idx = (page - 1) * page_size
|
||||
end_idx = start_idx + page_size
|
||||
schools_df = schools_df.iloc[start_idx:end_idx]
|
||||
schools_df = _with_type_group(schools_df.iloc[start_idx:end_idx])
|
||||
|
||||
return {
|
||||
"schools": clean_for_json(schools_df),
|
||||
@@ -1029,6 +1041,7 @@ async def get_school_details(request: Request, urn: int):
|
||||
"school_name": latest.get("school_name", ""),
|
||||
"local_authority": latest.get("local_authority", ""),
|
||||
"school_type": latest.get("school_type", ""),
|
||||
"type_group": type_group_for(latest.get("school_type")),
|
||||
"address": latest.get("address", ""),
|
||||
"religious_denomination": latest.get("religious_denomination", ""),
|
||||
"age_range": latest.get("age_range", ""),
|
||||
@@ -1522,13 +1535,12 @@ async def get_place(request: Request, kind: str, slug: str,
|
||||
# warning. Ordered de-duplication keeps the column order and the warning
|
||||
# cannot come back.
|
||||
#
|
||||
# nursery_provision and parliamentary_constituency are not in
|
||||
# SCHOOL_COLUMNS and the place table shows both. The `in rows.columns`
|
||||
# guard is what keeps a mart the pipeline has not rebuilt working: those
|
||||
# two are the optional GIAS columns data_loader degrades to NULL.
|
||||
# parliamentary_constituency is not in SCHOOL_COLUMNS and the place table
|
||||
# shows it. The `in rows.columns` guard is what keeps a mart the pipeline
|
||||
# has not rebuilt working: it and nursery_provision are the optional GIAS
|
||||
# columns data_loader degrades to NULL.
|
||||
cols = [c for c in dict.fromkeys(
|
||||
SCHOOL_COLUMNS + ["latitude", "longitude", "phase",
|
||||
"nursery_provision",
|
||||
"parliamentary_constituency",
|
||||
"rwm_expected_pct", "attainment_8_score",
|
||||
"total_pupils"])
|
||||
@@ -1558,7 +1570,8 @@ async def get_place(request: Request, kind: str, slug: str,
|
||||
# variants that exist rather than 404s.
|
||||
"phases": [ph for ph in ("primary", "secondary")
|
||||
if place.publishes_phase(ph)]},
|
||||
"schools": clean_for_json(_with_whole_school_pupils(rows[cols], rows)),
|
||||
"schools": clean_for_json(
|
||||
_with_type_group(_with_whole_school_pupils(rows[cols], rows))),
|
||||
"averages": averages,
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user