Розробка модуля програми лояльності 1С-Бітрікс
Вбудований інструмент «бонуси» у Бітрікс — це поле b_user.UF_BONUS_POINTS плюс саморобна логіка в компонентах. Немає історії нарахувань, немає строку дії балів, немає рівнів, немає інтеграції із замовленнями через події. Коли клієнт каже «хочемо програму лояльності», мається на увазі щось значно більше: накопичувальна система з рівнями, історією, обмеженим строком дії балів, частковою оплатою замовлення та вітриною привілеїв.
Модель даних
Модуль vendor.loyalty:
-
b_vendor_loyalty_account— рахунок лояльності: id, user_id, balance (поточний баланс), total_earned (всього нараховано за весь час), level_id, created_at -
b_vendor_loyalty_transaction— транзакції: id, account_id, type (earn/spend/expire/cancel/manual), amount, order_id, description, expires_at, created_at -
b_vendor_loyalty_level— рівні програми: id, name, min_points, earn_multiplier, privileges (JSON), icon_id -
b_vendor_loyalty_rule— правила нарахування: id, event_type (order_paid/review_added/birthday/referral/registration), points_type (fixed/percent), points_value, conditions (JSON), is_active
Нарахування балів
Нарахування прив'язане до подій Бітрікс. Для замовлень — OnSaleOrderPaid:
AddEventHandler('sale', 'OnSaleOrderPaid', ['\Vendor\Loyalty\EventHandler', 'onOrderPaid']);
public static function onOrderPaid(\Bitrix\Main\Event $event): void
{
$orderId = $event->getParameter('id');
$order = \Bitrix\Sale\Order::load($orderId);
$userId = $order->getUserId();
$account = AccountTable::getByUserId($userId);
$level = LevelTable::getById($account['LEVEL_ID']);
// Нараховуємо % від суми замовлення з урахуванням множника рівня
$basePoints = floor($order->getPrice() * 0.05); // 5% базово
$earnedPoints = floor($basePoints * $level['EARN_MULTIPLIER']);
TransactionTable::add([
'ACCOUNT_ID' => $account['ID'],
'TYPE' => 'earn',
'AMOUNT' => $earnedPoints,
'ORDER_ID' => $orderId,
'EXPIRES_AT' => (new DateTime())->add(new DateInterval('P1Y')), // строк дії — 1 рік
'DESCRIPTION' => "Нарахування за замовлення №{$order->getField('ACCOUNT_NUMBER')}",
]);
AccountTable::update($account['ID'], [
'BALANCE' => $account['BALANCE'] + $earnedPoints,
'TOTAL_EARNED' => $account['TOTAL_EARNED'] + $earnedPoints,
]);
// Перевірка підвищення рівня
LevelUpgradeService::check($account['ID']);
}
Строк дії балів та спалення
Бали можуть мати дату закінчення. Агент щодня перевіряє та списує прострочені бали:
// Агент запускається о 03:00 ночі
$expired = TransactionTable::getList([
'filter' => ['TYPE' => 'earn', '<=EXPIRES_AT' => new DateTime(), '>AMOUNT' => 0],
])->fetchAll();
foreach ($expired as $tx) {
// Списуємо залишок балів із цієї транзакції
TransactionTable::add(['TYPE' => 'expire', 'AMOUNT' => -$tx['REMAINING'], ...]);
// Оновлюємо баланс рахунку
}
Списання балів при оплаті замовлення
Часткова оплата замовлення балами реалізується через кастомну систему оплати (PaySystem):
// У процесорі платіжної системи
public function processRequest(Payment $payment, Request $request): ProcessRequestResult
{
$pointsToSpend = (int)$request->get('loyalty_points');
$account = AccountTable::getByUserId($payment->getOrder()->getUserId());
if ($account['BALANCE'] < $pointsToSpend) {
return ProcessRequestResult::error('Недостатньо балів');
}
// 1 бал = 1 гривня (налаштовується в модулі)
$discountAmount = $pointsToSpend / (int)Option::get('vendor.loyalty', 'points_rate', 1);
$discountAmount = min($discountAmount, $payment->getSum() * 0.5); // максимум 50% замовлення
// Списуємо бали та створюємо знижку на замовлення
TransactionTable::add(['TYPE' => 'spend', 'AMOUNT' => -$pointsToSpend, ...]);
AccountTable::update($account['ID'], ['BALANCE' => $account['BALANCE'] - $pointsToSpend]);
return ProcessRequestResult::success();
}
Рівні програми
Рівні підвищуються автоматично за TOTAL_EARNED. При підвищенні рівня:
- Перераховується множник нарахувань (
EARN_MULTIPLIER) - Надсилається сповіщення користувачу
- Активуються привілеї рівня (безкоштовна доставка, пріоритетна підтримка — через прапорці в
b_user.UF_*)
| Рівень | Поріг (всього балів) | Множник нарахувань |
|---|---|---|
| Стандарт | 0 | 1.0x |
| Срібло | 5 000 | 1.2x |
| Золото | 20 000 | 1.5x |
| Платина | 50 000 | 2.0x |
Пороги та множники налаштовуються в адміністративному інтерфейсі.
Особистий кабінет користувача
Блок «Моя лояльність» в особистому кабінеті:
- Поточний баланс і рівень
- Прогрес до наступного рівня
- Історія транзакцій із пагінацією
- Найближчі бали, що згорають, із датами
- Форма застосування балів при оформленні замовлення
Терміни розробки
| Етап | Термін |
|---|---|
| ORM-таблиці, модель рахунку та транзакцій | 1 день |
| Правила нарахування, обробники подій | 2 дні |
| Строк дії балів, агент спалення | 1 день |
| PaySystem для списання балів | 2 дні |
| Рівні, автопідвищення, привілеї | 2 дні |
| Особистий кабінет, історія транзакцій | 2 дні |
| Адміністративний інтерфейс | 1 день |
| Тестування | 1 день |
Разом: 12 робочих днів. Інтеграція з офлайн-касою або CRM для нарахування балів за покупки поза сайтом — окрема оцінка.







