Add Guest model for event guest management
This commit introduces the `Guest` model to manage event guests, including their details, status, RSVP tracking, and relationships with events and users. It also supports features like invitation handling, guest statuses, and guest-to-gift associations. This forms the foundation for handling guest-related functionalities in the backend.
This commit is contained in:
92
backend/app/models/guest.py
Normal file
92
backend/app/models/guest.py
Normal file
@@ -0,0 +1,92 @@
|
||||
from datetime import datetime, timezone
|
||||
from enum import Enum
|
||||
|
||||
from sqlalchemy import Column, String, Boolean, ForeignKey, UniqueConstraint, Integer, Enum as SQLEnum, DateTime, Table
|
||||
from sqlalchemy.dialects.postgresql import UUID, JSONB
|
||||
from sqlalchemy.orm import relationship
|
||||
|
||||
from .base import Base, TimestampMixin, UUIDMixin
|
||||
|
||||
|
||||
class GuestStatus(str, Enum):
|
||||
INVITED = "invited" # Initial state when guest is added
|
||||
PENDING = "pending" # Invitation sent, waiting for response
|
||||
CONFIRMED = "confirmed" # RSVP confirmed attendance
|
||||
DECLINED = "declined" # RSVP declined attendance
|
||||
WAITLISTED = "waitlisted" # On waitlist if event is at capacity
|
||||
CANCELLED = "cancelled" # Guest cancelled after initial confirmation
|
||||
|
||||
|
||||
class Guest(Base, UUIDMixin, TimestampMixin):
|
||||
__tablename__ = 'guests'
|
||||
|
||||
# Foreign Keys
|
||||
event_id = Column(UUID(as_uuid=True), ForeignKey('events.id'), nullable=False)
|
||||
invited_by = Column(UUID(as_uuid=True), ForeignKey('users.id'), nullable=False)
|
||||
user_id = Column(UUID(as_uuid=True), ForeignKey('users.id')) # Optional, if guest is a registered user
|
||||
|
||||
# Guest Information
|
||||
full_name = Column(String, nullable=False)
|
||||
email = Column(String)
|
||||
phone = Column(String)
|
||||
invitation_code = Column(String, unique=True, nullable=False)
|
||||
|
||||
# Guest Status
|
||||
status = Column(SQLEnum(GuestStatus), nullable=False, default=GuestStatus.INVITED)
|
||||
max_additional_guests = Column(Integer, default=0)
|
||||
actual_additional_guests = Column(Integer, default=0)
|
||||
|
||||
# Tracking
|
||||
invitation_sent_at = Column(DateTime(timezone=True))
|
||||
last_reminded_at = Column(DateTime(timezone=True))
|
||||
response_date = Column(DateTime(timezone=True))
|
||||
|
||||
# Additional Information
|
||||
dietary_restrictions = Column(String)
|
||||
notes = Column(String)
|
||||
custom_fields = Column(JSONB)
|
||||
|
||||
# Access Management
|
||||
is_blocked = Column(Boolean, default=False)
|
||||
can_bring_guests = Column(Boolean, default=False)
|
||||
|
||||
# Relationships
|
||||
event = relationship("Event", back_populates="guests")
|
||||
inviter = relationship("User", foreign_keys=[invited_by])
|
||||
user = relationship("User", foreign_keys=[user_id])
|
||||
rsvp = relationship("RSVP", back_populates="guest", uselist=False)
|
||||
gifts = relationship("GiftItem", secondary="guest_gifts", back_populates="reserved_by")
|
||||
|
||||
__table_args__ = (
|
||||
UniqueConstraint('event_id', 'email', name='uq_event_guest_email'),
|
||||
)
|
||||
|
||||
def __repr__(self):
|
||||
return f"<Guest {self.full_name} ({self.status.value})>"
|
||||
|
||||
@property
|
||||
def total_guests(self):
|
||||
"""Total number of guests including additional guests"""
|
||||
return 1 + (self.actual_additional_guests or 0)
|
||||
|
||||
@property
|
||||
def has_responded(self):
|
||||
"""Check if guest has responded to invitation"""
|
||||
return self.status in (GuestStatus.CONFIRMED, GuestStatus.DECLINED)
|
||||
|
||||
def update_status(self, new_status: GuestStatus):
|
||||
"""Update guest status and record response date"""
|
||||
self.status = new_status
|
||||
if new_status in (GuestStatus.CONFIRMED, GuestStatus.DECLINED):
|
||||
self.response_date = datetime.now(timezone.utc)
|
||||
|
||||
|
||||
# Association table for guest gifts (many-to-many relationship)
|
||||
guest_gifts = Table(
|
||||
'guest_gifts',
|
||||
Base.metadata,
|
||||
Column('guest_id', UUID(as_uuid=True), ForeignKey('guests.id'), primary_key=True),
|
||||
Column('gift_id', UUID(as_uuid=True), ForeignKey('gift_items.id'), primary_key=True),
|
||||
Column('reserved_at', DateTime(timezone=True), default=lambda: datetime.now(timezone.utc)),
|
||||
Column('notes', String),
|
||||
)
|
||||
Reference in New Issue
Block a user