Отчёты по заказам - агрегаты, группировка, выгрузка
Считаем выручку и заказы так, чтобы отчёт открывался за секунду, а не тянул десятки тысяч записей в память ради одной суммы.
Решение
Считаем агрегаты запросом к базе:
use Bitrix\Sale\Internals\OrderTable;
$row = OrderTable::getList([ 'select' => [ 'CNT' => new \Bitrix\Main\Entity\ExpressionField('CNT', 'COUNT(%s)', 'ID'), 'SUMMA' => new \Bitrix\Main\Entity\ExpressionField('SUMMA', 'SUM(%s)', 'PRICE'), ], 'filter' => ['=PAYED' => 'Y', '!=STATUS_ID' => 'CANCELED'],])->fetch();Суммы и количества считает база, а не код на странице. Выборка десяти тысяч заказов ради одной суммы съедает память и время, а тот же результат приходит одной строкой за доли секунды.
Группируем по дням и статусам:
$rows = OrderTable::getList([ 'select' => ['STATUS_ID', 'DAY' => new \Bitrix\Main\Entity\ExpressionField('DAY', 'DATE(%s)', 'DATE_INSERT'), 'SUMMA' => new \Bitrix\Main\Entity\ExpressionField('SUMMA', 'SUM(%s)', 'PRICE')], 'filter' => ['>=DATE_INSERT' => $from], 'group' => ['STATUS_ID', 'DAY'],])->fetchAll();Группировка строк задаётся в самом запросе к базе. Разбивка по дням и статусам приходит уже готовой, и коду остаётся только разложить строки в таблицу для показа.
Убираем из выручки лишнее:
$filter = [ '=PAYED' => 'Y', // считаем оплаченные '!=CANCELED' => 'Y', // без отменённых '!=STATUS_ID' => 'TEST', // и без тестовых, если такой статус есть];// договорённость о том, что считается выручкой, важнее самого запросаДоговорённость о том, что считается выручкой, важнее кода отчёта. Оплаченные, отгруженные и просто оформленные заказы дают три разных числа, и спор о них случается на первой же встрече по отчётам.
Считаем тяжёлый отчёт по расписанию:
// ночью считаем и кладём в свою таблицу, днём показываем готовоеSalesDailyTable::add(['DAY' => $day, 'CNT' => $row['CNT'], 'SUMMA' => $row['SUMMA']]);// отчёт за год по клику в час пик - это минуты нагрузки на базуТяжёлый отчёт считают заранее и показывают уже готовым. Отчёт за год, запускаемый менеджером в час пик, соревнуется за базу с покупателями и обычно выигрывает.
Отчёт стоит начинать с вопроса «какое решение он поменяет». Красивая таблица, на которую никто не смотрит дважды, стоит столько же времени, сколько и полезная, а пользы не приносит вовсе.
Часовой пояс сдвигает границы суток. Отчёт «за вчера», посчитанный по времени сервера, у магазина с покупателями из других часовых поясов расходится с их представлением о вчера на несколько заказов.
Числа отчёта стоит сверять с учётной системой хотя бы раз в месяц. Расхождение, найденное в конце квартала, обходится дороже, чем найденное в тот же день.
Типичные проблемы
Отчёт съедает всю память процесса.
Заказы выбираются в память, а суммы считаются кодом. Агрегаты считает база одним запросом.
Выручка не сходится с учётной системой.
В сумму попали отменённые или неоплаченные заказы. Состав выручки задают фильтром и договорённостью.
Отчёт роняет сайт в час пик.
Тяжёлый запрос запускается по клику менеджера. Такие отчёты считают ночью и хранят готовыми.
Числа за вчера отличаются у менеджеров.
Границы суток считаются в разных часовых поясах. Пояс отчёта фиксируют явно.
Отчёт по свойству заказа работает минуту.
Свойства лежат в отдельной таблице, и отбор по ним требует соединения. Часто используемым полям добавляют указатель.
Частые вопросы
Где хранить посчитанные отчёты?
В своей таблице с разбивкой по дням. Тогда любой период собирается сложением готовых строк.
Как считать средний чек?
Отношением суммы к числу заказов в том же запросе. Считать его по каждому заказу отдельно не нужно.
Нужен ли отдельный интерфейс отчётов?
Если к отчёту возвращаются - да, страницей в административной части. Разовый вопрос закрывает выгрузка в файл.
Что делать с возвратами?
Вычитать их из выручки того периода, когда они случились. Правка задним числом ломает уже сданные отчёты.
Смежное
- Заказы - оглавление подтемы
- Источник заказа: метки в адресе, хранение, отчёт - откуда берутся данные об источнике
- Дата сохранилась не та: разбор причин - почему в отчёт попадает лишний день
- Список заказов из кода: фильтры, постраничность, позиции - выборка заказов без агрегатов
- Свой гаджет рабочего стола: файлы, параметры, вывод - короткая сводка прямо на рабочем столе
- Оплаты и отгрузки заказа: объекты, признаки, частичные операции - что считать оплаченным
- Своя страница в админке: список, форма, пункт меню - куда показывать отчёт
- Каталог и продажи - устройство магазина целиком
- Брошенные корзины: поиск, письмо, чистка старых - что не дошло до заказа
- Онлайн-касса: подключение, состав чека, очередь и ошибки - сверка оплат и чеков
- Даты в коде: объект, часовой пояс, фильтр по периоду - откуда берётся сдвиг суток
- Электронная торговля в аналитике: события, покупка, сверка - с чем сверяют отчёт сервиса