Files
eventspace/backend/app/models/guest.py
Felipe Cardoso 4e66b22bae Set default guest permissions to allow bringing up to 10 guests.
Updated guest schema and database models to increase the default value for `max_additional_guests` from 0 to 10 and enable `can_bring_guests` by default. This ensures new guests can bring additional attendees without manual configuration.
2025-03-16 09:45:37 +01:00

93 lines
3.5 KiB
Python

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=10)
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=True)
# 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),
)