refactor: multi-dashboard structural migration
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:
2026-02-01 19:08:20 -05:00
parent a5d6866d63
commit 62d1a52eed
73 changed files with 1114 additions and 623 deletions

View File

@@ -8,11 +8,18 @@ from sqlalchemy.orm import Mapped, mapped_column
from .base import Base
# Schema constants
RAW_TORONTO_SCHEMA = "raw_toronto"
class DimTime(Base):
"""Time dimension table."""
"""Time dimension table (shared across all projects).
Note: Stays in public schema as it's a shared dimension.
"""
__tablename__ = "dim_time"
__table_args__ = {"schema": "public"}
date_key: Mapped[int] = mapped_column(Integer, primary_key=True)
full_date: Mapped[date] = mapped_column(Date, nullable=False, unique=True)
@@ -27,6 +34,7 @@ class DimCMHCZone(Base):
"""CMHC zone dimension table with PostGIS geometry."""
__tablename__ = "dim_cmhc_zone"
__table_args__ = {"schema": RAW_TORONTO_SCHEMA}
zone_key: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
zone_code: Mapped[str] = mapped_column(String(10), nullable=False, unique=True)
@@ -41,6 +49,7 @@ class DimNeighbourhood(Base):
"""
__tablename__ = "dim_neighbourhood"
__table_args__ = {"schema": RAW_TORONTO_SCHEMA}
neighbourhood_id: Mapped[int] = mapped_column(Integer, primary_key=True)
name: Mapped[str] = mapped_column(String(100), nullable=False)
@@ -69,6 +78,7 @@ class DimPolicyEvent(Base):
"""Policy event dimension for time-series annotation."""
__tablename__ = "dim_policy_event"
__table_args__ = {"schema": RAW_TORONTO_SCHEMA}
event_id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
event_date: Mapped[date] = mapped_column(Date, nullable=False)