volunteers.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. from uuid import UUID
  2. from fastapi import APIRouter, Depends, HTTPException
  3. from sqlalchemy import delete, select
  4. from sqlalchemy.ext.asyncio import AsyncSession
  5. from sqlalchemy.sql import func
  6. from app.api import deps
  7. from app.api.utils import update_object_from_payload, verify_id_list
  8. from app.models import Project, Slot, User, Volunteer, association_table_volunteer_slot
  9. from app.schemas.requests import VolunteerCreateRequest, VolunteerUpdateRequest
  10. from app.schemas.responses import VolunteerResponse
  11. router = APIRouter()
  12. @router.get("/project/{id}/volunteers", response_model=list[VolunteerResponse])
  13. async def list_project_volunteers(
  14. id: UUID,
  15. current_user: User = Depends(deps.get_current_user),
  16. session: AsyncSession = Depends(deps.get_session),
  17. ):
  18. """List volunteers from project"""
  19. p = await session.get(Project, id)
  20. if p is None:
  21. raise HTTPException(status_code=404, detail="Project not found")
  22. results = await session.execute(select(Volunteer).where(Volunteer.project_id == id))
  23. return results.scalars()
  24. @router.post("/project/{id}/volunteer", response_model=VolunteerResponse)
  25. async def create_volunteer(
  26. id: UUID,
  27. new_volunteer: VolunteerCreateRequest,
  28. current_user: User = Depends(deps.get_current_user),
  29. session: AsyncSession = Depends(deps.get_session),
  30. ):
  31. """Create a new volunteer to the project"""
  32. p = await session.get(Project, id)
  33. if p is None:
  34. raise HTTPException(status_code=404, detail="Project not found")
  35. input_dict = new_volunteer.dict()
  36. # Extract slots list from input dict
  37. slots: list[UUID] = []
  38. if input_dict["slots"] is not None:
  39. slots = input_dict["slots"]
  40. await verify_id_list(session, slots, id, Slot, "Invalid slot list")
  41. del input_dict["slots"]
  42. volunteer = Volunteer(project_id=id, **input_dict)
  43. session.add(volunteer)
  44. # commit to optain an id for the volunteer
  45. await session.commit()
  46. await session.execute(
  47. association_table_volunteer_slot.insert().values(
  48. [(volunteer.id, slot_id) for slot_id in slots]
  49. )
  50. )
  51. await session.commit()
  52. return volunteer
  53. @router.post(
  54. "/project/{project_id}/volunteer/{volunteer_id}", response_model=VolunteerResponse
  55. )
  56. async def update_volunteer(
  57. project_id: UUID,
  58. volunteer_id: UUID,
  59. new_volunteer: VolunteerUpdateRequest,
  60. current_user: User = Depends(deps.get_current_user),
  61. session: AsyncSession = Depends(deps.get_session),
  62. ):
  63. """Update a volunteer from the project"""
  64. volunteer = await session.get(Volunteer, volunteer_id)
  65. if (volunteer is None) or (volunteer.project_id != project_id):
  66. raise HTTPException(status_code=404, detail="Volunteer not found")
  67. input_dict = new_volunteer.dict()
  68. # Extract slots list from input dict
  69. if input_dict["slots"] is not None:
  70. slots: list[UUID] = input_dict["slots"]
  71. await verify_id_list(session, slots, project_id, Slot, "Invalid slot list")
  72. # Remove previous values
  73. await session.execute(
  74. association_table_volunteer_slot.delete().where(
  75. association_table_volunteer_slot.c.volunteer_id == volunteer.id
  76. )
  77. )
  78. # Add the new
  79. await session.execute(
  80. association_table_volunteer_slot.insert().values(
  81. [(volunteer.id, slot_id) for slot_id in slots]
  82. )
  83. )
  84. del input_dict["slots"]
  85. update_object_from_payload(volunteer, input_dict)
  86. await session.commit()
  87. await session.refresh(volunteer)
  88. return volunteer
  89. @router.delete("/project/{project_id}/volunteer/{volunteer_id}")
  90. async def delete_volunteer(
  91. project_id: UUID,
  92. volunteer_id: UUID,
  93. current_user: User = Depends(deps.get_current_user),
  94. session: AsyncSession = Depends(deps.get_session),
  95. ):
  96. """Delete a volunteer from the project"""
  97. await session.execute(
  98. delete(Volunteer).where(
  99. (Volunteer.id == volunteer_id) & (Volunteer.project_id == project_id)
  100. )
  101. )
  102. await session.commit()