Перейти к содержимому

Структура каталога при выгрузке из 1С - разделы, вложенность, две базы

Разбираемся, как группы номенклатуры 1С становятся разделами инфоблока и что делать, когда дерево приезжает не таким, как нужно сайту.

Решение

Смотрим, что приехало в разделы после обмена:

$sections = CIBlockSection::GetList(
['LEFT_MARGIN' => 'ASC'], // порядок обхода дерева
['IBLOCK_ID' => $iblockId],
false,
['ID', 'NAME', 'DEPTH_LEVEL', 'XML_ID']
);
while ($s = $sections->Fetch()) {
printf("%s%-30s xml_id=%s\n", str_repeat(' ', $s['DEPTH_LEVEL'] - 1), $s['NAME'], $s['XML_ID']);
}

Вложенность приезжает из 1С как есть: сколько уровней в справочнике номенклатуры, столько и в инфоблоке. Сайт её не выпрямляет и не схлопывает, даже если витрине удобнее два уровня вместо пяти.

Поле XML_ID у раздела - тот же внешний код, что и у товара. По нему обмен находит раздел при повторной выгрузке и решает, обновить его или создать новый рядом. Пустой внешний код у раздела означает, что его завели на сайте руками, и обмен такой раздел не тронет.

Раскладываем товары сами, если дерево не выгружается:

/local/php_interface/init.php
AddEventHandler('iblock', 'OnBeforeIBlockElementUpdate', 'routeBySupplier');
function routeBySupplier(&$arFields)
{
if (($_REQUEST['mode'] ?? '') !== 'import') {
return;
}
$code = $arFields['PROPERTY_VALUES'][SUPPLIER_PROP_ID][0]['VALUE'] ?? null;
if ($code && isset(SECTION_BY_SUPPLIER[$code])) {
$arFields['IBLOCK_SECTION'] = [SECTION_BY_SUPPLIER[$code]];
}
}

Такой обработчик нужен, когда в 1С плоский список, а на сайте нужна витрина по разделам. Раскладка идёт по свойству товара, а не по группе номенклатуры.

Разводим две базы 1С по корневым разделам:

// каждой базе свой корень: внешние коды групп в разных базах совпадают
$section = new CIBlockSection();
$rootA = $section->Add(['IBLOCK_ID' => $iblockId, 'NAME' => 'Основной склад', 'XML_ID' => 'base-a']);
$rootB = $section->Add(['IBLOCK_ID' => $iblockId, 'NAME' => 'Филиал', 'XML_ID' => 'base-b']);

Без разведения вторая база перезапишет разделы первой: обмен сопоставляет группы по внешнему коду, а нумерация в двух базах 1С идёт независимо.

Удерживаем товар в разделе, назначенном на сайте:

function keepSiteSection(&$arFields)
{
if (($_REQUEST['mode'] ?? '') === 'import') {
unset($arFields['IBLOCK_SECTION'], $arFields['IBLOCK_SECTION_ID']);
}
}

Иначе каждый обмен возвращает товар в группу из 1С, и ручная раскладка живёт до следующей выгрузки.

Выбор между двумя подходами стоит сделать один раз и записать в проекте. Либо дерево ведёт 1С, и тогда сайт не трогает разделы вовсе, либо раскладку ведёт сайт, и тогда привязка снимается на каждом обмене. Смешанный вариант, когда часть разделов ведёт 1С, а часть контент-менеджер, разъезжается через месяц: никто уже не помнит, какой раздел чей, и правки затираются молча.

Типичные проблемы

Товары приехали в корень инфоблока, разделов нет.

Группы номенклатуры не попали в выгрузку. Обмен разбирает группы отдельным узлом до товаров, и если 1С их не прислала, привязывать товар не к чему.

После второго обмена дерево разделов задвоилось.

Внешние коды групп изменились: так бывает после переноса базы 1С. Сайт не нашёл прежних разделов и создал новые рядом со старыми.

Товар переехал в другой раздел сам.

В 1С его перенесли в другую группу, и обмен повторил перенос. Привязку снимают обработчиком, если раскладку на сайте ведёт контент-менеджер.

Разделы из двух баз 1С затирают друг друга.

Нумерация групп в базах независима, и внешние коды совпадают. Каждой базе выделяют свой корневой раздел и выгружают внутрь него.

Частые вопросы

Можно ли выгрузить товары без дерева каталога?

Да, если в 1С не выгружать группы. Товары приедут в корень инфоблока, а раскладку по разделам делают на сайте своим обработчиком по свойству товара - поставщику, бренду, назначению.

Как сохранить структуру 1С, но переименовать разделы на сайте?

Названия обмен перезаписывает вместе с остальными полями раздела. Свои названия удерживают тем же приёмом, что и у товаров: снимают поле NAME в обработчике OnBeforeIBlockSectionUpdate по признаку mode=import.

Что будет с товарами, если группу в 1С удалить?

Раздел на сайте останется, а товары из него 1С перенесёт в другую группу при следующем обмене. Пустые разделы обмен не убирает: их чистят отдельно, сверяясь с присланным деревом.

Обязательно ли совпадение вложенности сайта и 1С?

Нет, но всё, что приходит из 1С, воспроизводится один в один. Другая структура на сайте держится только обработчиком, и её надо восстанавливать при каждом обмене.

Смежное

Первоисточник