from datetime import datetime, timezone from sqlalchemy import DateTime, ForeignKey, Index, Integer, Text, UniqueConstraint from sqlalchemy.dialects.postgresql import JSONB from sqlalchemy.orm import Mapped, mapped_column from fabledassistant.models import Base class WeatherCache(Base): __tablename__ = "weather_cache" id: Mapped[int] = mapped_column(primary_key=True) user_id: Mapped[int] = mapped_column(Integer, ForeignKey("users.id", ondelete="CASCADE")) # Unique key per location, e.g. "home", "work", or "event:" location_key: Mapped[str] = mapped_column(Text) location_label: Mapped[str] = mapped_column(Text, default="") # Current 7-day forecast from Open-Meteo (raw JSON) forecast_json: Mapped[dict | None] = mapped_column(JSONB, nullable=True) # Previous forecast — used to detect changes between fetches previous_json: Mapped[dict | None] = mapped_column(JSONB, nullable=True) fetched_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), default=lambda: datetime.now(timezone.utc) ) __table_args__ = ( UniqueConstraint("user_id", "location_key", name="uq_weather_cache_user_location"), Index("ix_weather_cache_user_id", "user_id"), ) def to_dict(self) -> dict: return { "id": self.id, "location_key": self.location_key, "location_label": self.location_label, "forecast_json": self.forecast_json, "fetched_at": self.fetched_at.isoformat(), }