from sqlalchemy import Boolean, Column, Integer, String, DateTime, ForeignKey, Text, Enum as SQLEnum from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.orm import relationship from sqlalchemy.sql import func from database import Base import uuid import enum class User(Base): __tablename__ = "users" id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, index=True) email = Column(String, unique=True, nullable=False, index=True) created_at = Column(DateTime(timezone=True), server_default=func.now()) # Relationships event_memberships = relationship("EventMember", back_populates="user", cascade="all, delete-orphan") guests_added = relationship("Guest", back_populates="added_by_user", foreign_keys="Guest.added_by_user_id") class Event(Base): __tablename__ = "events" id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, index=True) name = Column(String, nullable=False) date = Column(DateTime(timezone=True), nullable=True) location = Column(String, nullable=True) created_at = Column(DateTime(timezone=True), server_default=func.now()) updated_at = Column(DateTime(timezone=True), onupdate=func.now()) # Relationships members = relationship("EventMember", back_populates="event", cascade="all, delete-orphan") guests = relationship("Guest", back_populates="event", cascade="all, delete-orphan") class RoleEnum(str, enum.Enum): admin = "admin" editor = "editor" viewer = "viewer" class EventMember(Base): __tablename__ = "event_members" id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, index=True) event_id = Column(UUID(as_uuid=True), ForeignKey("events.id", ondelete="CASCADE"), nullable=False, index=True) user_id = Column(UUID(as_uuid=True), ForeignKey("users.id", ondelete="CASCADE"), nullable=False, index=True) role = Column(SQLEnum(RoleEnum), default=RoleEnum.admin, nullable=False) display_name = Column(String, nullable=True) created_at = Column(DateTime(timezone=True), server_default=func.now()) # Relationships event = relationship("Event", back_populates="members") user = relationship("User", back_populates="event_memberships") __table_args__ = ( __import__('sqlalchemy').UniqueConstraint('event_id', 'user_id', name='uq_event_user'), ) class GuestStatus(str, enum.Enum): invited = "invited" confirmed = "confirmed" declined = "declined" class Guest(Base): __tablename__ = "guests_v2" id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, index=True) event_id = Column(UUID(as_uuid=True), ForeignKey("events.id", ondelete="CASCADE"), nullable=False, index=True) added_by_user_id = Column(UUID(as_uuid=True), ForeignKey("users.id"), nullable=False, index=True) # Guest Information first_name = Column(String, nullable=False) last_name = Column(String, nullable=False) email = Column(String, nullable=True) phone = Column(String, nullable=True) # Legacy field - use phone_number instead phone_number = Column(String, nullable=True) # RSVP & Preferences rsvp_status = Column(SQLEnum(GuestStatus), default=GuestStatus.invited, nullable=False) meal_preference = Column(String, nullable=True) # Plus One has_plus_one = Column(Boolean, default=False) plus_one_name = Column(String, nullable=True) # Event Details table_number = Column(String, nullable=True) side = Column(String, nullable=True) # e.g. "groom side", "bride side" # Source Information owner_email = Column(String, nullable=True) # Email of person who added this guest source = Column(String, default="manual", nullable=False) # 'google', 'manual', 'self-service' # Notes & Metadata notes = Column(Text, nullable=True) created_at = Column(DateTime(timezone=True), server_default=func.now()) updated_at = Column(DateTime(timezone=True), onupdate=func.now()) # Relationships event = relationship("Event", back_populates="guests") added_by_user = relationship("User", back_populates="guests_added", foreign_keys=[added_by_user_id])