From dfa4928641aef2462e320e99100e03b429bb0e3d Mon Sep 17 00:00:00 2001 From: Tudor Date: Mon, 5 Oct 2026 16:24:41 +0100 Subject: [PATCH] feat(pipeline): add fact_ofsted_latest, one current Ofsted status per school The backend will read this instead of picking the latest row of fact_ofsted_inspection itself (twice, with arbitrary ties). Schema tests and assert_ofsted_current_grade_consistent pin its invariants. Built by the monthly Ofsted DAG (int_ofsted_latest+), not the daily one. Co-Authored-By: Claude Opus 5.5 --- .../transform/models/marts/_marts_schema.yml | 24 ++++++++++++ .../models/marts/fact_ofsted_latest.sql | 37 +++++++++++++++++++ ...assert_ofsted_current_grade_consistent.sql | 10 +++++ 3 files changed, 71 insertions(+) create mode 100644 pipeline/transform/models/marts/fact_ofsted_latest.sql create mode 100644 pipeline/transform/tests/assert_ofsted_current_grade_consistent.sql diff --git a/pipeline/transform/models/marts/_marts_schema.yml b/pipeline/transform/models/marts/_marts_schema.yml index 89f2301..b198b6b 100644 --- a/pipeline/transform/models/marts/_marts_schema.yml +++ b/pipeline/transform/models/marts/_marts_schema.yml @@ -125,6 +125,30 @@ models: - name: inspection_date tests: [not_null] + - name: fact_ofsted_latest + description: > + Current Ofsted status, one row per URN: the latest visit and the overall + grade still in force. See int_ofsted_latest for the rule. + columns: + - name: urn + tests: [not_null, unique] + - name: latest_visit_date + tests: [not_null] + - name: latest_visit_kind + tests: + - not_null + - accepted_values: + values: ['report_card', 'graded', 'ungraded'] + - name: current_grade + tests: + - accepted_values: + values: [1, 2, 3, 4] + quote: false + - name: current_grade_basis + tests: + - accepted_values: + values: ['graded', 'confirmed'] + - name: fact_pupil_characteristics description: Pupil demographics — one row per URN per year columns: diff --git a/pipeline/transform/models/marts/fact_ofsted_latest.sql b/pipeline/transform/models/marts/fact_ofsted_latest.sql new file mode 100644 index 0000000..12c5cb0 --- /dev/null +++ b/pipeline/transform/models/marts/fact_ofsted_latest.sql @@ -0,0 +1,37 @@ +-- Mart: current Ofsted status — one row per URN +-- The backend reads this instead of choosing the latest row of +-- fact_ofsted_inspection itself. The rule lives in int_ofsted_latest. + +select + urn, + latest_visit_date, + latest_visit_kind, + latest_visit_outcome, + current_grade, + current_grade_date, + current_grade_basis, + graded_inspection_date, + ungraded_inspection_date, + rc_inspection_date, + inspection_type, + framework, + overall_effectiveness, + quality_of_education, + behaviour_attitudes, + personal_development, + leadership_management, + early_years_provision, + sixth_form_provision, + ungraded_outcome, + ungraded_grade, + rc_safeguarding_met, + rc_inclusion, + rc_curriculum_teaching, + rc_achievement, + rc_attendance_behaviour, + rc_personal_development, + rc_leadership_governance, + rc_early_years, + rc_sixth_form, + report_url +from {{ ref('int_ofsted_latest') }} diff --git a/pipeline/transform/tests/assert_ofsted_current_grade_consistent.sql b/pipeline/transform/tests/assert_ofsted_current_grade_consistent.sql new file mode 100644 index 0000000..a1e36ea --- /dev/null +++ b/pipeline/transform/tests/assert_ofsted_current_grade_consistent.sql @@ -0,0 +1,10 @@ +-- A grade is dated by the inspection that awarded or confirmed it, never +-- after the latest visit, and has a date and a basis exactly when it exists. +-- A report card leaves no legacy grade in force. + +select urn +from {{ ref('fact_ofsted_latest') }} +where current_grade_date > latest_visit_date + or (current_grade is null) <> (current_grade_date is null) + or (current_grade is null) <> (current_grade_basis is null) + or (latest_visit_kind = 'report_card' and current_grade is not null)