Меню

Запретить изменения описаний товаров при выгрузке из 1С УТ на сайт

Просмотров: 23966

При разработке сайтов на Битрикс, с интеграцией с 1С Управление Тороговлей, нужно запретить изменения полей при обмене. В частности, детальное описание и картинку товара.

изменения описаний товаров при выгрузке

Если вы используете 1C для выгрузки структуры каталога, цен, торговых предложений и свойств товаров на ваш сайт, а описания и картинки вы добавляете уже после выгрузки, то у вас могут возникнуть проблемы. При обмене данными, информация, добавленная на сайте, может быть перезаписана. Это происходит потому, что 1C "видит", что у товара нет описания (в своей базе), но на сайте оно присутствует, и поэтому происходит удаление этого товара.

Чтобы избежать такой ситуации, можно воспользоваться событиями OnBeforeIBlockElementUpdate и OnBeforeIBlockElementAdd. Для этого добавьте следующий код в файл /bitrix/php_interface/init.php (если файла нет, создайте его):


AddEventHandler("iblock", "OnBeforeIBlockElementUpdate","DoNotUpdate");
function DoNotUpdate(&$arFields)
{
    if ($_REQUEST['mode'] == 'import') {
        unset($arFields['PREVIEW_PICTURE']);
        unset($arFields['DETAIL_PICTURE']);
        unset($arFields['PREVIEW_TEXT']);
        unset($arFields['DETAIL_TEXT']);
    }
}

AddEventHandler("iblock", "OnBeforeIBlockElementAdd","DoNotAdd");
function DoNotAdd(&$arFields)
{
    if ($_REQUEST['mode'] == 'import') {
        unset($arFields['PREVIEW_PICTURE']);
        unset($arFields['DETAIL_PICTURE']);
        unset($arFields['PREVIEW_TEXT']);
        unset($arFields['DETAIL_TEXT']);
    }
}

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

Аналог на D7 для запрета изменений при обмене данными

Вы также можете использовать D7 для реализации запрета на изменение полей при обмене данными. Вот пример кода:

use Bitrix\Main\EventManager;

EventManager::getInstance()->addEventHandler(
    'iblock',
    'OnBeforeIBlockElementUpdate',
    'DoNotUpdate'
);

EventManager::getInstance()->addEventHandler(
    'iblock',
    'OnBeforeIBlockElementAdd',
    'DoNotAdd'
);

function DoNotUpdate(&$arFields)
{
    if ($_REQUEST['mode'] == 'import') {
        unset($arFields['PREVIEW_PICTURE']);
        unset($arFields['DETAIL_PICTURE']);
        unset($arFields['PREVIEW_TEXT']);
        unset($arFields['DETAIL_TEXT']);
    }
}

function DoNotAdd(&$arFields)
{
    if ($_REQUEST['mode'] == 'import') {
        unset($arFields['PREVIEW_PICTURE']);
        unset($arFields['DETAIL_PICTURE']);
        unset($arFields['PREVIEW_TEXT']);
        unset($arFields['DETAIL_TEXT']);
    }
}

Дополнено: изменение полей товара при обмене с 1С

Написано спустя какое-то время, в обсуждении к заметке описаны случаи когда нужно изменить информацию о товарах, а не о элементах (это немного разное).

Дополняю: обновление габаритов товаров после обмена с 1С, например нужно увеличить все габариты на 1000:

AddEventHandler("iblock", "OnAfterIBlockElementAdd", "UpdateDimensionsAfterElementAddOrUpdate");
AddEventHandler("iblock", "OnAfterIBlockElementUpdate", "UpdateDimensionsAfterElementAddOrUpdate");

function UpdateDimensionsAfterElementAddOrUpdate(&$arFields)
{
    if (CModule::IncludeModule("iblock") && CModule::IncludeModule("catalog")) {
        if ($_REQUEST['mode'] == 'import' || $_REQUEST['mode'] == 'update') {
            // Обновление габаритов (увеличение на 1000 из 1С)
            $arProduct = CCatalogProduct::GetByID($arFields['ID']);
            if ($arProduct) {
                $updatedFields = array(
                    'WIDTH' => $arProduct['WIDTH'] * 1000,
                    'LENGTH' => $arProduct['LENGTH'] * 1000,
                    'HEIGHT' => $arProduct['HEIGHT'] * 1000
                );
                CCatalogProduct::Update($arFields['ID'], $updatedFields);
            }
        }
    }
}

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

Информацию о товаре (как товаре) получаем и обновляем методами CCatalogProduct::GetByID и CCatalogProduct::Update

Alex 04.11.2022
Подскажите пожалуйста. Делаю выгрузку на сайт, описание падает в анонс. Написал обработку в init.php но он не срабатывает

AddEventHandler("catalog", "OnBeforeProductUpdate", Array("My_Class", "OnBeforeProductUpdate"));

Код
class My_Class
   {
      function OnBeforeProductUpdate(&$arFields)
         {
            if (@$_REQUEST['mode']=='import')//импорт из 1с?
         {
         $arFields["PREVIEW_TEXT"]=$arFields["DETAIL_TEXT"];
         }
      }
   }

Подскажите как исправить
Михаил Базаров 04.11.2022
Это событие устарело, не сработает если отключена поддержка устаревших событий в модуле каталога.

Попробуйте использовать OnAfterIBlockElementUpdate
Как-то так, не проверял.
Код
AddEventHandler("iblock", "OnAfterIBlockElementUpdate", Array("MyClass", "OnAfterIBlockElementUpdateHandler"));

class MyClass
{
    // создаем обработчик события "OnAfterIBlockElementUpdate"
    function OnAfterIBlockElementUpdateHandler(&$arFields)
    {
           if ($_REQUEST['mode']=='import') {
               $arFields["PREVIEW_TEXT"]=$arFields["DETAIL_TEXT"];
          }
    }
}
Константин 22.03.2023
Добрый день, Михаил!
Есть задача - не передавать названия складов из 1С, а лучше даже менять при выгрузке

В общем нашел такой вариант:

Код
<?
AddEventHandler(&#39;catalog&#39;, &#39;OnBeforeCatalogStoreUpdate&#39;, &#39;storeUpdateHandler&#39;);
function storeUpdateHandler($storeId, &$arFields) {
   if (isset($_GET[&#39;type&#39;], $_GET[&#39;mode&#39;]) && $_GET[&#39;type&#39;] === &#39;catalog&#39; && $_GET[&#39;mode&#39;] === &#39;import&#39;) 
       {
    $newStoreTitle = $arFields[&#39;TITLE&#39;];
    $res = CCatalogStore::GetList([],[
        "ID"    =>   $storeId
    ]);
    if($ar_res = $res->GetNext()) {
        $oldStoreTitle = $ar_res[&#39;TITLE&#39;];
        if ($newStoreTitle !== $oldStoreTitle) {
            print_r(&#39;На сайте наименование склада #&#39;.$storeId.&#39; (&#39;.$oldStoreTitle.&#39;) отличается от наименования в выгрузке (&#39;.$newStoreTitle.&#39;). Наименование не меняем&#39;.PHP_EOL);            $arFields[&#39;TITLE&#39;] = htmlspecialcharsback($oldStoreTitle);         
        }
   }
    }
}   
?>


Переделал его как-то под ваш, не знаю правильно или нет

Код
<?
AddEventHandler(&#39;catalog&#39;, &#39;OnBeforeCatalogStoreUpdate&#39;, &#39;storeUpdateHandler&#39;);
function storeUpdateHandler($storeId, &$arFields) 
{
   if ($_REQUEST[&#39;mode&#39;]==&#39;import&#39;) 
    {
    unset($arFields[&#39;TITLE&#39;]);
    }
}
?>


но здесь идет отмена, а как заменить? сможете подсказать
Константин 22.03.2023
заменить название склада
Михаил Базаров 22.03.2023
Думаю вот так должно получиться

Код
$arFields['TITLE'] = 'NEW NAME';
Гость 05.02.2024
Здравствуйте! а не подскажите как запретить 1с менять расположение разделов. Ну на пример, я убрал с главной страницы пару разделов в под разделы, но 1с после обмена всё выставляет как у него в 1с структурировано. Изменить саму структуру в 1с нельзя по причине "типа менеджерам магазина так сложно искать товары".))))
Михаил Базаров 05.02.2024
Проверить негде, но чисто логически можно
Код
unset($arFields['SECTION_ID']);
unset($arFields['SECTION_CODE']);

Плюс, вроде бы помню это уже обсуждалось в комментариях. Но не точно  :)
Пролистайте всю ветку
https://bazarow.ru/forum/forum1/125-zapretit-izmeneniya-opisaniy-tovarov-pri-vygruzke-iz-1s-ut-na-sayt
Максим 08.07.2024
Чтобы не запретить обновлять поле торговых предложений CML2_LINK, unset не подойдет.
У меня работает такой код в init.php  (может кому то пригодится):
Код
AddEventHandler("iblock", "OnBeforeIBlockElementUpdate","DoNotUpdate");
function DoNotUpdate(&$arFields)
{
    if (($_REQUEST['mode']=='import'))
    {
        $arSelect = Array("ID", "IBLOCK_ID", "NAME", "PROPERTY_CML2_LINK");
        $arFilter = Array("IBLOCK_ID"=>"ИД_ИНФОБЛОКА_ТОРГОВЫХ_ПРЕДЛОЖЕНИЙ", "ID"=>$arFields['ID']);
        $res = CIBlockElement::GetList(Array(), $arFilter, false, Array(), $arSelect);
        while($ob = $res->GetNextElement()){
            $arProps = $ob->GetProperties();
        }
        $arFields['PROPERTY_VALUES'][ИД_СВОЙСТВА_CML2_LINK] = $arProps['CML2_LINK']['VALUE'];
    }
}
Михаил 04.01.2025
Здравствуйте, Михаил. Подскажите, как запретить изменение названия торгового предложения при выгрузке из 1с. При передачи стандартным модулем торговое предложение подставляется в скобках (), что очень неудобно для просмотра. Или как-то удалить эти скобки из наименования в файле /bitrix/php_interface/init.php?
Михаил Базаров 04.01.2025
Должно помочь  unset($arFields['NAME']) только еще проверять в каком инфоблоке
Код
AddEventHandler("iblock", "OnBeforeIBlockElementUpdate","DoNotUpdate");
function DoNotUpdate(&$arFields)
{
    if ($_REQUEST['mode'] == 'import') and 
       ($arFields['IBLOCK_CODE'] == 'offers' // вот тут поковыряйтесь, может там не CODE а XML-ID
    {
        unset($arFields['PREVIEW_PICTURE']);
        unset($arFields['DETAIL_PICTURE']);
        unset($arFields['PREVIEW_TEXT']);
        unset($arFields['DETAIL_TEXT']);
    }
}

Стоимость и сроки разработки сайтов и приложений

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

Интернет магазин: разработка с нуля от 400 000 руб.
от 5-ти недель

Cоздание интернет-магазина на 1С-Битрикс. Разработка с нуля, оптимизация кода под конкретный проект и требования. Реализация любого функционала без ограничений готовых решений.

Интернет-магазин на готовом решении от 100 000 руб.
от 7-ми дней

Готовое решение — вариант для тех, кто не хочет тратить много средств на индивидуальный проект, и не имеет серьезных требований к сайту. Запускается на одном из 200-та (на ваш выбор) готовых решений.

Мобильное приложение от 400 000 руб.
от 1-го месяца

Разработка кроссплатформенного мобильного приложения, которое не уступает нативным решениям как в производительности, так и пользовательском опыте. Публикуется в AppStore, GooglePlay и RuStore

Опросник на разработку. После ознакомления, задам уточняющие вопросы и оценю проект по стоимости и срокам разработки.