refactor: multi-dashboard structural migration
Some checks failed
CI / lint-and-test (pull_request) Has been cancelled
Some checks failed
CI / lint-and-test (pull_request) Has been cancelled
- Rename dbt project from toronto_housing to portfolio - Restructure dbt models into domain subdirectories: - shared/ for cross-domain dimensions (dim_time) - staging/toronto/, intermediate/toronto/, marts/toronto/ - Update SQLAlchemy models for raw_toronto schema - Add explicit cross-schema FK relationships for FactRentals - Namespace figure factories under figures/toronto/ - Namespace notebooks under notebooks/toronto/ - Update Makefile with domain-specific targets and env loading - Update all documentation for multi-dashboard structure This enables adding new dashboard projects (e.g., /football, /energy) without structural conflicts or naming collisions. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -4,6 +4,7 @@ from sqlalchemy import ForeignKey, Index, Integer, Numeric, String
|
||||
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
||||
|
||||
from .base import Base
|
||||
from .dimensions import RAW_TORONTO_SCHEMA
|
||||
|
||||
|
||||
class BridgeCMHCNeighbourhood(Base):
|
||||
@@ -14,6 +15,11 @@ class BridgeCMHCNeighbourhood(Base):
|
||||
"""
|
||||
|
||||
__tablename__ = "bridge_cmhc_neighbourhood"
|
||||
__table_args__ = (
|
||||
Index("ix_bridge_cmhc_zone", "cmhc_zone_code"),
|
||||
Index("ix_bridge_neighbourhood", "neighbourhood_id"),
|
||||
{"schema": RAW_TORONTO_SCHEMA},
|
||||
)
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
||||
cmhc_zone_code: Mapped[str] = mapped_column(String(10), nullable=False)
|
||||
@@ -22,11 +28,6 @@ class BridgeCMHCNeighbourhood(Base):
|
||||
Numeric(5, 4), nullable=False
|
||||
) # 0.0000 to 1.0000
|
||||
|
||||
__table_args__ = (
|
||||
Index("ix_bridge_cmhc_zone", "cmhc_zone_code"),
|
||||
Index("ix_bridge_neighbourhood", "neighbourhood_id"),
|
||||
)
|
||||
|
||||
|
||||
class FactCensus(Base):
|
||||
"""Census statistics by neighbourhood and year.
|
||||
@@ -35,6 +36,10 @@ class FactCensus(Base):
|
||||
"""
|
||||
|
||||
__tablename__ = "fact_census"
|
||||
__table_args__ = (
|
||||
Index("ix_fact_census_neighbourhood_year", "neighbourhood_id", "census_year"),
|
||||
{"schema": RAW_TORONTO_SCHEMA},
|
||||
)
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
||||
neighbourhood_id: Mapped[int] = mapped_column(Integer, nullable=False)
|
||||
@@ -66,10 +71,6 @@ class FactCensus(Base):
|
||||
Numeric(12, 2), nullable=True
|
||||
)
|
||||
|
||||
__table_args__ = (
|
||||
Index("ix_fact_census_neighbourhood_year", "neighbourhood_id", "census_year"),
|
||||
)
|
||||
|
||||
|
||||
class FactCrime(Base):
|
||||
"""Crime statistics by neighbourhood and year.
|
||||
@@ -78,6 +79,11 @@ class FactCrime(Base):
|
||||
"""
|
||||
|
||||
__tablename__ = "fact_crime"
|
||||
__table_args__ = (
|
||||
Index("ix_fact_crime_neighbourhood_year", "neighbourhood_id", "year"),
|
||||
Index("ix_fact_crime_type", "crime_type"),
|
||||
{"schema": RAW_TORONTO_SCHEMA},
|
||||
)
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
||||
neighbourhood_id: Mapped[int] = mapped_column(Integer, nullable=False)
|
||||
@@ -86,11 +92,6 @@ class FactCrime(Base):
|
||||
count: Mapped[int] = mapped_column(Integer, nullable=False)
|
||||
rate_per_100k: Mapped[float | None] = mapped_column(Numeric(10, 2), nullable=True)
|
||||
|
||||
__table_args__ = (
|
||||
Index("ix_fact_crime_neighbourhood_year", "neighbourhood_id", "year"),
|
||||
Index("ix_fact_crime_type", "crime_type"),
|
||||
)
|
||||
|
||||
|
||||
class FactAmenities(Base):
|
||||
"""Amenity counts by neighbourhood.
|
||||
@@ -99,6 +100,11 @@ class FactAmenities(Base):
|
||||
"""
|
||||
|
||||
__tablename__ = "fact_amenities"
|
||||
__table_args__ = (
|
||||
Index("ix_fact_amenities_neighbourhood_year", "neighbourhood_id", "year"),
|
||||
Index("ix_fact_amenities_type", "amenity_type"),
|
||||
{"schema": RAW_TORONTO_SCHEMA},
|
||||
)
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
||||
neighbourhood_id: Mapped[int] = mapped_column(Integer, nullable=False)
|
||||
@@ -106,11 +112,6 @@ class FactAmenities(Base):
|
||||
count: Mapped[int] = mapped_column(Integer, nullable=False)
|
||||
year: Mapped[int] = mapped_column(Integer, nullable=False)
|
||||
|
||||
__table_args__ = (
|
||||
Index("ix_fact_amenities_neighbourhood_year", "neighbourhood_id", "year"),
|
||||
Index("ix_fact_amenities_type", "amenity_type"),
|
||||
)
|
||||
|
||||
|
||||
class FactRentals(Base):
|
||||
"""Fact table for CMHC rental market data.
|
||||
@@ -119,13 +120,16 @@ class FactRentals(Base):
|
||||
"""
|
||||
|
||||
__tablename__ = "fact_rentals"
|
||||
__table_args__ = {"schema": RAW_TORONTO_SCHEMA}
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
||||
date_key: Mapped[int] = mapped_column(
|
||||
Integer, ForeignKey("dim_time.date_key"), nullable=False
|
||||
Integer, ForeignKey("public.dim_time.date_key"), nullable=False
|
||||
)
|
||||
zone_key: Mapped[int] = mapped_column(
|
||||
Integer, ForeignKey("dim_cmhc_zone.zone_key"), nullable=False
|
||||
Integer,
|
||||
ForeignKey(f"{RAW_TORONTO_SCHEMA}.dim_cmhc_zone.zone_key"),
|
||||
nullable=False,
|
||||
)
|
||||
bedroom_type: Mapped[str] = mapped_column(String(20), nullable=False)
|
||||
universe: Mapped[int | None] = mapped_column(Integer, nullable=True)
|
||||
@@ -139,6 +143,6 @@ class FactRentals(Base):
|
||||
rent_change_pct: Mapped[float | None] = mapped_column(Numeric(5, 2), nullable=True)
|
||||
reliability_code: Mapped[str | None] = mapped_column(String(2), nullable=True)
|
||||
|
||||
# Relationships
|
||||
time = relationship("DimTime", backref="rentals")
|
||||
zone = relationship("DimCMHCZone", backref="rentals")
|
||||
# Relationships - explicit foreign_keys needed for cross-schema joins
|
||||
time = relationship("DimTime", foreign_keys=[date_key], backref="rentals")
|
||||
zone = relationship("DimCMHCZone", foreign_keys=[zone_key], backref="rentals")
|
||||
|
||||
Reference in New Issue
Block a user