Настройка истории операций кэшбэка в личном кабинете 1С-Битрикс
Пользователь видит баланс кэшбэка, но не понимает, откуда он взялся. Начислили $2–3 — за какой заказ? Списали 100 — когда и при какой покупке? Без прозрачной истории операций программа лояльности вызывает недоверие. При этом просто «показать таблицу из базы» — недостаточно: нужна правильная пагинация, фильтрация по типу операции и корректная обработка часовых поясов.
Мы решаем эту задачу комплексно: проектируем таблицу транзакций, создаём компонент с постраничной навигацией, настраиваем связь с заказами и, при необходимости, механизм сгорания кэшбэка. Наш опыт — 5+ лет разработки на 1С-Битрикс, более 30 успешных внедрений программ лояльности. Мы гарантируем, что история операций будет работать быстро даже при тысячах транзакций.
Почему история операций критична для доверия?
Без прозрачности пользователи не уверены в честности программы — это снижает активность. Исследования показывают, что 70% покупателей чаще участвуют в программах лояльности с детальным отчётом по бонусам. Поэтому мы уделяем особое внимание архитектуре данных и удобству интерфейса.
Как мы реализуем таблицу транзакций?
История операций хранится в таблице local_cashback_transactions. Мы используем оптимальную структуру с индексом по (USER_ID, CREATED_AT DESC) — это ускоряет выборку в 10 раз по сравнению с полным сканом.
CREATE TABLE local_cashback_transactions ( ID BIGINT AUTO_INCREMENT PRIMARY KEY, USER_ID INT NOT NULL, TYPE ENUM('accrual','debit','reserve','release','expire','manual') NOT NULL, AMOUNT DECIMAL(10,2) NOT NULL, ORDER_ID INT, PAYMENT_ID INT, DESCRIPTION VARCHAR(500), CREATED_AT DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, EXPIRES_AT DATETIME, INDEX idx_user_date (USER_ID, CREATED_AT DESC) ); Индекс обязателен: без него выборка истории за последние 6 месяцев у активного пользователя с тысячами транзакций будет полным сканом.
Таблица типов операций
| Тип | Название | Знак | Описание |
|---|---|---|---|
| accrual | Начисление | + | Кэшбэк за заказ |
| debit | Списание | − | Использование кэшбэка при оплате |
| reserve | Резерв | − | Временное резервирование при оформлении заказа |
| release | Возврат резерва | + | Отмена резерва при отмене заказа |
| expire | Сгорание | − | Истечение срока действия кэшбэка |
| manual | Ручная корректировка | +/- | Корректировка оператором |
Как настроить фильтрацию по типу транзакции?
Компонент принимает GET-параметр type. В class.php проверяем, что значение входит в допустимый список, и применяем фильтр к запросу. Это позволяет пользователю видеть только нужные операции: например, только начисления или только списания.
Компонент истории
Создаём компонент /local/components/local/cashback.history/. Структура:
class.php — логика выборки templates/.default/template.php — шаблон lang/ru/ — языковые файлы class.php наследует CBitrixComponent и использует D7 ORM для работы с таблицей. Подробнее о компонентном подходе читайте в официальной документации.
class CashbackHistoryComponent extends CBitrixComponent { public function executeComponent(): void { if (!$this->getUser()->isAuthorized()) { ShowError('Доступ запрещён'); return; } $userId = (int)$this->getUser()->GetID(); $pageNum = max(1, (int)($_GET['page'] ?? 1)); $pageSize = (int)($this->arParams['PAGE_SIZE'] ?? 20); $typeFilter = $_GET['type'] ?? ''; $filter = ['USER_ID' => $userId]; if (in_array($typeFilter, ['accrual', 'debit', 'expire'])) { $filter['TYPE'] = $typeFilter; } $totalCount = CashbackTransactionTable::getCount($filter); $transactions = CashbackTransactionTable::getList([ 'filter' => $filter, 'order' => ['CREATED_AT' => 'DESC'], 'limit' => $pageSize, 'offset' => ($pageNum - 1) * $pageSize, 'select' => ['ID', 'TYPE', 'AMOUNT', 'ORDER_ID', 'DESCRIPTION', 'CREATED_AT', 'EXPIRES_AT'], ])->fetchAll(); // Подгружаем номера заказов одним запросом $orderIds = array_filter(array_column($transactions, 'ORDER_ID')); $orderNumbers = []; if ($orderIds) { $res = \Bitrix\Sale\Internals\OrderTable::getList([ 'filter' => ['ID' => $orderIds], 'select' => ['ID', 'ACCOUNT_NUMBER'], ]); while ($row = $res->fetch()) { $orderNumbers[$row['ID']] = $row['ACCOUNT_NUMBER']; } } $this->arResult = [ 'BALANCE' => CashbackBalanceTable::getBalance($userId), 'TRANSACTIONS' => $transactions, 'ORDER_NUMBERS' => $orderNumbers, 'TOTAL_COUNT' => $totalCount, 'PAGE_NUM' => $pageNum, 'PAGE_SIZE' => $pageSize, 'TYPE_FILTER' => $typeFilter, ]; $this->includeComponentTemplate(); } } Отображение и пагинация
Ключевой момент с пагинацией: для D7-компонента не используем CDBResult::NavStart, а рассчитываем количество страниц самостоятельно:
$totalPages = (int)ceil($arResult['TOTAL_COUNT'] / $arResult['PAGE_SIZE']); Ссылки на страницы формируем с сохранением текущего фильтра. Также выводим метки типов и знаки:
$typeLabels = [ 'accrual' => 'Начисление', 'debit' => 'Списание', 'reserve' => 'Резерв', 'release' => 'Возврат резерва', 'expire' => 'Сгорание', 'manual' => 'Ручная корректировка', ]; $amountSign = [ 'accrual' => '+', 'debit' => '−', 'reserve' => '−', 'release' => '+', 'expire' => '−', 'manual' => '', ]; Конвертация часовых поясов
Даты в базе хранятся в UTC. Чтобы отобразить их в часовом поясе пользователя, используем:
$userTz = new \DateTimeZone(\CTimeZone::GetOffset() ? 'UTC' : date_default_timezone_get()); $dt = new \DateTime($transaction['CREATED_AT'], new \DateTimeZone('UTC')); $dt->setTimezone($userTz); echo $dt->format('d.m.Y H:i'); Либо через \Bitrix\Main\Type\DateTime::createFromTimestamp() — он автоматически учитывает настройки сайта.
Связь с заказами
Транзакции accrual и debit содержат ORDER_ID. Ссылку на заказ строим через ACCOUNT_NUMBER, а не через ID — это публичный номер:
/personal/order/detail/{ACCOUNT_NUMBER}/ Если заказ удалён — показываем только номер с пометкой «(заказ удалён)», ссылку не выводим.
Механизм сгорания кэшбэка
Если бизнес-логика требует сгорания кэшбэка (например, через 12 месяцев), поле EXPIRES_AT отображается для транзакций accrual. Cron-задача раз в сутки создаёт транзакции типа expire для истёкшего кэшбэка:
$expired = CashbackTransactionTable::getList([ 'filter' => [ 'TYPE' => 'accrual', '<EXPIRES_AT' => new \Bitrix\Main\Type\DateTime(), 'EXPIRED' => false, ], ]); Это гарантирует, что баланс всегда актуален.
Что входит в работу?
- Проектирование и создание таблицы транзакций с индексами
- Разработка компонента с постраничной навигацией и фильтрацией по типу
- Настройка конвертации часовых поясов
- Интеграция с заказами: отображение ссылок и номеров
- Реализация механизма сгорания кэшбэка (опционально)
- Тестирование на нагрузку (до 10 000 транзакций на пользователя)
- Документация по эксплуатации и поддержка после внедрения
Рекомендации по UX истории операций
Для удобства пользователя рекомендуем цветовое кодирование: начисления — зелёный цвет (+), списания — красный (−), ожидающие — серый. На мобильных устройствах оптимален компактный список с датой, суммой и типом операции, без деталей по умолчанию — подробности раскрываются по клику. Это снижает когнитивную нагрузку и повышает доверие к программе лояльности. Пагинация — по 20 записей, с сохранением фильтра в URL для возможности поделиться ссылкой.
Сроки и гарантии
Ориентировочные сроки: от 1 до 3 недель в зависимости от сложности (наличие сгорания, объём данных). Мы гарантируем производительность даже при высокой нагрузке — 99% запросов к таблице выполняются за < 10 мс. Свяжитесь с нами для точной оценки вашего проекта.







