from sqlalchemy import ( Boolean, CheckConstraint, DateTime, Integer, ForeignKey, Index, String, UniqueConstraint, func, ) from sqlalchemy.orm import Mapped, mapped_column, relationship from datetime import datetime from typing import Optional from app.database import Base class CalendarMember(Base): __tablename__ = "calendar_members" __table_args__ = ( UniqueConstraint("calendar_id", "user_id", name="uq_calendar_members_cal_user"), CheckConstraint( "permission IN ('read_only', 'create_modify', 'full_access')", name="ck_calendar_members_permission", ), CheckConstraint( "status IN ('pending', 'accepted', 'rejected')", name="ck_calendar_members_status", ), Index("ix_calendar_members_user_id", "user_id"), Index("ix_calendar_members_calendar_id", "calendar_id"), Index("ix_calendar_members_status", "status"), ) id: Mapped[int] = mapped_column(primary_key=True, index=True) calendar_id: Mapped[int] = mapped_column( Integer, ForeignKey("calendars.id", ondelete="CASCADE"), nullable=False ) user_id: Mapped[int] = mapped_column( Integer, ForeignKey("users.id", ondelete="CASCADE"), nullable=False ) invited_by: Mapped[Optional[int]] = mapped_column( Integer, ForeignKey("users.id", ondelete="SET NULL"), nullable=True ) permission: Mapped[str] = mapped_column(String(20), nullable=False) can_add_others: Mapped[bool] = mapped_column( Boolean, default=False, server_default="false" ) local_color: Mapped[Optional[str]] = mapped_column(String(20), nullable=True) status: Mapped[str] = mapped_column(String(20), nullable=False, default="pending") invited_at: Mapped[datetime] = mapped_column( DateTime, default=func.now(), server_default=func.now() ) accepted_at: Mapped[Optional[datetime]] = mapped_column(DateTime, nullable=True) calendar: Mapped["Calendar"] = relationship(back_populates="members", lazy="raise") user: Mapped["User"] = relationship(foreign_keys=[user_id], lazy="raise") inviter: Mapped[Optional["User"]] = relationship( foreign_keys=[invited_by], lazy="raise" )