Налаштування знижки на комплект товарів 1С-Бітрікс
Знижка за покупку комплекту — «купи ноутбук + мишу + сумку і отримай -15%» — стандартний інструмент збільшення середнього чека. У 1С-Бітрікс це реалізується через модуль маркетингу (знижки з умовами по кошику) або через кастомні правила продажів. Нюансів вистачає: порядок застосування знижок, перетин з іншими акціями, відображення знижки на картці.
Варіант 1: знижка через модуль маркетингу (вбудований)
Адміністративна частина → Магазин → Маркетинг → Знижки → Додати знижку.
Умова знижки налаштовується через візуальний конструктор: тип умови «Набір товарів», перелічуємо ID або артикули товарів із комплекту, мінімальна кількість кожного. Значення знижки — відсоток або фіксована сума.
Обмеження вбудованого підходу: конструктор умов неінтуїтивний для нестандартних комплектів, немає відображення знижки на картці товару, немає блоку «Зберіть комплект» на фронтенді.
Варіант 2: кастомне правило продажів
Для складних комплектів — обробник події OnSaleOrderBeforeSaved:
AddEventHandler('sale', 'OnBeforeOrderFinalAction', ['\Local\Pricing\BundleDiscount', 'apply']);
namespace Local\Pricing;
class BundleDiscount
{
// Опис комплектів: [id_товару => кількість]
private static array $bundles = [
'laptop_bundle' => [
'products' => [1001 => 1, 1045 => 1, 1078 => 1], // ноутбук, миша, сумка
'discount_type' => 'percent',
'discount_value' => 15,
'min_total' => 0,
],
'photo_bundle' => [
'products' => [2033 => 1, 2044 => 1], // камера + об'єктив
'discount_type' => 'fixed',
'discount_value' => 3000,
'min_total' => 0,
],
];
public static function apply(\Bitrix\Sale\Order $order): void
{
$basket = $order->getBasket();
$basketMap = self::buildBasketMap($basket);
foreach (self::$bundles as $bundleKey => $bundle) {
if (!self::isBundlePresent($basketMap, $bundle['products'])) {
continue;
}
$discount = self::calculateDiscount($basket, $bundle);
if ($discount <= 0) continue;
// Застосовуємо знижку через механізм 1С-Бітрікс
$discountResult = new \Bitrix\Sale\Discount\Result\DiscountResult();
$discountResult->setApplyResult([
'DISCOUNT_VALUE' => $discount,
'DISCOUNT_TYPE' => 'F', // фіксована сума
'DISCOUNT_RESULT' => ['BASKET' => $basketMap],
]);
$order->getDiscount()->setApplyResult($discountResult);
}
}
private static function buildBasketMap(\Bitrix\Sale\Basket $basket): array
{
$map = [];
foreach ($basket as $item) {
$map[(int)$item->getProductId()] = (int)$item->getQuantity();
}
return $map;
}
private static function isBundlePresent(array $basketMap, array $required): bool
{
foreach ($required as $productId => $qty) {
if (($basketMap[$productId] ?? 0) < $qty) {
return false;
}
}
return true;
}
}
Блок «Зберіть комплект» на картці товару
Щоб покупець знав про знижку до оформлення замовлення, на картці відображається блок із товарами комплекту:
// У result_modifier.php картки товару
$currentProductId = (int)$arResult['ID'];
$bundle = \Local\Pricing\BundleRepository::findByProduct($currentProductId);
if ($bundle) {
$bundleProducts = \CIBlockElement::GetList(
[],
['ID' => array_keys($bundle['products']), 'IBLOCK_ID' => CATALOG_IBLOCK_ID],
false, false,
['ID', 'NAME', 'PREVIEW_PICTURE', 'DETAIL_PAGE_URL', 'CATALOG_PRICE_1']
);
$arResult['BUNDLE'] = [
'discount' => $bundle['discount_value'],
'type' => $bundle['discount_type'],
'products' => [],
];
while ($p = $bundleProducts->GetNext()) {
$arResult['BUNDLE']['products'][] = $p;
}
}
У шаблоні картки:
<?php if (!empty($arResult['BUNDLE'])): ?>
<div class="bundle-block">
<div class="bundle-block__title">
Купіть комплект і заощадьте
<?php if ($arResult['BUNDLE']['type'] === 'percent'): ?>
<?= $arResult['BUNDLE']['discount'] ?>%
<?php else: ?>
<?= number_format($arResult['BUNDLE']['discount'], 0, '', ' ') ?> ₽
<?php endif ?>
</div>
<div class="bundle-block__items">
<?php foreach ($arResult['BUNDLE']['products'] as $bundleItem): ?>
<div class="bundle-block__item">
<img src="<?= \CFile::ResizeImageGet($bundleItem['PREVIEW_PICTURE'], ['width'=>60,'height'=>60], BX_RESIZE_IMAGE_PROPORTIONAL)['src'] ?>"
alt="<?= htmlspecialchars($bundleItem['NAME']) ?>" width="60" height="60">
<a href="<?= $bundleItem['DETAIL_PAGE_URL'] ?>"><?= htmlspecialchars($bundleItem['NAME']) ?></a>
</div>
<?php endforeach ?>
</div>
<button class="bundle-block__add-all js-add-bundle"
data-bundle-ids="<?= implode(',', array_keys($arResult['BUNDLE']['products'])) ?>">
Додати все до кошика
</button>
</div>
<?php endif ?>
Кнопка «Додати весь комплект»
document.querySelector('.js-add-bundle')?.addEventListener('click', async function() {
const ids = this.dataset.bundleIds.split(',').map(Number);
for (const id of ids) {
await fetch('/local/ajax/cart-add.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ product_id: id, quantity: 1 }),
});
}
// Оновлюємо лічильник кошика
BX.onCustomEvent('OnBasketChange', [{}]);
});
Терміни реалізації
| Конфігурація | Термін |
|---|---|
| Знижка через вбудований модуль маркетингу | 1 день |
| Кастомний обробник + блок «Зберіть комплект» | 3–4 дні |
| + «Додати все до кошика» + відображення економії | +1–2 дні |







