from datetime import date, datetime from sqlalchemy import Date, DateTime, Float, ForeignKey, Index, String, UniqueConstraint from sqlalchemy.orm import Mapped, mapped_column, relationship from app.database import Base class EarningsEvent(Base): """Earnings calendar + surprise history, sourced from the DoltHub earnings repo. Forward rows (``announce_date`` > today) are the calendar; past rows are results. Rescheduling is handled in the importer's promotion transaction: this source's future-dated rows are deleted and re-inserted from the new snapshot so moved/cancelled dates never linger; past rows are never deleted. """ __tablename__ = "earnings_events" __table_args__ = ( UniqueConstraint("ticker_id", "announce_date", name="uq_earnings_ticker_announce"), Index("ix_earnings_events_announce_date", "announce_date"), ) id: Mapped[int] = mapped_column(primary_key=True) ticker_id: Mapped[int] = mapped_column( ForeignKey("tickers.id", ondelete="CASCADE"), nullable=False ) announce_date: Mapped[date] = mapped_column(Date, nullable=False) # bmo | amc | unknown (source coverage is partial) session: Mapped[str] = mapped_column(String(10), nullable=False, default="unknown") period_end: Mapped[date | None] = mapped_column(Date, nullable=True) eps_estimate: Mapped[float | None] = mapped_column(Float, nullable=True) eps_actual: Mapped[float | None] = mapped_column(Float, nullable=True) source: Mapped[str] = mapped_column(String(32), nullable=False) import_run_id: Mapped[int | None] = mapped_column( ForeignKey("data_import_runs.id", ondelete="SET NULL"), nullable=True ) created_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), default=datetime.utcnow, nullable=False ) ticker = relationship("Ticker", back_populates="earnings_events")