Files
vidconf/backend/models/invitee.py

62 lines
2.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Модель ConferenceInvitee — приглашённый на конференцию (ADR-003).
Не путать с `ConferenceParticipant` (ADR-002) — та таблица фиксирует
ФАКТИЧЕСКОЕ присутствие в сеансе, эта — состав, заданный организатором ДО
конференции. Организатор в этой таблице не хранится: он всегда выводится из
`conferences.owner_id` (см. ADR-003, п.2) — инвариант «организатор всегда в
составе и неудаляем» обеспечен конструктивно, без триггеров.
"""
import uuid
from datetime import datetime
from sqlalchemy import CheckConstraint, DateTime, ForeignKey, Index, String, func, text
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.orm import Mapped, mapped_column
from models.base import Base
class ConferenceInvitee(Base):
"""Приглашённый: ровно одна identity — зарегистрированный `user_id` ИЛИ внешний `email`."""
__tablename__ = "conference_invitees"
__table_args__ = (
CheckConstraint(
"(user_id IS NOT NULL)::int + (email IS NOT NULL)::int = 1",
name="ck_conference_invitees_single_identity",
),
# Частичные уникальные индексы (ADR-003, п.1): без дублей приглашения
# одного и того же пользователя/email на одну конференцию.
# `lower(email)` — регистронезависимо (email нормализуется в lower-case
# уже на уровне схемы `InviteeIn`, индекс — доп. страховка).
Index(
"uq_conference_invitees_user",
"conference_id",
"user_id",
unique=True,
postgresql_where=text("user_id IS NOT NULL"),
),
Index(
"uq_conference_invitees_email",
"conference_id",
text("lower(email)"),
unique=True,
postgresql_where=text("email IS NOT NULL"),
),
)
id: Mapped[uuid.UUID] = mapped_column(
UUID(as_uuid=True), primary_key=True, server_default=text("gen_random_uuid()")
)
conference_id: Mapped[uuid.UUID] = mapped_column(
UUID(as_uuid=True), ForeignKey("conferences.id", ondelete="CASCADE"), nullable=False
)
user_id: Mapped[uuid.UUID | None] = mapped_column(
UUID(as_uuid=True), ForeignKey("users.id", ondelete="CASCADE"), nullable=True
)
email: Mapped[str | None] = mapped_column(String(255), nullable=True)
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), nullable=False, server_default=func.now()
)