From b5b47ca1350405b5414d512b3303204f0b152142 Mon Sep 17 00:00:00 2001 From: Tudor Date: Mon, 13 Jul 2026 18:42:08 +0100 Subject: [PATCH] feat(api): Ofsted report-card labels and provider-page URL Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_0146VHeLAWjDVE2B5uU67jCB --- backend/ofsted_codes.py | 44 +++++++++++++++++++++++++++++ backend/tests/test_ofsted_codes.py | 45 ++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 backend/ofsted_codes.py create mode 100644 backend/tests/test_ofsted_codes.py diff --git a/backend/ofsted_codes.py b/backend/ofsted_codes.py new file mode 100644 index 0000000..81fa229 --- /dev/null +++ b/backend/ofsted_codes.py @@ -0,0 +1,44 @@ +"""Ofsted renewed-framework (Nov 2025) report-card code translation. + +Scale labels are the live-sampled vocabulary from the Ofsted MI file +(see pipeline/scripts/diagnose_compare_gaps.py, TASK 7 VALUE SAMPLE) — +verified against real data, not the consultation draft. +""" + +REPORT_CARD_GRADE_NAMES = { + 1: "Exceptional", + 2: "Strong standard", + 3: "Expected standard", + 4: "Needs attention", + 5: "Urgent improvement", +} + +# Graded evaluation areas only — safeguarding is a separate boolean +# judgement and must never appear in grade counts or label maps. +_RC_AREA_KEYS = ( + "rc_inclusion", + "rc_curriculum_teaching", + "rc_achievement", + "rc_attendance_behaviour", + "rc_personal_development", + "rc_leadership_governance", + "rc_early_years", + "rc_sixth_form", +) + + +def report_card_labels(ofsted: dict) -> dict: + """{area_key: {code, label}} for populated, known-valued rc_* areas.""" + out = {} + for key in _RC_AREA_KEYS: + code = ofsted.get(key) + label = REPORT_CARD_GRADE_NAMES.get(code) + if code is not None and label is not None: + out[key] = {"code": code, "label": label} + return out + + +def ofsted_page_url(urn: int) -> str: + """The school's page on ofsted.gov.uk (all its reports live there — + we never deep-link an individual report).""" + return f"https://reports.ofsted.gov.uk/provider/21/{urn}" diff --git a/backend/tests/test_ofsted_codes.py b/backend/tests/test_ofsted_codes.py new file mode 100644 index 0000000..aa8aba4 --- /dev/null +++ b/backend/tests/test_ofsted_codes.py @@ -0,0 +1,45 @@ +"""Report-card code translation uses the live-sampled Ofsted vocabulary +(pipeline/scripts/diagnose_compare_gaps.py, TASK 7 VALUE SAMPLE): +Exceptional / Strong standard / Expected standard / Needs attention / +Urgent improvement — never the consultation draft's 'Attention needed'.""" + +from backend.ofsted_codes import ( + REPORT_CARD_GRADE_NAMES, + ofsted_page_url, + report_card_labels, +) + + +def test_scale_is_sampled_vocabulary(): + assert REPORT_CARD_GRADE_NAMES == { + 1: "Exceptional", + 2: "Strong standard", + 3: "Expected standard", + 4: "Needs attention", + 5: "Urgent improvement", + } + + +def test_labels_only_for_populated_areas_and_never_safeguarding(): + ofsted = { + "rc_achievement": 2, + "rc_inclusion": 3, + "rc_attendance_behaviour": 4, + "rc_early_years": None, + "rc_safeguarding_met": True, + "overall_effectiveness": None, + } + labels = report_card_labels(ofsted) + assert labels == { + "rc_achievement": {"code": 2, "label": "Strong standard"}, + "rc_inclusion": {"code": 3, "label": "Expected standard"}, + "rc_attendance_behaviour": {"code": 4, "label": "Needs attention"}, + } + + +def test_unknown_code_is_skipped_not_crashed(): + assert report_card_labels({"rc_achievement": 9}) == {} + + +def test_provider_url(): + assert ofsted_page_url(138690) == "https://reports.ofsted.gov.uk/provider/21/138690"