from uuid import UUID from fastapi import APIRouter, Depends, HTTPException from sqlalchemy import delete, select from sqlalchemy.orm import Session from app.api import deps from app.api.utils import update_object_from_payload, verify_id_list from app.models import ( Project, Slot, SlotTemplate, User, Volunteer, association_table_volunteer_slot, ) from app.schemas.requests import ( SlotCreateRequest, SlotUpdateRequest, ) from app.schemas.responses import SlotResponse router = APIRouter(prefix="/project/{project_id}", tags=["project"]) @router.get("/slots", response_model=list[SlotResponse]) async def list_project_slots( project_id: UUID, current_user: User = Depends(deps.get_current_user), session: Session = Depends(deps.get_session), ): """List slots from project""" p = session.get(Project, project_id) if p is None: raise HTTPException(status_code=404, detail="Project not found") results = session.execute(select(Slot).where(Slot.project_id == project_id)) return results.scalars().all() @router.post("/slot", response_model=SlotResponse) async def create_slot( project_id: UUID, new_slot: SlotCreateRequest, current_user: User = Depends(deps.get_current_user), session: Session = Depends(deps.get_session), ): """Create a new slot to the project""" p = session.get(Project, project_id) if p is None: raise HTTPException(status_code=404, detail="Project not found") input_dict = new_slot.model_dump() # 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, project_id, Volunteer, "Invalid volunteer list") del input_dict["volunteers"] slot = Slot(project_id=project_id, **input_dict) session.add(slot) session.commit() # Add the slot to the list of volunteer if len(volunteers) > 0: session.execute( association_table_volunteer_slot.insert().values( [(volunteer_id, slot.id) for volunteer_id in volunteers] ) ) session.commit() return slot @router.post("/slot/{slot_id}", response_model=SlotResponse) async def update_slot( project_id: UUID, slot_id: UUID, new_slot: SlotUpdateRequest, current_user: User = Depends(deps.get_current_user), session: Session = Depends(deps.get_session), ): """Update a slot from the project""" slot = session.get(Slot, slot_id) if (slot is None) or (slot.project_id != str(project_id)): raise HTTPException(status_code=404, detail="Slot not found : ") if new_slot.template_id is not None: if new_slot.template_id != "": await verify_id_list( session, [new_slot.template_id], project_id, SlotTemplate, "Invalid template id", ) input_dict = new_slot.model_dump(exclude_unset=True) if "volunteers" in input_dict: volunteers: list[UUID] = input_dict["volunteers"] await verify_id_list(session, volunteers, project_id, Volunteer, "Invalid volunteer list") session.execute( association_table_volunteer_slot.delete().where( association_table_volunteer_slot.c.slot_id == slot.id ) ) if len(volunteers) > 0: session.execute( association_table_volunteer_slot.insert().values( [(volunteer_id, slot.id) for volunteer_id in volunteers] ) ) del input_dict["volunteers"] if "template_id" in input_dict and input_dict["template_id"] == "": slot.template_id = None del input_dict["template_id"] update_object_from_payload(slot, input_dict) session.commit() session.refresh(slot) return slot @router.delete("/slot/{slot_id}") async def delete_slot( project_id: UUID, slot_id: UUID, current_user: User = Depends(deps.get_current_user), session: Session = Depends(deps.get_session), ): """Delete a slot from the project""" session.execute(delete(Slot).where((Slot.id == slot_id) & (Slot.project_id == project_id))) session.commit()