sponsor_toast_state.py 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839
  1. """Per-user (or install-default) state for the sponsor-prompt toast.
  2. A single row stores which sponsor-toast milestones have already fired for a
  3. given user, when the most recent toast was shown (for the 14-day cooldown),
  4. and the app version last seen so we can fire the "version-update" trigger
  5. exactly once per major bump.
  6. ``user_id`` is nullable: in auth-disabled installs (no user concept), the
  7. service stores everything against a single NULL-keyed row.
  8. """
  9. from __future__ import annotations
  10. from datetime import datetime
  11. from sqlalchemy import DateTime, ForeignKey, Integer, String, Text, UniqueConstraint, func
  12. from sqlalchemy.orm import Mapped, mapped_column
  13. from backend.app.core.database import Base
  14. class SponsorToastState(Base):
  15. __tablename__ = "sponsor_toast_state"
  16. __table_args__ = (UniqueConstraint("user_id", name="uq_sponsor_toast_state_user_id"),)
  17. id: Mapped[int] = mapped_column(primary_key=True)
  18. user_id: Mapped[int | None] = mapped_column(
  19. Integer,
  20. ForeignKey("users.id", ondelete="CASCADE"),
  21. nullable=True,
  22. index=True,
  23. )
  24. last_shown_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)
  25. # JSON-serialised list[str] of milestone keys already fired (e.g. ["prints-100", "cost-100"]).
  26. # Stored as Text for SQLite/Postgres uniformity; the service serialises with json.dumps.
  27. milestones_seen: Mapped[str] = mapped_column(Text, nullable=False, default="[]")
  28. last_seen_version: Mapped[str | None] = mapped_column(String(50), nullable=True)
  29. created_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now())
  30. updated_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now(), onupdate=func.now())