3.1 KiB
TODO — Fix GET /api/planned-days 405 (planned-days router is incomplete)
Status: open · Area: backend · Owner: unassigned · Filed: 2026-06-14
Symptom
Loading the Dashboard and adding a day in the Calendar both log:
"GET /api/planned-days?child_id=3b9b6dad-... HTTP/1.1" 405 Method Not Allowed
Adding a day works (POST /api/planned-days → 201), but the follow-up refresh
(GET /api/planned-days?child_id=…) is rejected, so the calendar/dashboard never
show planned days.
Root cause
backend/app/routers/planned_days.py defines POST "" but no GET "". FastAPI
returns 405 (not 404) because the path exists for another verb. The list-by-child
endpoint was never finished — the GET /range handler (lines ~65–78) is a dead stub
(pass body, = None defaults on its service/_current_user deps) and /range
also collides with GET /{planned_leave_day_id}.
Same router has a second gap: api.updatePlannedDay issues PUT /api/planned-days/{id}
(used by Calendar edit, frontend/src/pages/Calendar.tsx:99), but there is no PUT
handler and no PlanningService.update. Editing an existing day will 405 once adding works.
Fix
In backend/app/services/planning_service.py:
- Add
list_by_child:(The SQLiteasync def list_by_child(self, child_id: UUID) -> list[PlannedLeaveDay]: return await self._repo.list(child_id=child_id)list()already filters onchild_idalone.) - Add
update(self, planned_leave_day_id: UUID, day_type: str | None, is_dubbeldag: bool | None) -> PlannedLeaveDay— load viaget_by_id(raiseNotFoundErrorif missing), apply provided fields, callrepo.update.
In backend/app/routers/planned_days.py:
- Add the list route before
GET /{planned_leave_day_id}:@router.get("", response_model=list[PlannedLeaveDayResponse]) async def list_planned_days( service: PlanningServiceDep, _current_user: CurrentUserDep, child_id: UUID = Query(...), ) -> list[PlannedLeaveDayResponse]: return [_to_response(d) for d in await service.list_by_child(child_id)] - Delete the dead
GET /rangestub (lines ~65–78). - Add the
PUT /{planned_leave_day_id}handler using the existingPlannedLeaveDayUpdatemodel →service.update(...)→_to_response.
Route ordering matters: declare
"",/workspace/..., then/{planned_leave_day_id}last, so the UUID catch-all doesn't swallow the others.
Verification
From backend/:
uv run ruff check . && uv run ruff format --check . && uv run pytest
Add tests:
GET /api/planned-days?child_id=…→ 200 with the seeded rows for that child.PUT /api/planned-days/{id}→ 200, fields updated; unknown id → 404.
Manual: add a vacation day in the Calendar → POST 201 then GET 200 and the list
refreshes; edit an existing day → PUT succeeds.
After code changes: graphify update .
Related
The 405 only blocks the planned-days list. The dashboard's empty metrics /
parental-leave breakdown is a separate snake_case↔camelCase issue —
see DASHBOARD_EMPTY_DATA_TODO.md.