from uuid import UUID from fastapi import APIRouter, Depends, HTTPException from sqlalchemy import delete, select from sqlalchemy.ext.asyncio import AsyncSession from app.api import deps from app.api.utils import update_object_from_payload, verify_id_list from app.models import ( Project, Slot, User, Volunteer, association_table_volunteer_slot, ) from app.schemas.requests import ( SlotCreateRequest, SlotUpdateRequest, ) from app.schemas.responses import SlotResponse router = APIRouter() @router.get("/project/{id}/slots", response_model=list[SlotResponse]) async def list_project_slots( id: UUID, current_user: User = Depends(deps.get_current_user), session: AsyncSession = Depends(deps.get_session), ): """List slots from project""" p = await session.get(Project, id) if p is None: raise HTTPException(status_code=404, detail="Project not found") results = await session.execute(select(Slot).where(Slot.project_id == id)) return results.scalars() @router.post("/project/{id}/slot", response_model=SlotResponse) async def create_slot( id: UUID, new_slot: SlotCreateRequest, current_user: User = Depends(deps.get_current_user), session: AsyncSession = Depends(deps.get_session), ): """Create a new slot to the project""" p = await session.get(Project, id) if p is None: raise HTTPException(status_code=404, detail="Project not found") input_dict = new_slot.dict() # Extract volunteer list from input dict volunteers: list[UUID] = [] if input_dict["volunteers"] is not None: volunteers = input_dict["volunteers"] await verify_id_list( session, volunteers, id, Volunteer, "Invalid volunteer list" ) del input_dict["volunteers"] slot = Slot(project_id=id, **input_dict) session.add(slot) await session.commit() # Add the slot to the list of volunteer await session.execute( association_table_volunteer_slot.insert().values( [(volunteer_id, slot.id) for volunteer_id in volunteers] ) ) await session.commit() return slot @router.post("/project/{id}/slot/{slot_id}", response_model=SlotResponse) async def update_slot( id: UUID, slot_id: UUID, new_slot: SlotUpdateRequest, current_user: User = Depends(deps.get_current_user), session: AsyncSession = Depends(deps.get_session), ): """Update a slot from the project""" slot = await session.get(Slot, slot_id) if (slot is None) or slot.project_id != id: raise HTTPException(status_code=404, detail="Slot not found") input_dict = new_slot.dict() if input_dict["volunteers"] is not None: volunteers: list[UUID] = input_dict["volunteers"] await verify_id_list( session, volunteers, id, Volunteer, "Invalid volunteer list" ) await session.execute( association_table_volunteer_slot.delete().where( association_table_volunteer_slot.c.slot_id == slot.id ) ) await session.execute( association_table_volunteer_slot.insert().values( [(volunteer_id, slot.id) for volunteer_id in volunteers] ) ) del input_dict["volunteers"] update_object_from_payload(slot, input_dict) await session.commit() await session.refresh(slot) return slot @router.delete("/project/{id}/slot/{slot_id}") async def delete_slot( id: UUID, slot_id: UUID, current_user: User = Depends(deps.get_current_user), session: AsyncSession = Depends(deps.get_session), ): """Delete a slot from the project""" await session.execute( delete(Slot).where((Slot.id == slot_id) & (Slot.project_id == id)) ) await session.commit()