Налаштування обов'язкових і опціональних товарів у комплекті 1С-Bitrix
Бандл «Ігровий ПК» повинен продаватися обов'язково з системним блоком, але клавіатуру, мишку та гарнітуру покупець вибирає сам — включити або ні. Це не просто прапорець у базі: різні варіанти комплектації дають різну ціну, різні залишки, різні рядки в замовленні. Стандартний механізм b_catalog_product_set має поле IS_REQUIRED, але фронтенд-логіка вибору опцій не реалізована з коробки.
Поле IS_REQUIRED у таблиці b_catalog_product_set
Поле IS_REQUIRED приймає значення 0 (опціональний) та 1 (обов'язковий). Це єдине розділення в стандартній структурі. Для складніших сценаріїв — наприклад, «вибрати рівно одну позицію з групи» — потрібно розширювати схему.
Додаємо поле GROUP_ID в b_catalog_product_set через користувацьке поле або через розширення таблиці (якщо дозволяє політика оновлень). Альтернатива без зміни структури таблиці: зберігати групування в окремій таблиці bl_bundle_option_group:
CREATE TABLE bl_bundle_option_group (
id SERIAL PRIMARY KEY,
bundle_id INT NOT NULL,
group_code VARCHAR(100) NOT NULL,
group_name VARCHAR(255),
min_select SMALLINT DEFAULT 0, -- мінімум вибраних з групи
max_select SMALLINT DEFAULT 1, -- максимум вибраних з групи
item_ids INT[] NOT NULL, -- масив ITEM_ID з b_catalog_product_set
UNIQUE (bundle_id, group_code)
);
Логіка вибору на фронтенді
Сторінка комплекту відображає обов'язкові позиції як не знімаємі (з галкою без можливості прибрати) та опціональні — як чекбокси або радіо-кнопки (якщо max_select = 1 у групі).
При зміні вибору скриптом перераховується загальна ціна. Ціну кожного опціонального компонента беремо з b_catalog_price за його PRODUCT_ID. Важливо враховувати персональні ціни користувача: якщо у покупця є цінова група, потрібно перевіряти b_catalog_price.CATALOG_GROUP_ID.
function recalcBundle(selectedItems) {
const basePrice = bundleData.basePrice; // ціна обов'язкових позицій
let optionsTotal = 0;
selectedItems.forEach(itemId => {
optionsTotal += bundleData.items[itemId].price;
});
document.getElementById('bundle-total').textContent =
formatPrice(basePrice + optionsTotal);
}
Додавання в кошик з вибраними опціями
При додаванні в кошик потрібно передати склад комплекту — тільки вибрані позиції. Через AJAX POST відправляємо bundle_id та масив selected_items[]. На сервері:
// Формуємо склад для додавання в кошик
$bundle = new \Bitrix\Sale\BasketItem();
// Обов'язкові позиції беремо завжди
$requiredItems = \Bitrix\Catalog\ProductSetTable::getList([
'filter' => ['SET_ID' => $bundleId, 'IS_REQUIRED' => 1],
])->fetchAll();
// Опціональні — тільки з $_POST['selected_items']
$optionalItems = array_intersect(
array_column($requiredItems, 'ITEM_ID'),
(array)$_POST['selected_items']
);
Підсумковий склад передається в \Bitrix\Catalog\Product\Bundle::add(). Кожен компонент створює окремий рядок в b_sale_basket з прапорцем SET_PARENT_ID.
Залишки при опціональних позиціях
Доступність комплекту при опціональних позиціях: перевіряємо залишки тільки обов'язкових компонентів. Опціональні — окремо, для кожної відображаємо «доступно N штук» поруч з чекбоксом. Якщо опціональна позиція закінчилася — чекбокс недоступний, але комплект без неї можна купити.
Ціна комплекту зі знижкою
Знижка на комплект застосовується тільки при виборі всіх опціональних позицій (повна комплектація) — це частий бізнес-кейс. Реалізується через правило кошика: знижка спрацьовує при співпаданні набору товарів у кошику з повним складом бандла. Умова правила: всі ITEM_ID з b_catalog_product_set присутні в кошику з потрібними кількостями.
Що налаштовуємо
- Таблицю
bl_bundle_option_groupдля групування опцій з параметрамиmin_select/max_select - Шаблон компонента відображення комплекту з чекбоксами та перерахунком ціни
- AJAX-обробник додавання в кошик з передачею вибраних опцій
- Логіку перевірки залишків обов'язкових та опціональних позицій окремо
- Правило кошика для знижки на повну комплектацію







