# Аналитика

`/admin/shop/analytics` — KPI и графики продаж.

## Период

Переключатель: **7 / 30 / 90 дней**. Активный период передаётся через `?range=7|30|90`. По умолчанию 30 дней.

## KPI-карточки сверху

| Метрика | Что считается |
|---|---|
| **Выручка** | Сумма `total` всех заказов в периоде, исключая `cancelled`. Подзаголовок — выручка сегодня. |
| **Заказы** | Кол-во заказов в периоде (без cancelled). Подзаголовок — заказов сегодня. |
| **Средний чек** | `revenue / orders` (если есть заказы) |
| **Клиенты** | Уникальные `customer_email` за период |

## Сводка каталога

Не зависит от периода — текущее состояние:

- Товаров в каталоге всего
- Не в наличии (`stock = 0`)
- Заказов «новых» (требуют действий)
- Отзывов всего

## График по дням

Бар-чарт за выбранный период. Высота столбика = `revenue / max(revenue) * 100%`. Tooltip: дата, кол-во сделок, сумма.

Для пустых дней — нулевой бар. Если за весь период продаж не было — empty-state с подсказкой увеличить период или дождаться первой сделки.

## Топ-5 товаров по выручке

JOIN'ом `shop_order_items × shop_orders` за период с GROUP BY товаров. Ссылка «все товары →» на `/admin/shop/products`. Каждая строка: позиция (1–5), название, сумма продаж, количество.

## По статусам

Разбивка заказов периода по `status` (включая `cancelled` — здесь интересно общее количество). Используется для понимания воронки: сколько в `new`, сколько уже `paid` и т.д.

## Архитектура

Все запросы — один проход GROUP BY вместо N+1, что важно при большой базе. `AnalyticsAdminController::index()` собирает все данные в одном вызове, передаёт в шаблон через `$this->view(...)`. Графики строятся CSS-блоками без JS-библиотек — никаких внешних зависимостей.
