feat(api): group GIAS school types and religions for parents

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
TudorandClaude Opus 5.5 committed 2026-10-02 11:52:43 +01:00
1 parent 3e2fa4a419
commit 354244f755
3 files changed
+214 -15

No files matched your search

@@ -103,8 +103,8 @@ Christian schools that are not tied to one church.
Grouping lives in the backend, not dbt. The API already translates GIAS codes
to names when it loads the marts (`backend/data_loader.py:
translate_gias_code_columns`), and every filter is applied to that DataFrame.
Grouping at the same point needs no mart change, so there is no Airflow run
between merge and staging showing it.
Grouping there needs no mart change, so there is no Airflow run between merge
and staging showing it.
### `backend/school_groups.py` (new)
@@ -112,25 +112,22 @@ between merge and staging showing it.
- `UNOFFERED_TYPE_CODES`: the not-offered codes, so that "every code is
accounted for" is testable.
- `FAITH_GROUPS`: ordered `(key, label, frozenset[int])` per faith group.
- `type_group_for(code) -> str | None` and
`faith_groups_for(code) -> tuple[str, ...]` (a missing code gives
- `type_group_for(name) -> str | None` and
`faith_groups_for(name) -> tuple[str, ...]` (a missing or blank name gives
`("none",)`).
No dependence on the generated GIAS dictionaries beyond their codes, so the
backend/pipeline dictionary parity test is untouched.
### `backend/data_loader.py`
### Grouping by name, at filter time
In `translate_gias_code_columns`, before the code columns are replaced by
names, add two columns from the codes:
- `school_type_group`: `type_group_for(school_type_code)`, or None.
- `faith_groups`: `faith_groups_for(religious_character_code)`, a tuple.
The fallback query that reads name columns from older marts
(`_MAIN_QUERY_NO_EXTRA_COLS` and its replacements) has no codes. There, both
columns are derived from the names by reverse lookup through `SCHOOL_TYPE` and
`RELIGIOUS_CHARACTER`.
The groups are defined over codes but looked up by the translated name
(`type_group_for(name)`, `faith_groups_for(name)`), when `/api/schools` and
`/api/filters` filter. The DataFrame those endpoints read carries names only:
`translate_gias_code_columns` replaces the codes at load, the legacy-name
mart fallback never had codes, and the API test fixtures are written in
names. The names come from the same dictionaries, so the lookup is exact.
`data_loader.py` is unchanged.
### `/api/schools`