Налаштування персональних знижок за групами клієнтів у 1С-Бітрікс
Менеджер створює «знижку 15% для VIP-клієнтів» в адмін-панелі Бітрікса й призначає її групі користувачів. Заходить тестовий VIP-аккаунт — знижка не застосовується. Причина: знижка створена в «Каталогу товарів», але користувач не належить до потрібної групи, тому що менеджер переплутав «групу покупців» (модуль sale) з «групою користувачів» (модуль main). У Бітриксі це різні сутності, і плутанина між ними — джерело більшості проблем з персональними знижками.
Архітектура знижок у Бітриксі
Модуль sale керує знижками через \Bitrix\Sale\Discount. Знижки можуть застосовуватися до:
- Групи користувачів (
b_user_group— таблиця main-модуля) - Окремих користувачів (через розширені умови)
- Покупців з певною історією замовлень (накопичувальні знижки)
Щоб призначити знижку групі: в адмін-панелі перейдіть на «Магазин → Правила роботи з цінами» — виберіть тип «Знижка на товар» або «Знижка на замовлення», в умовах вкажіть «Покупець входить до групи». Групи беруться з b_user_group.
Створення групи й прив'язка користувачів
Групи користувачів створюються в «Налаштування → Групи користувачів». Програмно:
$group = new \CGroup();
$groupId = $group->Add([
'NAME' => 'VIP-клієнти',
'DESCRIPTION' => 'Знижка 15% на весь каталог',
'ACTIVE' => 'Y',
'SORT' => 100,
]);
Додати користувача до групи:
$user = new \CUser();
$user->Update($userId, ['GROUP_ID' => array_merge($currentGroups, [$groupId])]);
Або через CUser::SetUserGroup($userId, $groups) — перезаписує всі групи, тому обов'язково передавайте поточні групи разом з новою.
Автоматичне призначення групи за умовами
Щоб автоматично перевести покупця до VIP-групи при досягненні порогу суми замовлень — обробник події OnSaleOrderSaved:
AddEventHandler('sale', 'OnSaleOrderSaved', function(\Bitrix\Main\Event $event) {
$order = $event->getParameter('ENTITY');
$userId = (int)$order->getUserId();
if (!$userId) return;
// Рахуємо суму оплачених замовлень
$total = 0;
$res = \Bitrix\Sale\Order::getList([
'filter' => ['USER_ID' => $userId, 'PAYED' => 'Y'],
'select' => ['PRICE'],
]);
while ($row = $res->fetch()) {
$total += $row['PRICE'];
}
$vipThreshold = 50000; // грошові одиниці
$vipGroupId = 5;
$dbUser = \CUser::GetByID($userId)->Fetch();
$currentGroups = array_map('intval', explode(',', $dbUser['GROUP_IDS'] ?? ''));
if ($total >= $vipThreshold && !in_array($vipGroupId, $currentGroups)) {
$currentGroups[] = $vipGroupId;
(new \CUser())->Update($userId, ['GROUP_ID' => $currentGroups]);
}
});
Знижки на торгові пропозиції (SKU)
Якщо знижка призначена товару-батькові, вона застосовується й до торгових пропозицій. Але якщо потрібна знижка тільки на конкретний SKU — умова в правилі ціни повинна вказувати на інфоблок пропозицій. У налаштуваннях правила: «Тип інфоблока» → виберіть інфоблок пропозицій, розділ або конкретні елементи.
Відображення персональної ціни
Стандартний компонент catalog.element відображає ціну через $arResult['CATALOG_PRICE_*'], де * — тип ціни. Знижки для груп застосовуються через \CCatalogProduct::GetOptimalPrice(), який урахує правила цін і групи поточного користувача. Якщо сторінка кешується — ціна в кеші може бути без знижки.
Рішення: виносити блок ціни в окремий некешований компонент або запитати актуальну ціну через AJAX після завантаження сторінки. Другий підхід краще для продуктивності при високому трафіку.







