104 lines
3.2 KiB
Python
104 lines
3.2 KiB
Python
from datetime import datetime, time, timedelta
|
|
from typing import List, Optional
|
|
from fastapi import APIRouter, Depends, HTTPException, status
|
|
from sqlmodel.ext.asyncio.session import AsyncSession
|
|
from app.database import get_session
|
|
from app.crud import get_sessions, end_sleep_session
|
|
from app.schemas import (
|
|
SessionListResponse,
|
|
SleepSessionUpdate,
|
|
SleepSessionRead,
|
|
SleepSessionCreate,
|
|
)
|
|
|
|
|
|
router = APIRouter(prefix="/api/sessions", tags=["sessions"])
|
|
|
|
|
|
@router.post("", response_model=SleepSessionRead, status_code=status.HTTP_201_CREATED)
|
|
async def create_session(
|
|
payload: SleepSessionCreate, session: AsyncSession = Depends(get_session)
|
|
):
|
|
from app.crud import get_active_session, create_sleep_session
|
|
|
|
active = await get_active_session(session)
|
|
if active:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_409_CONFLICT,
|
|
detail="An active sleep session is already open.",
|
|
)
|
|
|
|
return await create_sleep_session(session, payload.start_time)
|
|
|
|
|
|
@router.get("/active")
|
|
async def read_active_session(session: AsyncSession = Depends(get_session)):
|
|
from app.crud import get_active_session
|
|
|
|
active = await get_active_session(session)
|
|
return await get_active_session(session)
|
|
|
|
|
|
@router.get("", response_model=SessionListResponse)
|
|
async def list_sessions(
|
|
from_date: Optional[datetime] = None,
|
|
to_date: Optional[datetime] = None,
|
|
limit: int = 200,
|
|
session: AsyncSession = Depends(get_session),
|
|
):
|
|
sessions, total = await get_sessions(session, from_date, to_date, limit)
|
|
return {"sessions": sessions, "total": total}
|
|
|
|
|
|
@router.patch("/{session_id}/end", response_model=None)
|
|
async def end_session_endpoint(
|
|
session_id: int,
|
|
payload: SleepSessionUpdate,
|
|
session: AsyncSession = Depends(get_session),
|
|
):
|
|
if not payload.end_time:
|
|
raise HTTPException(
|
|
status_code=400, detail="end_time is required to end a session."
|
|
)
|
|
|
|
result = await end_sleep_session(session, session_id, payload.end_time)
|
|
|
|
if result is None:
|
|
raise HTTPException(status_code=404, detail="Session not found.")
|
|
if result is False:
|
|
raise HTTPException(status_code=409, detail="Session has already ended.")
|
|
if result == "invalid":
|
|
raise HTTPException(
|
|
status_code=400, detail="end_time cannot be before start_time."
|
|
)
|
|
|
|
return result
|
|
|
|
|
|
@router.delete("/{session_id}", status_code=status.HTTP_204_NO_CONTENT)
|
|
async def delete_session_endpoint(
|
|
session_id: int, session: AsyncSession = Depends(get_session)
|
|
):
|
|
from app.crud import delete_session
|
|
|
|
success = await delete_session(session, session_id)
|
|
if not success:
|
|
raise HTTPException(status_code=404, detail="Session not found.")
|
|
return None
|
|
|
|
|
|
@router.patch("/{session_id}", response_model=SleepSessionRead)
|
|
async def update_session_endpoint(
|
|
session_id: int,
|
|
payload: SleepSessionUpdate,
|
|
session: AsyncSession = Depends(get_session),
|
|
):
|
|
from app.crud import update_session
|
|
|
|
updated = await update_session(
|
|
session, session_id, payload.model_dump(exclude_unset=True)
|
|
)
|
|
if not updated:
|
|
raise HTTPException(status_code=404, detail="Session not found.")
|
|
return updated
|