"""Add recipient-scoped generic notifications. Revision ID: 20260716_01 Revises: 20260715_06 """ import sqlalchemy as sa from alembic import op from sqlalchemy.dialects import postgresql revision = "20260716_01" down_revision = "20260715_06" branch_labels = None depends_on = None def upgrade() -> None: op.create_table( "notifications", sa.Column("id", postgresql.UUID(as_uuid=True), nullable=False), sa.Column("study_id", postgresql.UUID(as_uuid=True), nullable=False), sa.Column("recipient_id", postgresql.UUID(as_uuid=True), nullable=False), sa.Column("category", sa.String(length=64), nullable=False), sa.Column("priority", sa.String(length=16), nullable=False, server_default="NORMAL"), sa.Column("title", sa.String(length=180), nullable=False), sa.Column("message", sa.String(length=500), nullable=False), sa.Column("action_path", sa.Text(), nullable=True), sa.Column("source_type", sa.String(length=64), nullable=False), sa.Column("source_id", sa.String(length=100), nullable=False), sa.Column("source_version", sa.String(length=100), nullable=True), sa.Column("dedupe_key", sa.String(length=255), nullable=False), sa.Column("read_at", sa.DateTime(timezone=True), nullable=True), sa.Column("resolved_at", sa.DateTime(timezone=True), nullable=True), sa.Column("created_at", sa.DateTime(timezone=True), nullable=False, server_default=sa.func.now()), sa.Column("updated_at", sa.DateTime(timezone=True), nullable=False, server_default=sa.func.now()), sa.ForeignKeyConstraint(["recipient_id"], ["users.id"], ondelete="CASCADE"), sa.ForeignKeyConstraint(["study_id"], ["studies.id"], ondelete="CASCADE"), sa.PrimaryKeyConstraint("id"), sa.UniqueConstraint("recipient_id", "dedupe_key", name="uq_notifications_recipient_dedupe"), ) op.create_index( "ix_notifications_recipient_study_state", "notifications", ["recipient_id", "study_id", "resolved_at", "read_at", "created_at"], ) op.create_index("ix_notifications_source", "notifications", ["source_type", "source_id"]) def downgrade() -> None: op.drop_index("ix_notifications_source", table_name="notifications") op.drop_index("ix_notifications_recipient_study_state", table_name="notifications") op.drop_table("notifications")