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

Йо-йо! Сегодня я столкнулся с непростой и как мне кажется глупой задачей. Все кто давно работают с битриксом знают, что они постоянно продвигают торговые предложения. Однако в 1С это до сих пор «не завезли» и каждый пилит свои костыли.

Сегодня (19.04.2019) я сам столкнулся с тем, что мне не могли выгрузить вес, высоту, ширину, длину товара в параметры торгового каталога у торговых предложений и загружали их в реквизиты товара. Чтобы было понятно, что такое реквизиты, вот вам скриншот

реквизиты товара из 1С в 1С-Битрикс

И вот из этого места мне нужно положить в это

В торговом предложении вкладка Торговый каталог -> Параметры

И всё это мне нужно, чтобы доставка у торговых предложений считалась корректно.

Я помыкался по форумам, вроде там кто-то что-то сделал, однако код не выложил. То что я нашёл на других сайтах мне не помогло. И без лишней лирики я покажу вам как решил данную задачу.

Получение данных из реквизитов

Это не очень простая задача. Сначала у меня не выходило получить все данные, которые мне были нужны, но я не понимал из-за чего. Потом на одном из форумов я увидел, что у человека уже была проблема похожая на мою и решение оказалось следующим:

Нужно поменять место хранения товаров и торговых предложений на «отдельная таблица» в настройках инфоблоков «Значения свойств хранятся:»

Далее по коду:

// Подключение модуля
CModule::IncludeModule('iblock');

// Получение свойств товаров из инфоблока с ID 36, у меня это id каталога товаров
$addProps = CIBlockElement::GetList (
    Array("ID" => "ASC"),
    Array("IBLOCK_ID" => 36),
        false,
        false,
        Array(
            'ID', 'PROPERTY_CML2_TRAITS'
        )
);

// Полученные свой перепаковываю
while($ar_fields = $addProps->GetNext())
{
    // Получение свойств из реквизитов
    // Описание реквизитов, например, Ширина
    $arrDesc = $ar_fields['PROPERTY_CML2_TRAITS_DESCRIPTION'];
    // Значение
    $arrValue = $ar_fields['PROPERTY_CML2_TRAITS_VALUE'];
    $arrThmb = [];
    // Получение ассоциативного массива 
    forEach($arrDesc as $key=>$value ){
        $arrThmb[$value] = $arrValue[$key];
    }
    // Получение конечного массива, без лишних свойств реквизитов
    $arrResult['ID'] = $ar_fields['ID'];
    $arrResult['Ширина'] = $arrThmb['Ширина'];
    $arrResult['Высота'] = $arrThmb['Высота'];
    $arrResult['Глубина'] = $arrThmb['Глубина'];
    $arrResult['Вес в упаковке'] = $arrThmb['Вес в упаковке'];
} 

Получение торговых предложений

Подключим ещё модуль каталога Cmodule::IncludeModule(‘catalog’) и получим id торговых предложений товара.

// Подключение модуля каталог
Cmodule::IncludeModule('catalog');
CModule::IncludeModule('iblock');

$addProps = CIBlockElement::GetList (
    Array("ID" => "ASC"),
    Array("IBLOCK_ID" => 36),
        false,
        false,
        Array(
            'ID', 'PROPERTY_CML2_TRAITS'
        )
);

while($ar_fields = $addProps->GetNext())
{
    // print_r($ar_fields);
    // Получение свойств 
    $arrDesc = $ar_fields['PROPERTY_CML2_TRAITS_DESCRIPTION'];
    $arrValue = $ar_fields['PROPERTY_CML2_TRAITS_VALUE'];
    $arrThmb = [];
    forEach($arrDesc as $key=>$value ){
        $arrThmb[$value] = $arrValue[$key];
    }
    $arrResult['ID'] = $ar_fields['ID'];
    $arrResult['Ширина'] = $arrThmb['Ширина'];
    $arrResult['Высота'] = $arrThmb['Высота'];
    $arrResult['Глубина'] = $arrThmb['Глубина'];
    $arrResult['Вес в упаковке'] = $arrThmb['Вес в упаковке'];
    // Получение торговых предложений
    $res = CCatalogSKU::getOffersList(
        $ar_fields['ID'], 
        $iblockID = 0,
        $skuFilter = array(), 
        $fields = array('ID'),  
        $propertyFilter = array()
     );
    // Массив по которому будем проходиться
   $arr = $res[$ar_fields['ID']];

}

Т.к. CCatalogSKU::getOffersList() возвращает данные для массива товаров, мы должны «перейти» на уровень глубже в массив. Для этого и нужна была строка $arr = $res[$ar_fields[‘ID’]];

Запись новых данных в торговое предложение

Теперь нам нужно пройтись по массиву id-шников торговых предложений и изменить вес, ширину, высоту и длину у них. И сделаем мы это с помощью функции CCatalogProduct::Update($PRODUCT_ID, $arFields)

Cmodule::IncludeModule('catalog');
CModule::IncludeModule('iblock');

$addProps = CIBlockElement::GetList (
    Array("ID" => "ASC"),
    Array("IBLOCK_ID" => 36),
        false,
        false,
        Array(
            'ID', 'PROPERTY_CML2_TRAITS'
        )
);

while($ar_fields = $addProps->GetNext())
{
    // print_r($ar_fields);
    // Получение свойств 
    $arrDesc = $ar_fields['PROPERTY_CML2_TRAITS_DESCRIPTION'];
    $arrValue = $ar_fields['PROPERTY_CML2_TRAITS_VALUE'];
    $arrThmb = [];
    forEach($arrDesc as $key=>$value ){
        $arrThmb[$value] = $arrValue[$key];
    }
    $arrResult['ID'] = $ar_fields['ID'];
    $arrResult['Ширина'] = $arrThmb['Ширина'];
    $arrResult['Высота'] = $arrThmb['Высота'];
    $arrResult['Глубина'] = $arrThmb['Глубина'];
    $arrResult['Вес в упаковке'] = $arrThmb['Вес в упаковке'];
    // Получение торговых предложений
    $res = CCatalogSKU::getOffersList(
        $ar_fields['ID'], 
        $iblockID = 0,
        $skuFilter = array(), 
        $fields = array('ID'),  
        $propertyFilter = array()
     );

        $arr = $res[$ar_fields['ID']];
    // Изменение данных у торговых предложений
        forEach($arr as $key=>$value){
            $PRODUCT_ID = $key; // id торгового предложения
   // Перечисление свойств
            $arFields = array(
                'WEIGHT' => $arrResult['Вес в упаковке'],
                'WIDTH' => $arrResult['Ширина'],
                'LENGTH' => $arrResult['Глубина'],
                'HEIGHT' => $arrResult['Высота']
            );
            CCatalogProduct::Update($PRODUCT_ID, $arFields);
        };


}

Событие выгрузки из 1С

Т.к. перезапись нужна каждый раз когда выгружается товар из 1С, нам нужно поставить обработчик события. Для этого мы идём в наши файлы по адресу \bitrix\php_interface, находим там файлы init.php и пишем:

AddEventHandler("catalog", "OnSuccessCatalogImport1C", "myCustomImportMod");

function myCustomImportMod($arg1, $arg2 = false){
   // Код, который был написан ранее
}

P.S.

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