среда, 31 января 2018 г.

Интеграция Битрикс и 1С: выгрузка комплектов, наборов - простой способ "в лоб"

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

Впервые столкнувшись с необходимостью выгрузки комплектов/наборов из 1С в Битрикс, я первоначально планировала раскомментировать эти забытые ошметки кода и использовать их, но потом отказалась от этой идеи, поняв, что можно сделать проще.

В различных конфигурациях 1С организация хранения комплектов/наборов осуществляется по-разному, однако это не имеет большого значения, и в данном посте я опишу достаточно универсальный и простой способ кастомизации интеграции для выгрузки комплектов.



Каким бы образом ни осуществлялось хранение наборов и комплектов в 1С, обычно стандартный модуль обмена выгружает комплект как простой товар (а если такой товар-комплект не выгружается вообще, сначала нужно добиться того, чтобы он выгружался в любом виде - добиться этого не сложно).

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

<ЗначенияРеквизитов>
<ЗначениеРеквизита>
<Наименование>Комплектующее</Наименование>
<Значение>Комплектующее1*25bb03f7-e953-11e7-8d71-002522ce173a*1</Значение>
</ЗначениеРеквизита>
<ЗначениеРеквизита>
<Наименование>Комплектующее</Наименование>
<Значение>Комплектующее2*25bb03ed-e953-11e7-8d71-002522ce173a*1</Значение>
        <ЗначениеРеквизита>
<Наименование>ТипНоменклатуры</Наименование>
<Значение>Комплект</Значение>
</ЗначениеРеквизита>
</ЗначенияРеквизитов>

В значении реквизита Комплектующее я передаю, разделяя звездочками, наименование комплектующего, его УИД и количество данного комплектующего для данного комплекта. Например, в комплекте "Спальня" будет 2 тумбочки и 1 кровать.

В качестве комплектующего можно брать как простой товар, так и конкретное торговое предложение. Наименование передается просто для упрощения отладки. Синхронизация идет по УИДам.

Забегая вперед, отмечу, что выгрузку комплектов по понятным причинам следует вести, когда составные части уже выгружены - это легко решается на стороне 1С созданием 2х узлов обмена с соответствующими отборами либо просто выгрузкой в 2 прохода.

Итак, у нас выгружается комплект в виде простого товара и мы решили, в каком виде мы хотим передать на сайт его состав. Осталось получить его состав. Я делаю это в процедуре ВыгрузитьТоварыXDTO, хотя мои читатели могут найти более оптимальный вариант, делаю запрос к базе и добавляю в реквизиты необходимую мне информацию о комплектующих.

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

 Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| КомплектыСрезПоследних.Документ
|ИЗ
| РегистрСведений.Комплекты.СрезПоследних(, Комплект = &Комплект) КАК КомплектыСрезПоследних
|
|УПОРЯДОЧИТЬ ПО
| ВЫБОР
| КОГДА КомплектыСрезПоследних.ТипДокумента = ЗНАЧЕНИЕ(Перечисление.ТипыДокументовРазбораКомплектов.ТехнологическаяКарта)
| ТОГДА 0
| ИНАЧЕ ВЫБОР
| КОГДА КомплектыСрезПоследних.ТипДокумента = ЗНАЧЕНИЕ(Перечисление.ТипыДокументовРазбораКомплектов.Калькуляция)
| ТОГДА 1
| ИНАЧЕ ВЫБОР
| КОГДА КомплектыСрезПоследних.ТипДокумента = ЗНАЧЕНИЕ(Перечисление.ТипыДокументовРазбораКомплектов.ПропорцииРазделки)
| ТОГДА 2
| ИНАЧЕ 3
| КОНЕЦ
| КОНЕЦ
| КОНЕЦ,
| КомплектыСрезПоследних.Период УБЫВ";
Запрос.УстановитьПараметр("Комплект", ТекТовар.Номенклатура.Ссылка);
Выборка = Запрос.Выполнить().Выбрать();

Но! Какая бы конфигурация у вас ни была, у вас в коде конфигурации есть готовый код этого запроса. Ищите глобальным поиском по слову КомплектыСрезПоследних или просто по слову Комплекты запрос, похожий на тот, что у меня в примере, и используйте его.

В итоге наша выгрузка товаров должна обладать теми дополнительными реквизитами, которые я привела выше.

Далее необходимо поработать на стороне сайта.

Нам нужен обработчик события OnAfterIBlockElementUpdate и OnAfterIBlockElementAdd - вешаемся на них и смотрим: если в реквизитах товара передан ТипНоменклатуры Комплект тогда перебираем реквизиты комплектующие, и ищем по внешним кодам товары и/или торговые предложения (как я уже отметила выше, в этот момент они уже должны быть на сайте). Далее на основании найденного готовим массив параметров для стандартных битриксовских функций работы с комплектами:

создание нового комплекта:

$arSaveSet = array(
'TYPE'    => 1,
'ITEM_ID' => $arFields['ID'],
'ACTIVE'  => "Y",
'ITEMS'   => $items
);
$setId = CCatalogProductSet::add($arSaveSet);
CCatalogProductSet::recalculateSetsByProduct($arFields['ID']);

апдейт старого:

$arSaveSet = array(
'ITEMS'   => $items
);
CCatalogProductSet::update($arSetsByProduct['SET_ID'],$arSaveSet); // апдейт "комплекта"
CCatalogProductSet::recalculateSetsByProduct($arFields['ID']); 

В обработчике, естественно, нельзя забывать о возможности его зацикливания, а заодно и о том, что тип товара необходимо изменить, если мы только еще создаем комплект:

class YBWSMoyKomplectyImport {
public static $disableHandler = false;
function onAfterProductUpdate(&$arFields)
{
  if (self::$disableHandler)
            return;
            ...
                               self::$disableHandler = true;

$arFields2 = array('TYPE' => 1);
CCatalogProduct::Update($arFields['ID'], $arFields2);

self::$disableHandler = false;
                     ...

         }
      ...
}

При наличии проблем с импортом комплектов, где комплектующее - предложение, обновляйте Битрикс до последней версии.

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

Собственно, на этом все. 

Комментариев нет: