Add RSVP model with status tracking and guest constraints
Introduce a new RSVP model to manage responses for events, including status, guest count, and additional details like dietary requirements. Enforce uniqueness for each guest per event and provide functionality to update RSVP status. This will support efficient event RSVP handling and data integrity.
This commit is contained in:
121
backend/app/models/gift.py
Normal file
121
backend/app/models/gift.py
Normal file
@@ -0,0 +1,121 @@
|
||||
from datetime import datetime, timezone
|
||||
from enum import Enum
|
||||
from sqlalchemy import (
|
||||
Column, String, Boolean, ForeignKey, UniqueConstraint,
|
||||
Integer, DateTime, Enum as SQLEnum, Table, Float
|
||||
)
|
||||
from sqlalchemy.orm import relationship
|
||||
from sqlalchemy.dialects.postgresql import UUID, JSONB
|
||||
from .base import Base, TimestampMixin, UUIDMixin
|
||||
|
||||
|
||||
class GiftStatus(str, Enum):
|
||||
AVAILABLE = "available"
|
||||
RESERVED = "reserved"
|
||||
PURCHASED = "purchased"
|
||||
RECEIVED = "received"
|
||||
REMOVED = "removed"
|
||||
|
||||
|
||||
class GiftPriority(str, Enum):
|
||||
LOW = "low"
|
||||
MEDIUM = "medium"
|
||||
HIGH = "high"
|
||||
MUST_HAVE = "must_have"
|
||||
|
||||
|
||||
class GiftItem(Base, UUIDMixin, TimestampMixin):
|
||||
__tablename__ = 'gift_items'
|
||||
|
||||
# Foreign Keys
|
||||
event_id = Column(UUID(as_uuid=True), ForeignKey('events.id'), nullable=False)
|
||||
added_by = Column(UUID(as_uuid=True), ForeignKey('users.id'), nullable=False)
|
||||
category_id = Column(UUID(as_uuid=True), ForeignKey('gift_categories.id'))
|
||||
|
||||
# Gift Details
|
||||
name = Column(String, nullable=False)
|
||||
description = Column(String)
|
||||
price = Column(Float)
|
||||
currency = Column(String, default='USD')
|
||||
quantity_requested = Column(Integer, default=1)
|
||||
quantity_received = Column(Integer, default=0)
|
||||
|
||||
# Status and Priority
|
||||
status = Column(SQLEnum(GiftStatus), nullable=False, default=GiftStatus.AVAILABLE)
|
||||
priority = Column(SQLEnum(GiftPriority), default=GiftPriority.MEDIUM)
|
||||
|
||||
# Purchase Information
|
||||
purchase_url = Column(String)
|
||||
store_name = Column(String)
|
||||
brand = Column(String)
|
||||
model = Column(String)
|
||||
|
||||
# Display
|
||||
image_url = Column(String)
|
||||
display_order = Column(Integer)
|
||||
is_visible = Column(Boolean, default=True)
|
||||
|
||||
# Additional Information
|
||||
notes = Column(String)
|
||||
custom_fields = Column(JSONB)
|
||||
|
||||
# Tracking
|
||||
last_status_change = Column(DateTime(timezone=True))
|
||||
|
||||
# Relationships
|
||||
event = relationship("Event", back_populates="gifts")
|
||||
added_by_user = relationship("User", foreign_keys=[added_by])
|
||||
category = relationship("GiftCategory", back_populates="gifts")
|
||||
reserved_by = relationship("Guest",
|
||||
secondary="guest_gifts",
|
||||
back_populates="gifts")
|
||||
purchase_history = relationship("GiftPurchase",
|
||||
back_populates="gift_item",
|
||||
order_by="desc(GiftPurchase.purchased_at)")
|
||||
|
||||
def __repr__(self):
|
||||
return f"<GiftItem {self.name} ({self.status.value})>"
|
||||
|
||||
def update_status(self, new_status: GiftStatus):
|
||||
"""Update gift status and record the change time"""
|
||||
self.status = new_status
|
||||
self.last_status_change = datetime.now(timezone.utc)
|
||||
|
||||
@property
|
||||
def remaining_quantity(self) -> int:
|
||||
"""Calculate remaining quantity needed"""
|
||||
return max(0, self.quantity_requested - self.quantity_received)
|
||||
|
||||
@property
|
||||
def is_fully_received(self) -> bool:
|
||||
"""Check if all requested quantities have been received"""
|
||||
return self.quantity_received >= self.quantity_requested
|
||||
|
||||
@property
|
||||
def formatted_price(self) -> str:
|
||||
"""Return formatted price with currency"""
|
||||
if self.price is None:
|
||||
return "Price not set"
|
||||
return f"{self.price:.2f} {self.currency}"
|
||||
|
||||
|
||||
# Association table for tracking gift purchases
|
||||
class GiftPurchase(Base, UUIDMixin):
|
||||
__tablename__ = 'gift_purchases'
|
||||
|
||||
gift_id = Column(UUID(as_uuid=True), ForeignKey('gift_items.id'), nullable=False)
|
||||
guest_id = Column(UUID(as_uuid=True), ForeignKey('guests.id'), nullable=False)
|
||||
quantity = Column(Integer, default=1, nullable=False)
|
||||
purchased_at = Column(DateTime(timezone=True),
|
||||
default=lambda: datetime.now(timezone.utc),
|
||||
nullable=False)
|
||||
purchase_price = Column(Float)
|
||||
purchase_currency = Column(String)
|
||||
notes = Column(String)
|
||||
|
||||
# Relationships
|
||||
gift_item = relationship("GiftItem", back_populates="purchase_history")
|
||||
guest = relationship("Guest")
|
||||
|
||||
def __repr__(self):
|
||||
return f"<GiftPurchase gift_id={self.gift_id} guest_id={self.guest_id}>"
|
||||
Reference in New Issue
Block a user