41 lines
2.0 KiB
Markdown
41 lines
2.0 KiB
Markdown
# Спецификация: `GET /api/v1/workouts` и `GET /api/v1/workouts/{id}` (единицы 4–5)
|
||
|
||
## `GET /api/v1/workouts` — список с пагинацией
|
||
|
||
Запрос: `?limit=` (1–100, умолчание 20), `?offset=` (≥ 0, умолчание 0);
|
||
вне диапазона — `400`.
|
||
|
||
Ответ `200`:
|
||
|
||
```json
|
||
{ "items": [ { "workout_id": "uuid", "started_at": "...", "ended_at": "...",
|
||
"status": "finished", "session_kind": "normal", "avg_hr": 132,
|
||
"sets": [ { "set_id": "uuid", "exercise_id": "uuid", "seq": 1,
|
||
"weight_kg": 60.0, "reps": 10, "rpe": 8, "knee_pain": null } ] } ],
|
||
"total": 42 }
|
||
```
|
||
|
||
Реализация — `WorkoutRepository.Select` (`workout_select`: карточки +
|
||
подходы агрегатом); `total` — COUNT по фильтру (без пагинации).
|
||
Примечание (З-40): пагинация — в памяти (выборка атлета целиком,
|
||
`limit`/`offset` режут результат) — известное ограничение v1.
|
||
|
||
Тесты: 1) список только этого атлета (🛡 — второй атлет не виден);
|
||
2) `limit`/`offset` режут выборку корректно; 3) `limit = 0` / `limit = 101` → 400.
|
||
|
||
## `GET /api/v1/workouts/{id}` — карточка
|
||
|
||
Ответ `200` — полная карточка (поля карточки + `sets[]` + `command_log[]`
|
||
с `t_offset_s`, `recognized_text`, `semantics`, `accepted`).
|
||
|
||
| Код | Когда |
|
||
|---|---|
|
||
| 404 | тренировка не найдена **или** принадлежит другому атлету (🛡 различие не выдаётся) |
|
||
| 400 | `{id}` — не UUID |
|
||
|
||
Реализация — `WorkoutRepository.Get` (`workout_get`: карточка + sets +
|
||
command_log) с проверкой `athlete_id`.
|
||
|
||
Тесты: 1) своя тренировка → 200 с sets и command_log;
|
||
2) чужая тренировка → 404; 3) не-UUID id → 400.
|