Files
kmtnflower/backend/app/api/shows.py

120 lines
3.6 KiB
Python

from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import selectinload
from app.auth import get_current_admin_user
from app.database import get_session
from app.models import Show, ShowSchedule
from app.schemas import ShowCreate, ShowUpdate, ShowResponse
from app.user_models import User
router = APIRouter()
@router.get("", response_model=list[ShowResponse])
async def list_shows(session: AsyncSession = Depends(get_session)):
query = (
select(Show)
.where(Show.active == True)
.options(selectinload(Show.schedules))
.order_by(Show.display_order, Show.title)
)
result = await session.execute(query)
return list(result.scalars().all())
@router.get("/{show_id}", response_model=ShowResponse)
async def get_show(
show_id: int,
session: AsyncSession = Depends(get_session),
):
result = await session.execute(
select(Show)
.options(selectinload(Show.schedules))
.where(Show.id == show_id)
)
show = result.scalar_one_or_none()
if not show:
raise HTTPException(status_code=404, detail="Show not found")
return show
@router.post("", response_model=ShowResponse, status_code=201)
async def create_show(
payload: ShowCreate,
session: AsyncSession = Depends(get_session),
_: User = Depends(get_current_admin_user),
):
data = payload.model_dump(exclude={"schedules"})
show = Show(**data)
for slot in payload.schedules:
show.schedules.append(ShowSchedule(**slot.model_dump()))
session.add(show)
await session.commit()
await session.refresh(show)
await session.refresh(show)
# Re-query with eager load to return schedules
result = await session.execute(
select(Show)
.options(selectinload(Show.schedules))
.where(Show.id == show.id)
)
return result.scalar_one()
@router.put("/{show_id}", response_model=ShowResponse)
async def update_show(
show_id: int,
payload: ShowUpdate,
session: AsyncSession = Depends(get_session),
_: User = Depends(get_current_admin_user),
):
result = await session.execute(
select(Show)
.options(selectinload(Show.schedules))
.where(Show.id == show_id)
)
show = result.scalar_one_or_none()
if not show:
raise HTTPException(status_code=404, detail="Show not found")
update_data = payload.model_dump(exclude_unset=True, exclude={"schedules"})
for key, value in update_data.items():
setattr(show, key, value)
if payload.schedules is not None:
# Replace all schedule slots
for sched in show.schedules:
await session.delete(sched)
await session.flush() # execute deletes before inserts to avoid UNIQUE conflict
for slot in payload.schedules:
session.add(ShowSchedule(show_id=show.id, **slot.model_dump()))
await session.commit()
await session.refresh(show)
# Re-query with eager load
result = await session.execute(
select(Show)
.options(selectinload(Show.schedules))
.where(Show.id == show.id)
)
return result.scalar_one()
@router.delete("/{show_id}", status_code=204)
async def delete_show(
show_id: int,
session: AsyncSession = Depends(get_session),
_: User = Depends(get_current_admin_user),
):
result = await session.execute(select(Show).where(Show.id == show_id))
show = result.scalar_one_or_none()
if not show:
raise HTTPException(status_code=404, detail="Show not found")
await session.delete(show)
await session.commit()