"""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_ENTITY, 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_ENTITY, 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]