Styling fix and scraper bug fix
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
# 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`:
|
||||
|
||||
1. Add `list_by_child`:
|
||||
```python
|
||||
async def list_by_child(self, child_id: UUID) -> list[PlannedLeaveDay]:
|
||||
return await self._repo.list(child_id=child_id)
|
||||
```
|
||||
(The SQLite `list()` already filters on `child_id` alone.)
|
||||
2. Add `update(self, planned_leave_day_id: UUID, day_type: str | None, is_dubbeldag: bool | None) -> PlannedLeaveDay`
|
||||
— load via `get_by_id` (raise `NotFoundError` if missing), apply provided fields, call `repo.update`.
|
||||
|
||||
In `backend/app/routers/planned_days.py`:
|
||||
|
||||
3. Add the list route **before** `GET /{planned_leave_day_id}`:
|
||||
```python
|
||||
@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)]
|
||||
```
|
||||
4. Delete the dead `GET /range` stub (lines ~65–78).
|
||||
5. Add the `PUT /{planned_leave_day_id}` handler using the existing
|
||||
`PlannedLeaveDayUpdate` model → `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/`:
|
||||
|
||||
```bash
|
||||
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`.
|
||||
Reference in New Issue
Block a user