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

Выгрузка свойств товара из 1С - типы, коды и множественные значения

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

Решение

Смотрим внешние коды свойств инфоблока:

$props = CIBlockProperty::GetList([], ['IBLOCK_ID' => $iblockId]);
while ($prop = $props->Fetch()) {
printf("%-24s %-12s xml_id=%s\n", $prop['CODE'], $prop['PROPERTY_TYPE'], $prop['XML_ID']);
}

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

Создаём свойство нужного типа до первого обмена:

$property = new CIBlockProperty();
$property->Add([
'IBLOCK_ID' => $iblockId,
'NAME' => 'Цвет',
'CODE' => 'COLOR',
'PROPERTY_TYPE' => 'L', // список; после обмена тип уже не сменить
'MULTIPLE' => 'N',
'XML_ID' => $guidFrom1C,
]);

Тип свойства обмен не меняет. Если свойство создалось автоматически при первой выгрузке, оно почти всегда получится строкой, и перевести его в список или в привязку к элементам потом можно только пересозданием.

Включаем множественность там, где значений несколько:

CIBlockProperty::Update($propertyId, ['MULTIPLE' => 'Y']);

У одиночного свойства обмен запишет последнее пришедшее значение и молча отбросит остальные. Ошибки в логе при этом не будет: с точки зрения обмена он всё сохранил.

Проверяем, что приехало, на конкретном товаре:

$el = CIBlockElement::GetList([], ['IBLOCK_ID' => $iblockId, 'XML_ID' => $xmlId], false, false, ['ID']);
$row = $el->Fetch();
$values = CIBlockElement::GetProperty($iblockId, $row['ID'], [], []);
while ($v = $values->Fetch()) {
echo "{$v['CODE']}: {$v['VALUE']}\n";
}

Такая выборка показывает и пустые свойства, поэтому по ней видно не только что приехало, но и что осталось незаполненным.

Привязываем существующее свойство к реквизиту 1С:

// XML_ID берём из выгруженного файла: <Свойство><Ид>...</Ид></Свойство>
CIBlockProperty::Update($propertyId, ['XML_ID' => 'e4f1c0a2-9b3d-11ee-8c90-0242ac120002']);
// после правки сбрасываем кеш свойств инфоблока, иначе обмен возьмёт старую карту
CIBlock::CleanCache($iblockId);

Так свойство перестаёт дублироваться: обмен находит его по коду и пишет в него, вместо того чтобы заводить новое рядом.

Сравнивать удобно с самим XML: обмен складывает присланные файлы в /upload/1c_catalog/, и там видно, что 1С действительно отправила. Если в XML реквизита нет, дело не в сайте, а в отборе на стороне 1С.

Отдельная история - свойства торговых предложений. Они живут в своём инфоблоке, и коды у них свои: одноимённое свойство товара и предложения это два разных свойства с разными XML_ID. Путаница между ними даёт классическую картину, когда у товара характеристика пустая, а у его предложений заполнена.

Смотрим, что 1С прислала по конкретному реквизиту:

Окно терминала
# в файле import.xml узел свойства лежит рядом с его значением у товара
grep -A3 -m5 '<Свойство>' /home/bitrix/www/upload/1c_catalog/import*.xml
grep -c '<ЗначенияСвойства>' /home/bitrix/www/upload/1c_catalog/import*.xml

Порядок разбора внутри файла тоже важен. Справочники приезжают до товаров, и свойство типа «привязка к элементам» находит цель только если она уже в базе. При первом обмене на пустом каталоге такие свойства часто остаются пустыми и заполняются лишь со второго прогона.

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

Свойство приехало строкой вместо списка.

Свойство создал сам обмен при первой выгрузке. Тип он выбирает строковый и потом не меняет: нужное свойство заводят руками до первого обмена и проставляют ему XML_ID реквизита.

Из нескольких значений сохранилось одно.

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

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

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

Свойство типа «привязка к элементам» приезжает пустым.

Обмен передаёт значение внешним кодом, и элемент-цель должен быть выгружен раньше. Если справочник приезжает в том же файле после товаров, привязка не находит цели.

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

Можно ли сопоставить реквизит 1С с уже существующим свойством сайта?

Да, для этого свойству проставляют XML_ID, равный идентификатору реквизита в 1С. После этого обмен пишет в него, а не создаёт новое. Идентификатор смотрят в выгруженном XML, в узле свойства.

Почему картинки из свойства приезжают одной штукой?

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

Как выгрузить только часть реквизитов?

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

Что будет со свойством, если его удалить на сайте?

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

Смежное

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