From ca5f6a962c71dc82a66b3126838821742366d440 Mon Sep 17 00:00:00 2001 From: Tudor Sitaru Date: Tue, 7 Apr 2026 21:15:54 +0100 Subject: [PATCH] fix(dim_school): expand phase inference with name-based fallback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The case-insensitive "Not Applicable" fix caught schools where GIAS publishes statutory ages, but some independent schools leave those blank too — they fall through every branch and end up with null phase and no pill in the UI. Add a third tier that infers phase from the school name (Primary/Infant/Junior/Prep vs Secondary/High/Grammar/Senior/Upper) and also normalise "Not Applicable" handling with trim() + "unknown"/"" exclusion, so the final else branch can safely return null instead of the catch-all string. Co-Authored-By: Claude Opus 4.6 --- .../transform/models/marts/dim_school.sql | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/pipeline/transform/models/marts/dim_school.sql b/pipeline/transform/models/marts/dim_school.sql index c2fc641..20443dc 100644 --- a/pipeline/transform/models/marts/dim_school.sql +++ b/pipeline/transform/models/marts/dim_school.sql @@ -15,12 +15,31 @@ select s.local_authority_code * 1000 + s.establishment_number as laestab, s.school_name, case - when s.phase is not null and lower(s.phase) != 'not applicable' then s.phase + -- 1. Trust GIAS phase when it's a real value (not the catch-all "Not Applicable") + when s.phase is not null + and lower(trim(s.phase)) not in ('not applicable', '', 'unknown') + then s.phase + -- 2. Infer from statutory age range (independent schools still publish these) when s.statutory_high_age is not null and s.statutory_high_age <= 11 then 'Primary' when s.statutory_low_age is not null and s.statutory_low_age >= 11 then 'Secondary' when s.statutory_low_age is not null and s.statutory_high_age is not null and s.statutory_low_age < 11 and s.statutory_high_age > 11 then 'All-through' - else s.phase + -- 3. Fallback: infer from school name (covers independents with missing ages) + when s.school_name ilike '%primary%' + or s.school_name ilike '%infant%' + or s.school_name ilike '%junior%' + or s.school_name ilike '%preparatory%' + or s.school_name ilike '% prep school%' + or s.school_name ilike '% prep %' + then 'Primary' + when s.school_name ilike '%secondary%' + or s.school_name ilike '%high school%' + or s.school_name ilike '%grammar%' + or s.school_name ilike '%senior school%' + or s.school_name ilike '%upper school%' + then 'Secondary' + -- 4. Give up — leave phase null so the UI renders no pill + else null end as phase, s.school_type, s.academy_trust_name,