from __future__ import annotations import uuid from datetime import datetime from sqlalchemy import CheckConstraint, DateTime, Index, String, text from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.orm import Mapped, mapped_column from core.db.base import Base, SoftDeleteMixin, TimestampMixin from core.db.types import json_jsonb as jsonb from schemas.enums import NotificationTargetMode class Notification(TimestampMixin, SoftDeleteMixin, Base): __tablename__ = "notifications" __table_args__ = ( CheckConstraint( "status IN ('draft', 'published', 'revoked')", name="ck_notifications_status", ), CheckConstraint( "target_mode IN ('new_users', 'exist_users', 'all_users', 'user_ids')", name="ck_notifications_target_mode", ), CheckConstraint( "jsonb_typeof(payload) = 'object'", name="ck_notifications_payload_object", ), Index( "ix_notifications_status_created_at", "status", "created_at", ), Index( "ix_notifications_published_at", "published_at", ), Index( "uq_notifications_source_source_key", "source", "source_key", unique=True, postgresql_where=text("source_key IS NOT NULL"), ), ) id: Mapped[uuid.UUID] = mapped_column( UUID(as_uuid=True), primary_key=True, default=uuid.uuid4 ) type: Mapped[str] = mapped_column( String(32), nullable=False, server_default=text("'system'") ) source: Mapped[str] = mapped_column( String(32), nullable=False, server_default=text("'manual'") ) source_key: Mapped[str | None] = mapped_column(String(128), nullable=True) source_version: Mapped[int | None] = mapped_column(nullable=True) content_hash: Mapped[str | None] = mapped_column(String(64), nullable=True) title: Mapped[dict[str, str]] = mapped_column( jsonb, nullable=False, server_default=text("'{}'::jsonb"), default=dict, ) body: Mapped[dict[str, str]] = mapped_column( jsonb, nullable=False, server_default=text("'{}'::jsonb"), default=dict, ) payload: Mapped[dict[str, object]] = mapped_column( jsonb, nullable=False, server_default=text("'{}'::jsonb"), default=dict, ) status: Mapped[str] = mapped_column( String(16), nullable=False, server_default=text("'published'") ) target_mode: Mapped[NotificationTargetMode] = mapped_column( String(32), nullable=False, server_default=text("'all_users'") ) published_at: Mapped[datetime | None] = mapped_column( DateTime(timezone=True), nullable=True ) revoked_at: Mapped[datetime | None] = mapped_column( DateTime(timezone=True), nullable=True )