Разработка конструктора наборов товаров 1С-Битрикс
Покупатель хочет собрать подарочную корзину из 5 позиций на выбор. Или скомплектовать компьютер из совместимых комплектующих. Или выбрать шины + диски + TPMS как один заказ. Ни один из стандартных компонентов Битрикс — ни bitrix:catalog.element, ни торговые предложения — не решает эту задачу. Нужен конструктор наборов.
Чем конструктор отличается от торговых предложений
Торговые предложения (SKU) в Битрикс — это вариации одного товара: размер, цвет. Конструктор наборов — это комбинация разных товаров из разных категорий, собранная в один заказ с общей ценой. Иногда с фиксированным количеством позиций на каждую «ячейку», иногда с произвольным выбором.
Примеры:
- Подарочный набор: выбери 3 товара из списка 20 вариантов
- Конструктор ПК: выбери процессор + материнскую плату + RAM (с проверкой совместимости)
- Комбо-набор: бургер + напиток + гарнир (один товар из каждой группы)
Структура данных
Набор — это отдельная сущность. Вариант реализации — инфоблок «Наборы» с привязкой к товарам каталога.
Инфоблок наборов (IBLOCK_SETS):
-
SET_NAME— название набора -
SET_DESCRIPTION— описание -
SLOTS— JSON с описанием ячеек набора (множественное свойство типа «Строка» или отдельная таблица) -
DISCOUNT_TYPE— тип скидки набора (percent/fixed) -
DISCOUNT_VALUE— размер скидки
Структура слота (ячейки) в JSON:
{
"slot_id": 1,
"name": "Основное блюдо",
"required": true,
"min_qty": 1,
"max_qty": 1,
"product_filter": {
"IBLOCK_ID": 5,
"SECTION_ID": [12, 13]
}
}
Для сложных проектов (конструктор ПК) лучше хранить слоты в отдельной кастомной таблице:
CREATE TABLE b_set_slots (
ID SERIAL PRIMARY KEY,
SET_ID INT NOT NULL REFERENCES b_iblock_element(ID),
SLOT_NAME VARCHAR(255),
REQUIRED BOOLEAN DEFAULT TRUE,
MIN_QTY INT DEFAULT 1,
MAX_QTY INT DEFAULT 1,
SORT INT DEFAULT 100
);
CREATE TABLE b_set_slot_products (
SLOT_ID INT NOT NULL REFERENCES b_set_slots(ID),
PRODUCT_ID INT NOT NULL REFERENCES b_iblock_element(ID),
PRIMARY KEY (SLOT_ID, PRODUCT_ID)
);
Логика выбора и расчёта цены
Пользовательский интерфейс конструктора — последовательные шаги или единая страница с вертикальными группами. На каждом шаге — список товаров для данного слота.
Расчёт итоговой цены происходит на клиенте (быстро, без сервера) и подтверждается на сервере (при добавлении в корзину):
function calcSetTotal(selectedProducts) {
let total = selectedProducts.reduce((sum, p) => sum + p.price * p.qty, 0);
// применяем скидку набора
if (setDiscount.type === 'percent') {
total = total * (1 - setDiscount.value / 100);
} else {
total = total - setDiscount.value;
}
return Math.max(0, total);
}
Добавление набора в корзину
Стандартный API корзины Битрикс не умеет добавлять «связанные» позиции, которые составляют набор. Нужна кастомная логика:
use Bitrix\Sale\Basket;
use Bitrix\Sale\BasketItem;
$basket = Basket::loadItemsForFUser(CSaleBasket::GetBasketUserID(), SITE_ID);
$setBasketCode = 'set_' . uniqid(); // уникальный идентификатор набора
foreach ($selectedProducts as $product) {
$item = $basket->createItem('catalog', $product['PRODUCT_ID']);
$item->setFields([
'QUANTITY' => $product['QTY'],
'PRODUCT_PRICE_ID' => $product['PRICE_ID'],
'CUSTOM_PRICE' => 'Y',
'PRICE' => $product['PRICE'],
// кастомное поле для группировки позиций набора
'PROPS' => [['NAME' => 'SET_CODE', 'VALUE' => $setBasketCode]],
]);
}
$basket->save();
В корзине позиции набора отображаются сгруппированными по SET_CODE. Для этого шаблон корзины (bitrix:sale.basket.basket) нужно кастомизировать — добавить группировку по свойству набора.
Проверка совместимости
Для конструкторов технических изделий (ПК, автозапчасти, мебель под размер) нужна проверка совместимости между выбранными позициями. Матрица совместимости хранится в кастомной таблице:
CREATE TABLE b_compatibility_rules (
ID SERIAL PRIMARY KEY,
PRODUCT_A_ID INT NOT NULL,
PRODUCT_B_ID INT NOT NULL,
COMPATIBLE BOOLEAN DEFAULT TRUE,
REASON TEXT
);
При каждом выборе товара AJAX-запрос к PHP-контроллеру проверяет совместимость с уже выбранными позициями и возвращает список несовместимых вариантов для блокировки в UI:
public function checkCompatibilityAction(int $productId, array $selectedIds): array {
$incompatible = [];
foreach ($selectedIds as $id) {
$rule = CompatibilityTable::getRow([
'filter' => [
['PRODUCT_A_ID' => $productId, 'PRODUCT_B_ID' => $id],
['COMPATIBLE' => false],
]
]);
if ($rule) {
$incompatible[] = ['product_id' => $id, 'reason' => $rule['REASON']];
}
}
return $incompatible;
}
Сохранённые конфигурации
Пользователь может захотеть сохранить собранный набор и вернуться к нему. Сохранение конфигурации в пользовательском аккаунте:
CREATE TABLE b_user_set_configs (
ID SERIAL PRIMARY KEY,
USER_ID INT NOT NULL,
SET_ID INT NOT NULL,
CONFIG_NAME VARCHAR(255),
PRODUCTS JSONB NOT NULL,
DATE_CREATE TIMESTAMP DEFAULT NOW()
);
Пользователь видит свои конфигурации в личном кабинете и может добавить любую из них в корзину одним кликом.
Сроки
| Тип конструктора | Что входит | Срок |
|---|---|---|
| Подарочный набор (простой выбор) | UI + корзина + скидка набора | 2–3 недели |
| Комбо с группами (фаст-фуд стиль) | + группы слотов, обязательные позиции | 3–5 недель |
| Конструктор с совместимостью | + матрица совместимости, проверки | 5–8 недель |
| + Сохранённые конфигурации | + ЛК, история, шаринг конфигурации | +2–3 недели |
Конструктор наборов увеличивает средний чек: пользователь, который собирает комплект, тратит больше, чем тот, кто покупает один товар. Инструмент работает тем лучше, чем проще и понятнее интерфейс выбора.







