slots.py 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. from uuid import UUID
  2. from fastapi import APIRouter, Depends, HTTPException
  3. from sqlalchemy import delete, select
  4. from sqlalchemy.orm import Session
  5. from app.api import deps
  6. from app.api.utils import assert_project_exists, update_object_from_payload, verify_id_list
  7. from app.models import (
  8. Slot,
  9. SlotTemplate,
  10. User,
  11. Volunteer,
  12. association_table_volunteer_slot,
  13. )
  14. from app.schemas.requests import (
  15. SlotCreateRequest,
  16. SlotUpdateRequest,
  17. )
  18. from app.schemas.responses import SlotResponse
  19. router = APIRouter(prefix="/project/{project_id}", tags=["project"])
  20. def assert_template_from_commission(
  21. session: Session, current_user: User, project_id: UUID, template_id: UUID
  22. ):
  23. template_row = session.execute(
  24. select(SlotTemplate.commission_id, SlotTemplate.project_id).where(
  25. SlotTemplate.id == template_id
  26. )
  27. ).first()
  28. if template_row is None or template_row[1] != str(project_id):
  29. raise HTTPException(400, "Invalid template id")
  30. deps.assert_commission_ownership(session, current_user, project_id, template_row[0])
  31. @router.get("/slots", response_model=list[SlotResponse])
  32. async def list_project_slots(
  33. project_id: UUID,
  34. current_user: User = Depends(deps.get_current_user),
  35. session: Session = Depends(deps.get_session),
  36. ):
  37. """List slots from project"""
  38. assert_project_exists(session, project_id)
  39. results = session.execute(select(Slot).where(Slot.project_id == project_id))
  40. return results.scalars().all()
  41. @router.post("/slot", response_model=SlotResponse)
  42. async def create_slot(
  43. project_id: UUID,
  44. new_slot: SlotCreateRequest,
  45. current_user: User = Depends(deps.get_current_user),
  46. session: Session = Depends(deps.get_session),
  47. ):
  48. """Create a new slot to the project"""
  49. assert_project_exists(session, project_id)
  50. if new_slot.template_id:
  51. assert_template_from_commission(session, current_user, project_id, new_slot.template_id)
  52. input_dict = new_slot.model_dump()
  53. # Extract volunteer list from input dict
  54. volunteers: list[UUID] = []
  55. if input_dict["volunteers"] is not None:
  56. volunteers = input_dict["volunteers"]
  57. await verify_id_list(session, volunteers, project_id, Volunteer, "Invalid volunteer list")
  58. del input_dict["volunteers"]
  59. slot = Slot(project_id=project_id, **input_dict)
  60. session.add(slot)
  61. session.commit()
  62. # Add the slot to the list of volunteer
  63. if len(volunteers) > 0:
  64. session.execute(
  65. association_table_volunteer_slot.insert().values(
  66. [(volunteer_id, slot.id) for volunteer_id in volunteers]
  67. )
  68. )
  69. session.commit()
  70. return slot
  71. @router.post("/slot/{slot_id}", response_model=SlotResponse)
  72. async def update_slot(
  73. project_id: UUID,
  74. slot_id: UUID,
  75. new_slot: SlotUpdateRequest,
  76. current_user: User = Depends(deps.get_current_user),
  77. session: Session = Depends(deps.get_session),
  78. ):
  79. """Update a slot from the project"""
  80. slot = session.get(Slot, slot_id)
  81. if (slot is None) or (slot.project_id != str(project_id)):
  82. raise HTTPException(status_code=404, detail="Slot not found : ")
  83. if new_slot.template_id:
  84. assert_template_from_commission(session, current_user, project_id, new_slot.template_id)
  85. if slot.template_id is not None:
  86. assert_template_from_commission(session, current_user, project_id, slot.template_id)
  87. input_dict = new_slot.model_dump(exclude_unset=True)
  88. if "volunteers" in input_dict:
  89. volunteers: list[UUID] = input_dict["volunteers"]
  90. await verify_id_list(session, volunteers, project_id, Volunteer, "Invalid volunteer list")
  91. session.execute(
  92. association_table_volunteer_slot.delete().where(
  93. association_table_volunteer_slot.c.slot_id == slot.id
  94. )
  95. )
  96. if len(volunteers) > 0:
  97. session.execute(
  98. association_table_volunteer_slot.insert().values(
  99. [(volunteer_id, slot.id) for volunteer_id in volunteers]
  100. )
  101. )
  102. del input_dict["volunteers"]
  103. if "template_id" in input_dict and input_dict["template_id"] == "":
  104. slot.template_id = None
  105. del input_dict["template_id"]
  106. update_object_from_payload(slot, input_dict)
  107. session.commit()
  108. session.refresh(slot)
  109. return slot
  110. @router.delete("/slot/{slot_id}")
  111. async def delete_slot(
  112. project_id: UUID,
  113. slot_id: UUID,
  114. current_user: User = Depends(deps.get_current_user),
  115. session: Session = Depends(deps.get_session),
  116. ):
  117. """Delete a slot from the project"""
  118. result = session.execute(
  119. select(Slot.id, Slot.template_id).where(Slot.id == slot_id, Slot.project_id == project_id)
  120. ).first()
  121. if result is None:
  122. raise HTTPException(status_code=404, detail="Slot not found")
  123. if result[1] is not None:
  124. assert_template_from_commission(session, current_user, project_id, result[1])
  125. session.execute(delete(Slot).where(Slot.id == slot_id))
  126. session.commit()