From 6f602f4a9ec352d621b2fc369e89fa9257ed503e Mon Sep 17 00:00:00 2001 From: Tudor Date: Wed, 8 Jul 2026 22:05:55 +0100 Subject: [PATCH] feat(api): expose GIAS establishment status on school payloads Co-Authored-By: Claude Fable 5 --- backend/app.py | 1 + backend/data_loader.py | 1 + backend/schemas.py | 1 + backend/tests/test_school_status.py | 70 +++++++++++++++++++++++++++++ 4 files changed, 73 insertions(+) create mode 100644 backend/tests/test_school_status.py diff --git a/backend/app.py b/backend/app.py index 7f017df..1e7c758 100644 --- a/backend/app.py +++ b/backend/app.py @@ -604,6 +604,7 @@ 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"), + "status": latest.get("status"), "latitude": latest.get("latitude"), "longitude": latest.get("longitude"), "phase": latest.get("phase"), diff --git a/backend/data_loader.py b/backend/data_loader.py index 9e50c73..c753d1a 100644 --- a/backend/data_loader.py +++ b/backend/data_loader.py @@ -129,6 +129,7 @@ _MAIN_QUERY = text(""" s.gender, s.age_range, s.has_sixth_form, + s.status, s.admissions_policy, s.capacity, s.total_pupils AS gias_total_pupils, diff --git a/backend/schemas.py b/backend/schemas.py index a757469..8144116 100644 --- a/backend/schemas.py +++ b/backend/schemas.py @@ -544,6 +544,7 @@ SCHOOL_COLUMNS = [ "religious_denomination", "age_range", "has_sixth_form", + "status", "gender", "admissions_policy", "ofsted_grade", diff --git a/backend/tests/test_school_status.py b/backend/tests/test_school_status.py new file mode 100644 index 0000000..ff9787e --- /dev/null +++ b/backend/tests/test_school_status.py @@ -0,0 +1,70 @@ +"""Tests for GIAS establishment status exposure. + +"Open, but proposed to close" schools are now kept by the dims; the API must +surface `status` on list items and school_info so the UI can render the +proposed-to-close marker (listing tag) and notice strip (detail page). +""" + +import numpy as np +import pandas as pd +import pytest +from fastapi.testclient import TestClient + +PROPOSED = "Open, but proposed to close" + + +def _schools_df() -> pd.DataFrame: + base = { + "local_authority": "Testshire", + "school_type": "Academy", + "phase": "Secondary", + "address": "1 Test Street", + "town": "Testtown", + "postcode": "TS1 1AA", + "religious_denomination": None, + "gender": "Mixed", + "age_range": "11-16", + "admissions_policy": None, + "has_sixth_form": False, + "ofsted_grade": np.nan, + "ofsted_date": None, + "ofsted_framework": None, + "latitude": 51.5, + "longitude": -0.1, + "year": 202425, + "total_pupils": 800, + "rwm_expected_pct": np.nan, + "attainment_8_score": 48.0, + } + return pd.DataFrame( + [ + {**base, "urn": 200001, "school_name": "Alpha Academy", + "status": "Open"}, + {**base, "urn": 200002, "school_name": "Sarson High School", + "status": PROPOSED}, + ] + ) + + +@pytest.fixture() +def client(monkeypatch): + from backend import app as app_module + + monkeypatch.setattr(app_module, "load_latest_school_data", _schools_df) + monkeypatch.setattr(app_module, "load_school_data", _schools_df) + monkeypatch.setattr(app_module, "get_supplementary_data", lambda db, urn: {}) + return TestClient(app_module.app, raise_server_exceptions=False) + + +def test_list_payload_includes_status(client): + resp = client.get("/api/schools") + assert resp.status_code == 200, resp.text + by_urn = {s["urn"]: s for s in resp.json()["schools"]} + assert by_urn[200001]["status"] == "Open" + assert by_urn[200002]["status"] == PROPOSED + + +def test_detail_payload_includes_status(client): + resp = client.get("/api/schools/200002") + assert resp.status_code == 200, resp.text + assert resp.json()["school_info"]["status"] == PROPOSED