feat(ofsted): fall back to ungraded inspection outcome for school grade
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 18s
Build and Push Docker Images / Build Frontend (Next.js) (push) Successful in 48s
Build and Push Docker Images / Build Pipeline (Meltano + dbt + Airflow) (push) Successful in 1m30s
Build and Push Docker Images / Trigger Portainer Update (push) Successful in 1s
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 18s
Build and Push Docker Images / Build Frontend (Next.js) (push) Successful in 48s
Build and Push Docker Images / Build Pipeline (Meltano + dbt + Airflow) (push) Successful in 1m30s
Build and Push Docker Images / Trigger Portainer Update (push) Successful in 1s
Ungraded (Section 8) inspections don't assign a fresh grade — the export only gives free text like "School remains Good". Parse that text into a grade (remains Outstanding -> 1, remains Good -> 2, else null) and use it as a last-resort fallback when no graded overall effectiveness exists. Also retain schools that have only an ungraded inspection (no graded date) by coalescing the inspection date, so ~8.5k previously-dropped schools now carry a grade. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -59,6 +59,15 @@ COLUMN_PRIORITY = {
|
||||
"Latest OEIF sixth form provision",
|
||||
"Sixth form provision (where applicable)",
|
||||
],
|
||||
# Ungraded (Section 8) inspection — no fresh grade is assigned; the outcome
|
||||
# is free text like "School remains Good". Used as a last-resort fallback
|
||||
# for the school's grade when no graded overall effectiveness is available.
|
||||
"ungraded_outcome": [
|
||||
"Ungraded inspection overall outcome",
|
||||
],
|
||||
"ungraded_inspection_date": [
|
||||
"Date of latest ungraded inspection",
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
@@ -100,6 +109,8 @@ class OfstedInspectionsStream(Stream):
|
||||
th.Property("effectiveness_of_leadership_and_management", th.StringType),
|
||||
th.Property("early_years_provision", th.StringType),
|
||||
th.Property("sixth_form_provision", th.StringType),
|
||||
th.Property("ungraded_outcome", th.StringType),
|
||||
th.Property("ungraded_inspection_date", th.StringType),
|
||||
th.Property("report_url", th.StringType),
|
||||
).to_dict()
|
||||
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
-- Macro: Parse an Ofsted ungraded (Section 8) inspection outcome into a grade.
|
||||
--
|
||||
-- Ungraded inspections do not assign a fresh grade; the outcome is free text
|
||||
-- describing whether the school kept its previous judgement, e.g.
|
||||
-- "School remains Good", "School remains Good (Concerns) - S5 Next",
|
||||
-- "School remains Outstanding", "School remains Outstanding (Concerns) - S5 Next".
|
||||
-- These are the only Good/Outstanding signal we can recover, so we match on the
|
||||
-- "remains <grade>" phrase (tolerant of any trailing qualifier).
|
||||
--
|
||||
-- Outcomes that don't establish a Good/Outstanding status — "Standards
|
||||
-- maintained", "Improved significantly", "Some aspects not as strong" — map to
|
||||
-- null. Grades align with parse_ofsted_grade (1 = Outstanding, 2 = Good).
|
||||
|
||||
{% macro parse_ungraded_outcome(column) %}
|
||||
case
|
||||
when {{ column }} ilike '%remains Outstanding%' then 1
|
||||
when {{ column }} ilike '%remains Good%' then 2
|
||||
else null
|
||||
end
|
||||
{% endmacro %}
|
||||
@@ -23,6 +23,8 @@ select
|
||||
leadership_management,
|
||||
early_years_provision,
|
||||
sixth_form_provision,
|
||||
ungraded_outcome,
|
||||
ungraded_grade,
|
||||
rc_safeguarding_met,
|
||||
rc_inclusion,
|
||||
rc_curriculum_teaching,
|
||||
|
||||
@@ -60,7 +60,9 @@ select
|
||||
|
||||
-- Latest Ofsted (populated after monthly Ofsted pipeline runs)
|
||||
{% if ofsted_relation is not none %}
|
||||
o.overall_effectiveness as ofsted_grade,
|
||||
-- Prefer the graded overall effectiveness; fall back to the grade parsed
|
||||
-- from the latest ungraded (Section 8) outcome when no graded grade exists.
|
||||
coalesce(o.overall_effectiveness, o.ungraded_grade) as ofsted_grade,
|
||||
o.inspection_date as ofsted_date,
|
||||
o.framework as ofsted_framework
|
||||
{% else %}
|
||||
|
||||
@@ -12,6 +12,8 @@ select
|
||||
leadership_management,
|
||||
early_years_provision,
|
||||
sixth_form_provision,
|
||||
ungraded_outcome,
|
||||
ungraded_grade,
|
||||
rc_safeguarding_met,
|
||||
rc_inclusion,
|
||||
rc_curriculum_teaching,
|
||||
|
||||
@@ -8,7 +8,13 @@ with source as (
|
||||
renamed as (
|
||||
select
|
||||
cast(urn as integer) as urn,
|
||||
to_date(nullif(trim(inspection_date), 'NULL'), 'DD/MM/YYYY') as inspection_date,
|
||||
-- Inspection event date: the graded inspection when present, otherwise the
|
||||
-- ungraded (Section 8) inspection so schools with only an ungraded
|
||||
-- inspection are still retained.
|
||||
coalesce(
|
||||
to_date(nullif(trim(inspection_date), 'NULL'), 'DD/MM/YYYY'),
|
||||
to_date(nullif(trim(ungraded_inspection_date), 'NULL'), 'DD/MM/YYYY')
|
||||
) as inspection_date,
|
||||
inspection_type,
|
||||
event_type_grouping as framework,
|
||||
|
||||
@@ -21,6 +27,12 @@ renamed as (
|
||||
{{ safe_numeric('early_years_provision') }}::integer as early_years_provision,
|
||||
{{ safe_numeric('sixth_form_provision') }}::integer as sixth_form_provision,
|
||||
|
||||
-- Ungraded (Section 8) inspection outcome — free text, plus a grade
|
||||
-- parsed from it (1/2/null) used as a last-resort fallback for schools
|
||||
-- with no graded overall effectiveness.
|
||||
nullif(trim(ungraded_outcome), 'NULL') as ungraded_outcome,
|
||||
{{ parse_ungraded_outcome('ungraded_outcome') }}::integer as ungraded_grade,
|
||||
|
||||
-- Report Card fields (post-Nov 2025 framework)
|
||||
-- TODO: add rc_* columns to tap-uk-ofsted schema once CSV column names are confirmed
|
||||
null::text as rc_safeguarding_met,
|
||||
@@ -36,7 +48,10 @@ renamed as (
|
||||
report_url
|
||||
from source
|
||||
where urn is not null
|
||||
and nullif(trim(inspection_date), 'NULL') is not null
|
||||
and (
|
||||
nullif(trim(inspection_date), 'NULL') is not null
|
||||
or nullif(trim(ungraded_inspection_date), 'NULL') is not null
|
||||
)
|
||||
)
|
||||
|
||||
select * from renamed
|
||||
|
||||
Reference in New Issue
Block a user