185 lines
6.7 KiB
Markdown
185 lines
6.7 KiB
Markdown
# Задачи (SprintTask, TeamTask)
|
||
|
||
← [Сводка API](README.md)
|
||
|
||
Сущность **SprintTask** — задача, закрытая в [спринте](sprints.md). Содержит метрики по отдельной задаче.
|
||
|
||
Сущность **TeamTask** — расширение `SprintTask` с информацией о спринте. Используется в списке всех задач [команды](teams.md).
|
||
|
||
## Связанные сущности
|
||
|
||
- [Команды](teams.md) — список всех задач команды: `GET /api/teams/{teamId}/tasks`
|
||
- [Спринты](sprints.md) — родительская сущность (`sprint_id` в БД; в ответе `GET /api/sprints/{sprintId}/tasks` не возвращается)
|
||
- [Конфигурация](config.md) — `jira_url` для формирования ссылки на задачу в Jira
|
||
|
||
---
|
||
|
||
## Модель данных
|
||
|
||
### SprintTask
|
||
|
||
```json
|
||
{
|
||
"id": 101,
|
||
"task_type": "backend",
|
||
"task_key": "TS-1234",
|
||
"task_title": "Пример задачи",
|
||
"employee_name": "Иван Иванов",
|
||
"employee_role": "backend",
|
||
"estimate_seconds": 28800,
|
||
"total_time_seconds": 32400,
|
||
"take_in_work_datetime": "2026-01-14 10:00:00+04",
|
||
"resolution_datetime": "2026-01-20 16:30:00+04",
|
||
"lead_time_days": 5,
|
||
"recast_percentage": 12.5,
|
||
"efficiency_percentage": 45.0,
|
||
"review_count": 2,
|
||
"test_count": 1
|
||
}
|
||
```
|
||
|
||
| Поле | Тип | Описание |
|
||
|------|-----|----------|
|
||
| `id` | `integer` | Идентификатор записи в БД |
|
||
| `task_type` | `string` | Тип задачи |
|
||
| `task_key` | `string` | Ключ задачи в Jira |
|
||
| `task_title` | `string` | Заголовок задачи |
|
||
| `employee_name` | `string \| null` | ФИО исполнителя |
|
||
| `employee_role` | `string \| null` | Роль исполнителя |
|
||
| `estimate_seconds` | `integer` | Оценка в секундах |
|
||
| `total_time_seconds` | `integer` | Фактически затраченное время в секундах |
|
||
| `take_in_work_datetime` | `string \| null` | Дата и время взятия в работу |
|
||
| `resolution_datetime` | `string \| null` | Дата и время закрытия |
|
||
| `lead_time_days` | `integer \| null` | System Lead Time в рабочих днях |
|
||
| `recast_percentage` | `number \| null` | Переработка относительно оценки, % |
|
||
| `efficiency_percentage` | `number \| null` | КПД (Flow Efficiency), % |
|
||
| `review_count` | `integer` | Количество заходов на ревью |
|
||
| `test_count` | `integer` | Количество заходов на тестирование |
|
||
|
||
### Роли исполнителей (`employee_role`)
|
||
|
||
`analytic`, `backend`, `designer`, `frontend`, `qa`, `project`
|
||
|
||
### Ссылка на задачу в Jira
|
||
|
||
```
|
||
{jira_url}/browse/{task_key}
|
||
```
|
||
|
||
`jira_url` получается из [конфигурации](config.md): `GET /api/config`.
|
||
|
||
### TeamTask
|
||
|
||
Расширяет `SprintTask` полями спринта:
|
||
|
||
```json
|
||
{
|
||
"id": 101,
|
||
"task_type": "backend",
|
||
"task_key": "TS-1234",
|
||
"task_title": "Пример задачи",
|
||
"employee_name": "Иван Иванов",
|
||
"employee_role": "backend",
|
||
"estimate_seconds": 28800,
|
||
"total_time_seconds": 32400,
|
||
"take_in_work_datetime": "2026-01-14 10:00:00+04",
|
||
"resolution_datetime": "2026-01-20 16:30:00+04",
|
||
"lead_time_days": 5,
|
||
"recast_percentage": 12.5,
|
||
"efficiency_percentage": 45.0,
|
||
"review_count": 2,
|
||
"test_count": 1,
|
||
"sprint_id": 42,
|
||
"sprint_name": "TS 2026_1 до 26.01"
|
||
}
|
||
```
|
||
|
||
| Поле | Тип | Описание |
|
||
|------|-----|----------|
|
||
| `sprint_id` | `integer` | Идентификатор [спринта](sprints.md) |
|
||
| `sprint_name` | `string` | Название спринта |
|
||
|
||
Остальные поля совпадают с [SprintTask](#sprinttask).
|
||
|
||
### PaginatedTeamTasks
|
||
|
||
Ответ эндпоинта `GET /api/teams/{teamId}/tasks`:
|
||
|
||
```json
|
||
{
|
||
"team_id": 1,
|
||
"team_name": "ts",
|
||
"items": [],
|
||
"page": 1,
|
||
"per_page": 50,
|
||
"total": 128,
|
||
"total_pages": 3
|
||
}
|
||
```
|
||
|
||
| Поле | Тип | Описание |
|
||
|------|-----|----------|
|
||
| `team_id` | `integer` | Идентификатор [команды](teams.md) |
|
||
| `team_name` | `string` | Название команды |
|
||
| `items` | `TeamTask[]` | Задачи на текущей странице |
|
||
| `page` | `integer` | Номер текущей страницы (начиная с 1) |
|
||
| `per_page` | `integer` | Размер страницы |
|
||
| `total` | `integer` | Общее количество задач команды |
|
||
| `total_pages` | `integer` | Общее количество страниц |
|
||
|
||
---
|
||
|
||
## Эндпоинты
|
||
|
||
### `GET /api/teams/{teamId}/tasks`
|
||
|
||
Возвращает все задачи [команды](teams.md) из всех её [спринтов](sprints.md) с пагинацией.
|
||
|
||
**Параметры пути**
|
||
|
||
| Параметр | Тип | Описание |
|
||
|----------|-----|----------|
|
||
| `teamId` | `integer` | Идентификатор команды |
|
||
|
||
**Query-параметры**
|
||
|
||
| Параметр | Тип | По умолчанию | Описание |
|
||
|----------|-----|--------------|----------|
|
||
| `page` | `integer` | `1` | Номер страницы (минимум 1) |
|
||
| `per_page` | `integer` | `50` | Количество задач на странице (1–100) |
|
||
|
||
**Ответ:** `200` — объект `PaginatedTeamTasks`
|
||
|
||
Задачи отсортированы по дате закрытия (новые первыми), затем по ключу задачи. В выборку попадают только задачи, привязанные к спринтам команды (`tasks.sprint_id` → `sprints.team_id`).
|
||
|
||
Если запрошенная страница больше `total_pages`, сервер возвращает последнюю доступную страницу.
|
||
|
||
**Ошибки:** `404` — команда не найдена
|
||
|
||
**Примеры**
|
||
|
||
```bash
|
||
curl http://localhost/api/teams/1/tasks
|
||
curl "http://localhost/api/teams/1/tasks?page=2&per_page=50"
|
||
```
|
||
|
||
---
|
||
|
||
### `GET /api/sprints/{sprintId}/tasks`
|
||
|
||
Возвращает [задачи](tasks.md), закрытые в указанном [спринте](sprints.md).
|
||
|
||
**Параметры пути**
|
||
|
||
| Параметр | Тип | Описание |
|
||
|----------|-----|----------|
|
||
| `sprintId` | `integer` | Идентификатор спринта |
|
||
|
||
**Ответ:** `200` — массив `SprintTask[]`, отсортированный по дате закрытия (от старых к новым), затем по ключу задачи
|
||
|
||
**Пример**
|
||
|
||
```bash
|
||
curl http://localhost/api/sprints/42/tasks
|
||
```
|