Files
F-r-ldraledigplannerare/backend/app/routers/preschool_planning_days.py
T
jacobh2 64734ae6e7 Silence the deprecation warnings our own code raises
Starlette renamed HTTP_422_UNPROCESSABLE_ENTITY to HTTP_422_UNPROCESSABLE_CONTENT
and now warns on the old spelling; the value is unchanged at 422, so the 20 call
sites in the routers move over with no wire-format or frontend impact.

Alembic >=1.16 supersedes version_path_separator with path_separator, which
governs both prepend_sys_path and version_locations, and warns when it is absent.

Together this takes pytest from 26 deprecation warnings to 6. The remainder are
slowapi calling asyncio.iscoroutinefunction; they are left visible deliberately,
with no filterwarnings entry, as a reminder to revisit once upstream ships a fix.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-20 18:48:02 +02:00

78 lines
2.8 KiB
Python

"""HTTP routes for preschool planning ("studiedagar") days per year.
Routers stay thin: validate via Pydantic, call the service, map domain
errors to HTTP. Scoped per child via `WorkspaceScope.check_child`, which
404s (never 403) on a missing or foreign-workspace child id.
"""
from uuid import UUID
from fastapi import APIRouter, HTTPException, status
from app.dependencies import PreschoolPlanningDaysServiceDep, WorkspaceScopeDep
from app.models.preschool_planning_days import (
PreschoolPlanningDaysPlannedUpdate,
PreschoolPlanningDaysResponse,
PreschoolPlanningDaysTakenUpdate,
)
from app.utils.errors import ValidationError
router = APIRouter(prefix="/api/preschool-planning-days", tags=["preschool-planning-days"])
@router.put("/{child_id}/{year}/planned", response_model=PreschoolPlanningDaysResponse)
async def upsert_planned_days(
child_id: UUID,
year: int,
payload: PreschoolPlanningDaysPlannedUpdate,
service: PreschoolPlanningDaysServiceDep,
scope: WorkspaceScopeDep,
) -> PreschoolPlanningDaysResponse:
child = await scope.check_child(child_id)
try:
entity = await service.upsert_planned(child, year, payload.planned_days)
except ValidationError as exc:
raise HTTPException(status.HTTP_422_UNPROCESSABLE_CONTENT, str(exc)) from exc
return PreschoolPlanningDaysResponse.from_entity(entity)
@router.put("/{child_id}/{year}/taken", response_model=PreschoolPlanningDaysResponse)
async def record_taken_days(
child_id: UUID,
year: int,
payload: PreschoolPlanningDaysTakenUpdate,
service: PreschoolPlanningDaysServiceDep,
scope: WorkspaceScopeDep,
) -> PreschoolPlanningDaysResponse:
child = await scope.check_child(child_id)
try:
entity = await service.record_taken(child, year, payload.taken_days)
except ValidationError as exc:
raise HTTPException(status.HTTP_422_UNPROCESSABLE_CONTENT, str(exc)) from exc
return PreschoolPlanningDaysResponse.from_entity(entity)
@router.get("/{child_id}/{year}", response_model=PreschoolPlanningDaysResponse)
async def get_year(
child_id: UUID,
year: int,
service: PreschoolPlanningDaysServiceDep,
scope: WorkspaceScopeDep,
) -> PreschoolPlanningDaysResponse:
child = await scope.check_child(child_id)
entity = await service.get_by_child_year(child_id, year)
if entity is None:
return PreschoolPlanningDaysResponse.default_for(child, year)
return PreschoolPlanningDaysResponse.from_entity(entity)
@router.get("/{child_id}", response_model=list[PreschoolPlanningDaysResponse])
async def list_years(
child_id: UUID,
service: PreschoolPlanningDaysServiceDep,
scope: WorkspaceScopeDep,
) -> list[PreschoolPlanningDaysResponse]:
await scope.check_child(child_id)
entities = await service.list_for_child(child_id)
return [PreschoolPlanningDaysResponse.from_entity(e) for e in entities]