feat(gias): load UKPRN and the inspectorate GIAS names (H4)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
000626c5d6
commit
1949e85c58
5 files changed
+80
-1
No files matched your search
@@ -111,7 +111,7 @@ print(f'Validation passed: {{count}} GIAS rows')
|
|||||||
# where that DAG hasn't run (pipeline/tests/test_dag_selectors.py).
|
# where that DAG hasn't run (pipeline/tests/test_dag_selectors.py).
|
||||||
dbt_build = BashOperator(
|
dbt_build = BashOperator(
|
||||||
task_id="dbt_build",
|
task_id="dbt_build",
|
||||||
bash_command=f"cd {PIPELINE_DIR}/transform && {DBT_BIN} build --profiles-dir . --target production --select stg_gias_establishments+ stg_gias_links+ gias_code_names+ --exclude int_ks2_with_lineage+ int_ks4_with_lineage+ stg_ees_ks4_destinations+ stg_ees_ks5_destinations+",
|
bash_command=f"cd {PIPELINE_DIR}/transform && {DBT_BIN} build --profiles-dir . --target production --select stg_gias_establishments+ stg_gias_links+ gias_code_names+ stg_gias_ukprn --exclude int_ks2_with_lineage+ int_ks4_with_lineage+ stg_ees_ks4_destinations+ stg_ees_ks5_destinations+",
|
||||||
)
|
)
|
||||||
|
|
||||||
sync_typesense = BashOperator(
|
sync_typesense = BashOperator(
|
||||||
|
|||||||
@@ -72,6 +72,12 @@ class GIASEstablishmentsStream(Stream):
|
|||||||
th.Property("Northing", th.StringType),
|
th.Property("Northing", th.StringType),
|
||||||
th.Property("StatutoryLowAge", th.StringType),
|
th.Property("StatutoryLowAge", th.StringType),
|
||||||
th.Property("StatutoryHighAge", th.StringType),
|
th.Property("StatutoryHighAge", th.StringType),
|
||||||
|
# Matches Ofsted's further-education providers, which some FE
|
||||||
|
# records name by UKPRN only (audit H4).
|
||||||
|
th.Property("UKPRN", th.StringType),
|
||||||
|
# "ISI" for independent schools the Independent Schools Inspectorate
|
||||||
|
# inspects; "Ofsted" or "Not applicable" otherwise (audit H4).
|
||||||
|
th.Property("InspectorateName (name)", th.StringType),
|
||||||
).to_dict()
|
).to_dict()
|
||||||
|
|
||||||
def get_records(self, context):
|
def get_records(self, context):
|
||||||
|
|||||||
@@ -0,0 +1,61 @@
|
|||||||
|
"""Every field the GIAS establishments stream declares must be a column of the
|
||||||
|
extract GIAS publishes, or it silently loads as null. H4 adds UKPRN (matches
|
||||||
|
Ofsted's further-education providers) and InspectorateName (name) ("ISI" for
|
||||||
|
about 1,340 independent schools). HEADER is GIAS's own, from
|
||||||
|
edubasealldata20261013.csv.
|
||||||
|
"""
|
||||||
|
import re
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
TAP = (Path(__file__).resolve().parents[1] / 'plugins' / 'extractors' / 'tap-uk-gias'
|
||||||
|
/ 'tap_uk_gias' / 'tap.py')
|
||||||
|
|
||||||
|
HEADER = (
|
||||||
|
'URN', 'LA (code)', 'LA (name)', 'EstablishmentNumber', 'EstablishmentName',
|
||||||
|
'TypeOfEstablishment (code)', 'TypeOfEstablishment (name)', 'EstablishmentTypeGroup (code)',
|
||||||
|
'EstablishmentTypeGroup (name)', 'EstablishmentStatus (code)', 'EstablishmentStatus (name)',
|
||||||
|
'ReasonEstablishmentOpened (code)', 'ReasonEstablishmentOpened (name)', 'OpenDate',
|
||||||
|
'ReasonEstablishmentClosed (code)', 'ReasonEstablishmentClosed (name)', 'CloseDate',
|
||||||
|
'PhaseOfEducation (code)', 'PhaseOfEducation (name)', 'StatutoryLowAge', 'StatutoryHighAge',
|
||||||
|
'Boarders (code)', 'Boarders (name)', 'NurseryProvision (name)', 'OfficialSixthForm (code)',
|
||||||
|
'OfficialSixthForm (name)', 'Gender (code)', 'Gender (name)', 'ReligiousCharacter (code)',
|
||||||
|
'ReligiousCharacter (name)', 'ReligiousEthos (name)', 'Diocese (code)', 'Diocese (name)',
|
||||||
|
'AdmissionsPolicy (code)', 'AdmissionsPolicy (name)', 'SchoolCapacity', 'SpecialClasses (code)',
|
||||||
|
'SpecialClasses (name)', 'CensusDate', 'NumberOfPupils', 'NumberOfBoys', 'NumberOfGirls',
|
||||||
|
'PercentageFSM', 'TrustSchoolFlag (code)', 'TrustSchoolFlag (name)', 'Trusts (code)',
|
||||||
|
'Trusts (name)', 'SchoolSponsorFlag (name)', 'SchoolSponsors (name)', 'FederationFlag (name)',
|
||||||
|
'Federations (code)', 'Federations (name)', 'UKPRN', 'FEHEIdentifier',
|
||||||
|
'FurtherEducationType (name)', 'LastChangedDate', 'Street', 'Locality', 'Address3', 'Town',
|
||||||
|
'County (name)', 'Postcode', 'SchoolWebsite', 'TelephoneNum', 'HeadTitle (name)',
|
||||||
|
'HeadFirstName', 'HeadLastName', 'HeadPreferredJobTitle', 'BSOInspectorateName (name)',
|
||||||
|
'InspectorateReport', 'DateOfLastInspectionVisit', 'NextInspectionVisit', 'TeenMoth (name)',
|
||||||
|
'TeenMothPlaces', 'CCF (name)', 'SENPRU (name)', 'EBD (name)', 'PlacesPRU', 'FTProv (name)',
|
||||||
|
'EdByOther (name)', 'Section41Approved (name)', 'SEN1 (name)', 'SEN2 (name)', 'SEN3 (name)',
|
||||||
|
'SEN4 (name)', 'SEN5 (name)', 'SEN6 (name)', 'SEN7 (name)', 'SEN8 (name)', 'SEN9 (name)',
|
||||||
|
'SEN10 (name)', 'SEN11 (name)', 'SEN12 (name)', 'SEN13 (name)',
|
||||||
|
'TypeOfResourcedProvision (name)', 'ResourcedProvisionOnRoll', 'ResourcedProvisionCapacity',
|
||||||
|
'SenUnitOnRoll', 'SenUnitCapacity', 'GOR (code)', 'GOR (name)',
|
||||||
|
'DistrictAdministrative (code)', 'DistrictAdministrative (name)', 'AdministrativeWard (code)',
|
||||||
|
'AdministrativeWard (name)', 'ParliamentaryConstituency (code)',
|
||||||
|
'ParliamentaryConstituency (name)', 'UrbanRural (code)', 'UrbanRural (name)',
|
||||||
|
'GSSLACode (name)', 'Easting', 'Northing', 'MSOA (name)', 'LSOA (name)',
|
||||||
|
'InspectorateName (name)', 'SENStat', 'SENNoStat', 'BoardingEstablishment (name)', 'PropsName',
|
||||||
|
'PreviousLA (code)', 'PreviousLA (name)', 'PreviousEstablishmentNumber', 'Country (name)',
|
||||||
|
'UPRN', 'SiteName', 'QABName (code)', 'QABName (name)', 'EstablishmentAccredited (code)',
|
||||||
|
'EstablishmentAccredited (name)', 'QABReport', 'CHNumber', 'MSOA (code)', 'LSOA (code)', 'FSM',
|
||||||
|
'AccreditationExpiryDate',
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def declared():
|
||||||
|
source = TAP.read_text()
|
||||||
|
block = source[source.index('class GIASEstablishmentsStream'):source.index('class GIASLinksStream')]
|
||||||
|
return re.findall(r'th\.Property\("([^"]+)"', block)
|
||||||
|
|
||||||
|
|
||||||
|
def test_every_declared_field_is_a_gias_column():
|
||||||
|
assert set(declared()) - set(HEADER) == set()
|
||||||
|
|
||||||
|
|
||||||
|
def test_the_inspection_fields_are_declared():
|
||||||
|
assert {'UKPRN', 'InspectorateName (name)'} <= set(declared())
|
||||||
@@ -38,6 +38,7 @@ renamed as (
|
|||||||
"UrbanRural (name)" as urban_rural,
|
"UrbanRural (name)" as urban_rural,
|
||||||
"ParliamentaryConstituency (name)" as parliamentary_constituency,
|
"ParliamentaryConstituency (name)" as parliamentary_constituency,
|
||||||
"NurseryProvision (name)" as nursery_provision,
|
"NurseryProvision (name)" as nursery_provision,
|
||||||
|
nullif(trim("InspectorateName (name)"), '') as inspectorate_name,
|
||||||
cast(nullif("Easting", '') as integer) as easting,
|
cast(nullif("Easting", '') as integer) as easting,
|
||||||
cast(nullif("Northing", '') as integer) as northing,
|
cast(nullif("Northing", '') as integer) as northing,
|
||||||
cast(nullif("StatutoryLowAge", '') as integer) as statutory_low_age,
|
cast(nullif("StatutoryLowAge", '') as integer) as statutory_low_age,
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
-- URN → UKPRN from the raw GIAS extract, for matching Ofsted's further
|
||||||
|
-- education providers (int_ofsted_fe_latest, int_ofsted_listed; audit H4).
|
||||||
|
-- A model on the raw source rather than a column of stg_gias_establishments:
|
||||||
|
-- a ref to that model would put the Ofsted models into the daily build's
|
||||||
|
-- stg_gias_establishments+ selection (pipeline/tests/test_dag_selectors.py).
|
||||||
|
|
||||||
|
select
|
||||||
|
cast("URN" as integer) as urn,
|
||||||
|
nullif(trim("UKPRN"), '') as ukprn
|
||||||
|
from {{ source('raw', 'gias_establishments') }}
|
||||||
|
where "URN" ~ '^[0-9]+$'
|
||||||
Reference in new issue
Block a user