UMBRA/backend/app/routers/events.py
2026-02-15 16:13:41 +08:00

123 lines
3.7 KiB
Python

from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select
from typing import Optional, List
from datetime import date
from app.database import get_db
from app.models.calendar_event import CalendarEvent
from app.schemas.calendar_event import CalendarEventCreate, CalendarEventUpdate, CalendarEventResponse
from app.routers.auth import get_current_session
from app.models.settings import Settings
router = APIRouter()
@router.get("/", response_model=List[CalendarEventResponse])
async def get_events(
start: Optional[date] = Query(None),
end: Optional[date] = Query(None),
db: AsyncSession = Depends(get_db),
current_user: Settings = Depends(get_current_session)
):
"""Get all calendar events with optional date range filtering."""
query = select(CalendarEvent)
if start:
query = query.where(CalendarEvent.start_datetime >= start)
if end:
query = query.where(CalendarEvent.end_datetime <= end)
query = query.order_by(CalendarEvent.start_datetime.asc())
result = await db.execute(query)
events = result.scalars().all()
return events
@router.post("/", response_model=CalendarEventResponse, status_code=201)
async def create_event(
event: CalendarEventCreate,
db: AsyncSession = Depends(get_db),
current_user: Settings = Depends(get_current_session)
):
"""Create a new calendar event."""
if event.end_datetime < event.start_datetime:
raise HTTPException(status_code=400, detail="End datetime must be after start datetime")
new_event = CalendarEvent(**event.model_dump())
db.add(new_event)
await db.commit()
await db.refresh(new_event)
return new_event
@router.get("/{event_id}", response_model=CalendarEventResponse)
async def get_event(
event_id: int,
db: AsyncSession = Depends(get_db),
current_user: Settings = Depends(get_current_session)
):
"""Get a specific calendar event by ID."""
result = await db.execute(select(CalendarEvent).where(CalendarEvent.id == event_id))
event = result.scalar_one_or_none()
if not event:
raise HTTPException(status_code=404, detail="Calendar event not found")
return event
@router.put("/{event_id}", response_model=CalendarEventResponse)
async def update_event(
event_id: int,
event_update: CalendarEventUpdate,
db: AsyncSession = Depends(get_db),
current_user: Settings = Depends(get_current_session)
):
"""Update a calendar event."""
result = await db.execute(select(CalendarEvent).where(CalendarEvent.id == event_id))
event = result.scalar_one_or_none()
if not event:
raise HTTPException(status_code=404, detail="Calendar event not found")
update_data = event_update.model_dump(exclude_unset=True)
# Validate datetime order if both are being updated
start = update_data.get("start_datetime", event.start_datetime)
end = update_data.get("end_datetime", event.end_datetime)
if end < start:
raise HTTPException(status_code=400, detail="End datetime must be after start datetime")
for key, value in update_data.items():
setattr(event, key, value)
await db.commit()
await db.refresh(event)
return event
@router.delete("/{event_id}", status_code=204)
async def delete_event(
event_id: int,
db: AsyncSession = Depends(get_db),
current_user: Settings = Depends(get_current_session)
):
"""Delete a calendar event."""
result = await db.execute(select(CalendarEvent).where(CalendarEvent.id == event_id))
event = result.scalar_one_or_none()
if not event:
raise HTTPException(status_code=404, detail="Calendar event not found")
await db.delete(event)
await db.commit()
return None