Настройка массовой привязки торговых предложений 1С-Битрикс

Наша компания занимается разработкой, поддержкой и обслуживанием решений на Битрикс и Битрикс24 любой сложности. От простых одностраничных сайтов до сложных интернет магазинов, CRM систем с интеграцией 1С и телефонии. Опыт разработчиков подтвержден сертификатами от вендора.
Предлагаемые услуги
Показано 1 из 1 услугВсе 1626 услуг
Настройка массовой привязки торговых предложений 1С-Битрикс
Простая
~1 рабочий день
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1167
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    811
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Разработка на базе Битрикс, Битрикс24, 1С для компании Development of an Online Appointment Booking Widget for a Medical Center
    563
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Разработка на базе 1С Предприятие для компании МИРСАНБЕЛ
    743
  • image_crm_dolbimby_434_0.webp
    Разработка сайта на CRM Битрикс24 для компании DOLBIMBY
    655
  • image_crm_technotorgcomplex_453_0.webp
    Разработка на базе Битрикс24 для компании ТЕХНОТОРГКОМПЛЕКС
    976

Настройка массовой привязки торговых предложений 1С-Битрикс

Торговые предложения в Битрикс — это элементы отдельного инфоблока, каждый из которых привязан к родительскому товару через поле CML2_LINK (хранится в b_iblock_element_property). Когда у вас тысячи SKU и эта привязка нарушена — предложения не отображаются в карточке товара, цены и остатки не показываются. Задача массовой привязки возникает при миграции с другой платформы, импорте из 1С с ошибками или ручном создании базы.

Как работает связь товар — торговое предложение

Инфоблок каталога содержит основные товары. Для торговых предложений создаётся связанный инфоблок — его ID указывается в поле OFFERS_IBLOCK_ID в b_iblock.ID. Связь объявляется через b_iblock_fields или через интерфейс: Инфоблоки → Типы инфоблоков → Торговый каталог → Редактировать.

Каждое торговое предложение имеет свойство с кодом CML2_LINK (тип «Привязка к элементам») — значение в b_iblock_element_property.VALUE соответствует ID родительского товара.

-- Проверить, у скольких предложений не заполнена привязка:
SELECT COUNT(*)
FROM b_iblock_element ie
WHERE ie.IBLOCK_ID = {offers_iblock_id}
AND NOT EXISTS (
    SELECT 1 FROM b_iblock_element_property iep
    INNER JOIN b_iblock_property ip ON ip.ID = iep.IBLOCK_PROPERTY_ID
    WHERE iep.IBLOCK_ELEMENT_ID = ie.ID
    AND ip.CODE = 'CML2_LINK'
    AND iep.VALUE IS NOT NULL
);

Нахождение ID свойства CML2_LINK

$offersIblockId = 11; // ID инфоблока торговых предложений

$propRes = \Bitrix\Iblock\PropertyTable::getList([
    'filter' => ['IBLOCK_ID' => $offersIblockId, 'CODE' => 'CML2_LINK'],
    'select' => ['ID'],
])->fetch();

$linkPropertyId = $propRes['ID'];

Массовая привязка по XML_ID

Самый распространённый сценарий: у товаров и предложений в b_iblock_element.XML_ID хранится артикул из 1С. Привязка делается по совпадению артикула или по маппинговой таблице.

// Пример: привязываем предложения к товарам по первым 8 символам XML_ID
// Товар: XML_ID = 'PROD-001', Предложения: XML_ID = 'PROD-001-S', 'PROD-001-M', 'PROD-001-L'

$catalogIblockId = 10;
$offersIblockId  = 11;

// Собираем карту товаров: XML_ID → ID элемента
$productMap = [];
$productsRes = \CIBlockElement::GetList([], ['IBLOCK_ID' => $catalogIblockId], false, false, ['ID', 'XML_ID']);
while ($row = $productsRes->Fetch()) {
    $productMap[$row['XML_ID']] = $row['ID'];
}

// Обрабатываем предложения пакетами
$offersRes = \CIBlockElement::GetList([], ['IBLOCK_ID' => $offersIblockId], false, false, ['ID', 'XML_ID']);

$batch = [];
while ($row = $offersRes->Fetch()) {
    // Определяем XML_ID родителя: берём первые N символов или парсим по разделителю
    $parentXmlId = substr($row['XML_ID'], 0, 8); // настройте под свою схему
    if (!isset($productMap[$parentXmlId])) continue;

    $parentId = $productMap[$parentXmlId];
    $batch[]  = ['offer_id' => $row['ID'], 'parent_id' => $parentId];

    if (count($batch) >= 200) {
        bindOffersToProducts($batch, $offersIblockId, $linkPropertyId);
        $batch = [];
    }
}
if (!empty($batch)) {
    bindOffersToProducts($batch, $offersIblockId, $linkPropertyId);
}

function bindOffersToProducts(array $batch, int $iblockId, int $propId): void
{
    foreach ($batch as $item) {
        // Проверяем, есть ли уже запись
        $existing = \Bitrix\Iblock\ElementPropertyTable::getList([
            'filter' => [
                'IBLOCK_ELEMENT_ID' => $item['offer_id'],
                'IBLOCK_PROPERTY_ID' => $propId,
            ],
            'select' => ['ID'],
        ])->fetch();

        if ($existing) {
            \Bitrix\Iblock\ElementPropertyTable::update($existing['ID'], [
                'VALUE' => $item['parent_id'],
            ]);
        } else {
            \Bitrix\Iblock\ElementPropertyTable::add([
                'IBLOCK_ELEMENT_ID'  => $item['offer_id'],
                'IBLOCK_PROPERTY_ID' => $propId,
                'VALUE'              => $item['parent_id'],
            ]);
        }
    }
}

Привязка через CSV-маппинг

Если логика определения родителя сложнее — используйте внешнюю карту:

offer_xml_id,parent_xml_id
SKU-001-RED,PROD-001
SKU-001-BLUE,PROD-001
SKU-002-S,PROD-002
$map = parseCsv('/import/offers_mapping.csv'); // [['offer_xml_id' => ..., 'parent_xml_id' => ...]]
foreach ($map as $row) {
    $offerId  = getElementIdByXmlId($offersIblockId, $row['offer_xml_id']);
    $parentId = getElementIdByXmlId($catalogIblockId, $row['parent_xml_id']);
    if ($offerId && $parentId) {
        \CIBlockElement::SetPropertyValues($offerId, $offersIblockId, $parentId, 'CML2_LINK');
    }
}

Проверка результата и инвалидация кэша

После массовой привязки обязательно:

  1. Проверьте несколько товаров в публичной части — предложения должны отображаться в карточке
  2. Сбросьте кэш инфоблоков для обоих инфоблоков
  3. Переиндексируйте фасетный фильтр, если предложения участвуют в фильтрации
\Bitrix\Iblock\InformationBlock::cleanTagCache($catalogIblockId);
\Bitrix\Iblock\InformationBlock::cleanTagCache($offersIblockId);
\Bitrix\Iblock\PropertyIndex\Manager::markIblockToReindex($offersIblockId);

Сроки выполнения

Объём Время
До 1 000 предложений 2–4 часа (анализ + скрипт + проверка)
1 000–20 000 предложений 1 день
20 000+ предложений 2–3 дня (включая отладку маппинга и верификацию)