feat: update analytics

This commit is contained in:
ivannoskov
2026-01-12 12:46:29 +03:00
parent 52a4425751
commit 1f36a074af
14 changed files with 1683 additions and 594 deletions

View File

@@ -0,0 +1,183 @@
# Требования к API для аналитики по проектам
## Endpoint
```
GET /api/v1/workspaces/{workspace_id}/analytics/projects
```
## Параметры запроса (Query Parameters)
| Параметр | Тип | Обязательный | Описание |
|----------|-----|-------------|----------|
| `project_ids` | `string[]` | Нет | Массив UUID проектов для фильтрации. Если не указан - все проекты workspace |
| `date_from` | `string (ISO 8601)` | Нет | Начало периода (например: `2024-12-01T00:00:00Z`) |
| `date_to` | `string (ISO 8601)` | Нет | Конец периода (например: `2024-12-31T23:59:59Z`) |
| `grouping` | `enum: "day" \| "week" \| "month" \| "quarter"` | Да | Группировка данных по периодам |
| `date_grouping` | `enum: "purchase_date" \| "link_date" \| "placement_date"` | Да | По какой дате группировать размещения |
| `metrics` | `string[]` | Нет | Массив метрик для расчета. Если не указан - возвращаются все доступные метрики |
### Доступные метрики:
- `total_cost` - Сумма расходов
- `purchases_count` - Количество закупов (размещений)
- `total_subscriptions` - Общее количество подписок
- `total_views` - Общее количество просмотров
- `avg_cpf` - Средний CPF (cost per follower)
- `avg_cpm` - Средний CPM (cost per mille)
- `avg_post_cost` - Средняя стоимость поста
- `clicks_count` - Количество переходов (кликов)
- `reach_volume` - Объем охвата
- `total_discounts` - Сумма скидок
- `avg_discount_percent` - Средний процент скидки
- `avg_conversion` - Средняя конверсия закупов
## Формат ответа
```json
{
"periods": [
{
"period": "2024-12-01",
"period_label": "1 дек",
"metrics": {
"total_cost": 5500.0,
"purchases_count": 3,
"total_subscriptions": 156,
"total_views": 8500,
"avg_cpf": 35.26,
"avg_cpm": 647.06,
"avg_post_cost": 1833.33,
"clicks_count": 156,
"reach_volume": 8500,
"total_discounts": 0.0,
"avg_discount_percent": 0.0,
"avg_conversion": 0.0
}
},
{
"period": "2024-12-02",
"period_label": "2 дек",
"metrics": {
"total_cost": 3200.0,
"purchases_count": 2,
"total_subscriptions": 89,
"total_views": 4200,
"avg_cpf": 35.96,
"avg_cpm": 761.9,
"avg_post_cost": 1600.0,
"clicks_count": 89,
"reach_volume": 4200,
"total_discounts": 0.0,
"avg_discount_percent": 0.0,
"avg_conversion": 0.0
}
}
],
"totals": {
"total_cost": 8700.0,
"purchases_count": 5,
"total_subscriptions": 245,
"total_views": 12700,
"avg_cpf": 35.51,
"avg_cpm": 685.04,
"avg_post_cost": 1740.0,
"clicks_count": 245,
"reach_volume": 12700,
"total_discounts": 0.0,
"avg_discount_percent": 0.0,
"avg_conversion": 0.0
}
}
```
## Примеры запросов
### Пример 1: График расходов по дням за декабрь
```http
GET /api/v1/workspaces/123e4567-e89b-12d3-a456-426614174000/analytics/projects?grouping=day&date_grouping=placement_date&date_from=2024-12-01T00:00:00Z&date_to=2024-12-31T23:59:59Z&metrics[]=total_cost&project_ids[]=proj-001&project_ids[]=proj-002
```
### Пример 2: Средний CPF по неделям
```http
GET /api/v1/workspaces/123e4567-e89b-12d3-a456-426614174000/analytics/projects?grouping=week&date_grouping=placement_date&metrics[]=avg_cpf&metrics[]=total_subscriptions
```
### Пример 3: Все метрики по месяцам
```http
GET /api/v1/workspaces/123e4567-e89b-12d3-a456-426614174000/analytics/projects?grouping=month&date_grouping=purchase_date&date_from=2024-01-01T00:00:00Z&date_to=2024-12-31T23:59:59Z
```
## Формат периода (period)
В зависимости от `grouping`:
- `day`: `"YYYY-MM-DD"` (например: `"2024-12-01"`)
- `week`: `"YYYY-Www"` (например: `"2024-W49"`) - ISO week format
- `month`: `"YYYY-MM"` (например: `"2024-12"`)
- `quarter`: `"YYYY-QN"` (например: `"2024-Q4"`)
## Формат period_label
Человекочитаемая метка периода для отображения на графике:
- `day`: `"1 дек"` или `"1 дек 2024"`
- `week`: `"49 нед. 2024"` или `"1-7 дек"`
- `month`: `"дек 2024"`
- `quarter`: `"Q4 2024"`
## Логика расчета метрик
### Агрегации (SUM):
- `total_cost` - сумма всех `cost`
- `total_subscriptions` - сумма всех `subscriptions_count`
- `total_views` - сумма всех `views_count`
- `total_discounts` - сумма всех скидок
- `clicks_count` - сумма всех кликов
- `reach_volume` - сумма всех просмотров (аналогично `total_views`)
### Счетчики (COUNT):
- `purchases_count` - количество размещений в периоде
### Средние значения (AVG):
- `avg_cpf` = `total_cost / total_subscriptions` (если `total_subscriptions > 0`)
- `avg_cpm` = `(total_cost / total_views) * 1000` (если `total_views > 0`)
- `avg_post_cost` = `total_cost / purchases_count` (если `purchases_count > 0`)
- `avg_discount_percent` = средний процент скидки по размещениям
- `avg_conversion` = средняя конверсия закупов
### Totals (итоговые значения):
Все метрики в `totals` рассчитываются как агрегация по всем периодам в ответе.
## Обработка ошибок
### 400 Bad Request
```json
{
"detail": [
{
"loc": ["query", "grouping"],
"msg": "Invalid grouping value. Must be one of: day, week, month, quarter",
"type": "value_error"
}
]
}
```
### 422 Unprocessable Entity
```json
{
"detail": [
{
"loc": ["query", "date_from"],
"msg": "date_from must be before date_to",
"type": "value_error"
}
]
}
```
## Примечания
- Если для метрики нет данных (например, `total_discounts`), возвращается `0` или `null`
- Если знаменатель равен 0 при расчете средних значений, возвращается `null`
- Периоды сортируются по возрастанию (`period`)
- Если данных нет для какого-то периода, он не включается в ответ (или включается с нулевыми значениями - на усмотрение бэкенда)