"""artist_visit: per-artist last-viewed timestamp for the "+N new" badge Revision ID: 0034 Revises: 0033 Create Date: 2026-06-03 Powers the artists-directory "+N new since last visit" badge + ArtistView banner. Single row per artist (no user_id yet — rule #47 multi-user ACL is aspirational; widens to (user_id, artist_id) PK when User lands). Seed every existing artist with `last_viewed_at = NOW()` so the badge starts at 0 across the board — no noisy "you have 5000 unseen images" on first deploy. New artists auto-get a row via `ArtistService.find_or_create`. """ from typing import Sequence, Union import sqlalchemy as sa from alembic import op revision: str = "0034" down_revision: Union[str, None] = "0033" branch_labels: Union[str, Sequence[str], None] = None depends_on: Union[str, Sequence[str], None] = None def upgrade() -> None: op.create_table( "artist_visit", sa.Column( "artist_id", sa.Integer, sa.ForeignKey("artist.id", ondelete="CASCADE"), primary_key=True, ), sa.Column( "last_viewed_at", sa.DateTime(timezone=True), nullable=False, server_default=sa.text("NOW()"), ), ) # Seed: every existing artist starts "fully caught up". Without this, # every operator with N artists would see N badges (worth of every # image ever imported) on first deploy. op.execute( "INSERT INTO artist_visit (artist_id, last_viewed_at) " "SELECT id, NOW() FROM artist" ) def downgrade() -> None: op.drop_table("artist_visit")