Настройка обязательных и опциональных товаров в комплекте 1С-Битрикс
Бандл «Игровой ПК» должен продаваться обязательно с системным блоком, но клавиатуру, мышь и гарнитуру покупатель выбирает сам — включить или нет. Это не просто флаг в базе: разные варианты комплектации дают разную цену, разные остатки, разные строки в заказе. Стандартный механизм 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-обработчик добавления в корзину с передачей выбранных опций
- Логику проверки остатков обязательных и опциональных позиций раздельно
- Правило корзины для скидки на полную комплектацию







