refactor: update app code for domain-scoped schema migration
Some checks failed
CI / lint-and-test (pull_request) Has been cancelled

- Update dbt model references to use new schema naming (stg_toronto, int_toronto, mart_toronto)
- Refactor figure factories to use consistent column naming from new schema
- Update callbacks to work with refactored data structures
- Add centralized design tokens module for consistent styling
- Streamline CLAUDE.md documentation

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-02-02 17:00:30 -05:00
parent cda2a078d9
commit dfa5f92d8a
21 changed files with 618 additions and 407 deletions

View File

@@ -5,11 +5,11 @@ models:
description: "Rental data enriched with time and zone dimensions"
columns:
- name: rental_id
tests:
data_tests:
- unique
- not_null
- name: zone_code
tests:
data_tests:
- not_null
- name: int_neighbourhood__demographics
@@ -17,11 +17,11 @@ models:
columns:
- name: neighbourhood_id
description: "Neighbourhood identifier"
tests:
data_tests:
- not_null
- name: census_year
description: "Census year"
tests:
data_tests:
- not_null
- name: income_quintile
description: "Income quintile (1-5, city-wide)"
@@ -31,7 +31,7 @@ models:
columns:
- name: neighbourhood_id
description: "Neighbourhood identifier"
tests:
data_tests:
- not_null
- name: year
description: "Reference year"
@@ -45,11 +45,11 @@ models:
columns:
- name: neighbourhood_id
description: "Neighbourhood identifier"
tests:
data_tests:
- not_null
- name: year
description: "Statistics year"
tests:
data_tests:
- not_null
- name: crime_rate_per_100k
description: "Total crime rate per 100K population"
@@ -61,7 +61,7 @@ models:
columns:
- name: neighbourhood_id
description: "Neighbourhood identifier"
tests:
data_tests:
- not_null
- name: year
description: "Reference year"
@@ -75,11 +75,11 @@ models:
columns:
- name: neighbourhood_id
description: "Neighbourhood identifier"
tests:
data_tests:
- not_null
- name: year
description: "Survey year"
tests:
data_tests:
- not_null
- name: avg_rent_2bed
description: "Weighted average 2-bedroom rent"

View File

@@ -16,12 +16,12 @@ crime_by_year as (
neighbourhood_id,
crime_year as year,
sum(incident_count) as total_incidents,
sum(case when crime_type = 'Assault' then incident_count else 0 end) as assault_count,
sum(case when crime_type = 'Auto Theft' then incident_count else 0 end) as auto_theft_count,
sum(case when crime_type = 'Break and Enter' then incident_count else 0 end) as break_enter_count,
sum(case when crime_type = 'Robbery' then incident_count else 0 end) as robbery_count,
sum(case when crime_type = 'Theft Over' then incident_count else 0 end) as theft_over_count,
sum(case when crime_type = 'Homicide' then incident_count else 0 end) as homicide_count,
sum(case when crime_type = 'assault' then incident_count else 0 end) as assault_count,
sum(case when crime_type = 'auto_theft' then incident_count else 0 end) as auto_theft_count,
sum(case when crime_type = 'break_and_enter' then incident_count else 0 end) as break_enter_count,
sum(case when crime_type = 'robbery' then incident_count else 0 end) as robbery_count,
sum(case when crime_type = 'theft_over' then incident_count else 0 end) as theft_over_count,
sum(case when crime_type = 'homicide' then incident_count else 0 end) as homicide_count,
avg(rate_per_100k) as avg_rate_per_100k
from crime
group by neighbourhood_id, crime_year

View File

@@ -42,10 +42,10 @@ pivoted as (
select
neighbourhood_id,
year,
max(case when bedroom_type = 'Two Bedroom' then weighted_avg_rent / nullif(total_weight, 0) end) as avg_rent_2bed,
max(case when bedroom_type = 'One Bedroom' then weighted_avg_rent / nullif(total_weight, 0) end) as avg_rent_1bed,
max(case when bedroom_type = 'Bachelor' then weighted_avg_rent / nullif(total_weight, 0) end) as avg_rent_bachelor,
max(case when bedroom_type = 'Three Bedroom +' then weighted_avg_rent / nullif(total_weight, 0) end) as avg_rent_3bed,
max(case when bedroom_type = '2bed' then weighted_avg_rent / nullif(total_weight, 0) end) as avg_rent_2bed,
max(case when bedroom_type = '1bed' then weighted_avg_rent / nullif(total_weight, 0) end) as avg_rent_1bed,
max(case when bedroom_type = 'bachelor' then weighted_avg_rent / nullif(total_weight, 0) end) as avg_rent_bachelor,
max(case when bedroom_type = '3bed' then weighted_avg_rent / nullif(total_weight, 0) end) as avg_rent_3bed,
avg(vacancy_rate) as vacancy_rate,
sum(rental_units_estimate) as total_rental_units
from allocated

View File

@@ -6,7 +6,7 @@ models:
columns:
- name: rental_id
description: "Unique rental record identifier"
tests:
data_tests:
- unique
- not_null
@@ -17,11 +17,11 @@ models:
columns:
- name: neighbourhood_id
description: "Neighbourhood identifier"
tests:
data_tests:
- not_null
- name: neighbourhood_name
description: "Official neighbourhood name"
tests:
data_tests:
- not_null
- name: geometry
description: "PostGIS geometry for mapping"
@@ -41,11 +41,11 @@ models:
columns:
- name: neighbourhood_id
description: "Neighbourhood identifier"
tests:
data_tests:
- not_null
- name: neighbourhood_name
description: "Official neighbourhood name"
tests:
data_tests:
- not_null
- name: geometry
description: "PostGIS geometry for mapping"
@@ -63,11 +63,11 @@ models:
columns:
- name: neighbourhood_id
description: "Neighbourhood identifier"
tests:
data_tests:
- not_null
- name: neighbourhood_name
description: "Official neighbourhood name"
tests:
data_tests:
- not_null
- name: geometry
description: "PostGIS geometry for mapping"
@@ -77,7 +77,7 @@ models:
description: "100 = city average crime rate"
- name: safety_tier
description: "Safety tier (1=safest, 5=highest crime)"
tests:
data_tests:
- accepted_values:
arguments:
values: [1, 2, 3, 4, 5]
@@ -89,11 +89,11 @@ models:
columns:
- name: neighbourhood_id
description: "Neighbourhood identifier"
tests:
data_tests:
- not_null
- name: neighbourhood_name
description: "Official neighbourhood name"
tests:
data_tests:
- not_null
- name: geometry
description: "PostGIS geometry for mapping"
@@ -103,7 +103,7 @@ models:
description: "100 = city average income"
- name: income_quintile
description: "Income quintile (1-5)"
tests:
data_tests:
- accepted_values:
arguments:
values: [1, 2, 3, 4, 5]
@@ -115,11 +115,11 @@ models:
columns:
- name: neighbourhood_id
description: "Neighbourhood identifier"
tests:
data_tests:
- not_null
- name: neighbourhood_name
description: "Official neighbourhood name"
tests:
data_tests:
- not_null
- name: geometry
description: "PostGIS geometry for mapping"
@@ -129,7 +129,7 @@ models:
description: "100 = city average amenities"
- name: amenity_tier
description: "Amenity tier (1=best, 5=lowest)"
tests:
data_tests:
- accepted_values:
arguments:
values: [1, 2, 3, 4, 5]

View File

@@ -128,7 +128,8 @@ final as (
-- Component scores (0-100)
round(safety_score::numeric, 1) as safety_score,
round(affordability_score::numeric, 1) as affordability_score,
-- Amenity score not available at this level, use placeholder
-- TODO: Replace with actual amenity score when fact_amenities is populated
-- Currently uses neutral placeholder (50.0) which affects livability_score accuracy
50.0 as amenity_score,
-- Composite livability score: safety (40%), affordability (40%), amenities (20%)

View File

@@ -6,16 +6,16 @@ models:
columns:
- name: rental_id
description: "Unique identifier for rental record"
tests:
data_tests:
- unique
- not_null
- name: date_key
description: "Date dimension key (YYYYMMDD)"
tests:
data_tests:
- not_null
- name: zone_key
description: "CMHC zone dimension key"
tests:
data_tests:
- not_null
- name: stg_dimensions__cmhc_zones
@@ -23,12 +23,12 @@ models:
columns:
- name: zone_key
description: "Zone dimension key"
tests:
data_tests:
- unique
- not_null
- name: zone_code
description: "CMHC zone code"
tests:
data_tests:
- unique
- not_null
@@ -37,12 +37,12 @@ models:
columns:
- name: neighbourhood_id
description: "Neighbourhood primary key"
tests:
data_tests:
- unique
- not_null
- name: neighbourhood_name
description: "Official neighbourhood name"
tests:
data_tests:
- not_null
- name: geometry
description: "PostGIS geometry (POLYGON)"
@@ -52,16 +52,16 @@ models:
columns:
- name: census_id
description: "Census record identifier"
tests:
data_tests:
- unique
- not_null
- name: neighbourhood_id
description: "Neighbourhood foreign key"
tests:
data_tests:
- not_null
- name: census_year
description: "Census year (2016, 2021)"
tests:
data_tests:
- not_null
- name: stg_toronto__crime
@@ -69,16 +69,16 @@ models:
columns:
- name: crime_id
description: "Crime record identifier"
tests:
data_tests:
- unique
- not_null
- name: neighbourhood_id
description: "Neighbourhood foreign key"
tests:
data_tests:
- not_null
- name: crime_type
description: "Type of crime"
tests:
data_tests:
- not_null
- name: stg_toronto__amenities
@@ -86,16 +86,16 @@ models:
columns:
- name: amenity_id
description: "Amenity record identifier"
tests:
data_tests:
- unique
- not_null
- name: neighbourhood_id
description: "Neighbourhood foreign key"
tests:
data_tests:
- not_null
- name: amenity_type
description: "Type of amenity"
tests:
data_tests:
- not_null
- name: stg_cmhc__zone_crosswalk
@@ -103,18 +103,18 @@ models:
columns:
- name: crosswalk_id
description: "Crosswalk record identifier"
tests:
data_tests:
- unique
- not_null
- name: cmhc_zone_code
description: "CMHC zone code"
tests:
data_tests:
- not_null
- name: neighbourhood_id
description: "Neighbourhood foreign key"
tests:
data_tests:
- not_null
- name: area_weight
description: "Proportional area weight (0-1)"
tests:
data_tests:
- not_null

View File

@@ -10,8 +10,9 @@ staged as (
select
zone_key,
zone_code,
zone_name,
geometry
zone_name
-- geometry column excluded: CMHC does not provide zone boundaries
-- Spatial analysis uses dim_neighbourhood geometry instead
from source
)