Refactored the event API routes to improve error handling, add logging, and provide enhanced response structures with pagination. Updated tests to use new fixtures and include additional authentication utilities to facilitate testing with FastAPI's dependency injection. Also resolved issues with timezone awareness in event schemas.
93 lines
2.7 KiB
Python
93 lines
2.7 KiB
Python
from datetime import datetime, time, timezone
|
|
from typing import Dict, Optional
|
|
from uuid import UUID
|
|
|
|
from pydantic import BaseModel, Field, field_validator
|
|
|
|
|
|
class EventBase(BaseModel):
|
|
title: str = Field(..., min_length=1, max_length=200)
|
|
description: Optional[str] = None
|
|
location_name: Optional[str] = None
|
|
location_address: Optional[str] = None
|
|
location_url: Optional[str] = None
|
|
event_date: datetime
|
|
event_start_time: Optional[time] = None
|
|
event_end_time: Optional[time] = None
|
|
timezone: str
|
|
rsvp_deadline: Optional[datetime] = None
|
|
is_public: bool = False
|
|
access_code: Optional[str] = None
|
|
theme_id: Optional[UUID] = None
|
|
custom_theme_settings: Optional[Dict] = None
|
|
additional_info: Optional[Dict] = None
|
|
is_active: bool = True
|
|
rsvp_enabled: bool = True
|
|
gift_registry_enabled: bool = True
|
|
updates_enabled: bool = True
|
|
max_guests_per_invitation: Optional[int] = Field(None, ge=1)
|
|
contact_email: Optional[str] = None
|
|
contact_phone: Optional[str] = None
|
|
|
|
@field_validator('timezone')
|
|
def validate_timezone(cls, v):
|
|
from zoneinfo import ZoneInfo
|
|
try:
|
|
ZoneInfo(v)
|
|
return v
|
|
except Exception:
|
|
raise ValueError("Invalid timezone")
|
|
|
|
@field_validator('event_date')
|
|
def validate_event_date(cls, v):
|
|
if not v.tzinfo:
|
|
v = v.replace(tzinfo=timezone.utc)
|
|
now = datetime.now(tz=timezone.utc)
|
|
if v < now:
|
|
raise ValueError("Event date cannot be in the past")
|
|
return v
|
|
|
|
@field_validator('rsvp_deadline')
|
|
def validate_rsvp_deadline(cls, v, values):
|
|
if v:
|
|
if not v.tzinfo:
|
|
raise ValueError("RSVP deadline must be timezone-aware")
|
|
if 'event_date' in values.data:
|
|
if v > values.data['event_date']:
|
|
raise ValueError("RSVP deadline must be before event date")
|
|
return v
|
|
|
|
|
|
class EventCreate(EventBase):
|
|
slug: str = Field(..., min_length=1, pattern="^[a-z0-9-]+$")
|
|
|
|
|
|
class EventUpdate(EventBase):
|
|
title: Optional[str] = None
|
|
event_date: Optional[datetime] = None
|
|
timezone: Optional[str] = None
|
|
slug: Optional[str] = Field(None, min_length=1, pattern="^[a-z0-9-]+$")
|
|
|
|
|
|
class EventInDBBase(EventBase):
|
|
id: UUID
|
|
created_by: UUID
|
|
created_at: datetime
|
|
updated_at: datetime
|
|
slug: str
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
class EventResponse(EventInDBBase):
|
|
@field_validator('event_date')
|
|
def validate_datetime(cls, v):
|
|
if v.tzinfo is None:
|
|
v.event_date = v.event_date.replace(tzinfo=timezone.utc)
|
|
return v
|
|
|
|
|
|
|
|
class Event(EventInDBBase):
|
|
pass |