from typing import Annotated import datetime from uuid import UUID from fastapi import APIRouter, Depends, HTTPException, Query from sqlalchemy import delete, select from sqlalchemy.orm import Session from app.api import deps from app.api.utils import update_object_from_payload from app.models import ( Project, Sms, User, ) from app.schemas.requests import SmsCreateRequest, SmsUpdateRequest from app.schemas.responses import SMSResponse router = APIRouter() @router.get("/project/{project_id}/sms", response_model=list[SMSResponse]) async def list_project_sms( project_id: UUID, current_user: User = Depends(deps.get_current_user), session: Session = Depends(deps.get_session), ): """List sms 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(Sms).where(Sms.project_id == project_id)) return results.scalars().all() @router.post("/project/{project_id}/sms", response_model=SMSResponse) async def create_sms( project_id: UUID, new_sms: SmsCreateRequest, current_user: User = Depends(deps.get_current_user), session: Session = Depends(deps.get_session), ): """Create a new to the project""" p = session.get(Project, project_id) if p is None: raise HTTPException(status_code=404, detail="Project not found") sms = Sms(project_id=project_id, **new_sms.model_dump()) session.add(sms) session.commit() return sms @router.post("/project/{project_id}/sms/{sms_id}", response_model=SMSResponse) async def update_sms( project_id: UUID, sms_id: UUID, new_sms: SmsUpdateRequest, current_user: User = Depends(deps.get_current_user), session: Session = Depends(deps.get_session), ): """Update an sms from the project""" sms = session.get(Sms, sms_id) if (sms is None) or (sms.project_id != str(project_id)): raise HTTPException(status_code=404, detail="Sms not found") update_object_from_payload(sms, new_sms.model_dump(exclude_unset=True)) session.commit() session.refresh(sms) return sms @router.delete("/project/{project_id}/sms/{sms_id}") async def delete_sms( project_id: UUID, sms_id: UUID, current_user: User = Depends(deps.get_current_user), session: Session = Depends(deps.get_session), ): """Delete a sms from the project""" session.execute(delete(Sms).where((Sms.id == sms_id) & (Sms.project_id == str(project_id)))) session.commit() @router.get("/sms/to-send", response_model=list[SMSResponse]) async def list_sms_to_send( current_user: User = Depends(deps.get_current_user), session: Session = Depends(deps.get_session), max_delay: Annotated[ int | None, Query(description="the maximum delay a sms should be send with") ] = 10, ): """List sms that should be send by now""" now = datetime.datetime.now() min_sending_time = now - datetime.timedelta(minutes=max_delay) results = session.execute( select(Sms).where( (Sms.sending_time > min_sending_time) & (Sms.sending_time < now) & (Sms.send_time == None) # noqa: E711 ) ) return results.scalars().all() @router.post("/sms/send-now/{sms_id}", response_model=SMSResponse) async def send_sms_now( sms_id: UUID, current_user: User = Depends(deps.get_current_user), session: Session = Depends(deps.get_session), ): """Update the SMS to be sent now""" sms = session.get(Sms, sms_id) if sms is None: raise HTTPException(status_code=404, detail="SMS not found") elif sms.send_time is not None: raise HTTPException(status_code=400, detail="SMS has already been sent") else: sms.send_time = datetime.datetime.now() session.commit() return sms @router.get("/sms/not-send", response_model=list[SMSResponse]) async def list_not_sent( current_user: User = Depends(deps.get_current_user), session: Session = Depends(deps.get_session), ): """List sms that are not sent""" results = session.execute(select(Sms).where((Sms.send_time == None))) # noqa: E711 return results.scalars().all() @router.get("/sms/future", response_model=list[SMSResponse]) async def list_future_sms( current_user: User = Depends(deps.get_current_user), session: Session = Depends(deps.get_session), ): """List sms that should be sent in the future""" results = session.execute(select(Sms).where(Sms.sending_time > datetime.datetime.now())) return results.scalars().all()