Новый шаблон sale.order.ajax: кастомизация

Изображение
На реализацию этого функционала ушло порядка 30 часов рабочего времени (плюс время на самообразование). За это время было отправлено 18 коммитов, написано 371 строк кода и осуществлено несколько попыток виртуального суицида :) Основная задача Создать группу свойств "Параметры доставки", которая будет зависеть от выбора типа доставки. Для курьера это "Адрес доставки", для "Транспортной компании" это выбор ТК из выпадающего списка, для доставки "Другая транспортная компания" - тоже текстовое поле (как и адрес доставки). Все эти поля являются обязательными, и отображаться должны не в блоке "Пользователь", а в блоке с доставками. В новом шаблоне sale.order.ajax перенести поля в другой блок не так просто, как кажется на первый взгляд, а информации на эту тему буквально крупицы.

Кастомизация импорта 1С при помощи обработчиков событий Битрикс

У клиента появилась интересная задача: после обмена данных с 1С автоматически выставлять флаг "Новинка" для тех товаров, количество которых изменилось в большую сторону.
Было несколько вариантов реализации. Первый, что пришел в голову - использовать событие OnBeforeIblockUpdate, сравнивать сколько было- сколько стало, и выставлять флаг "Новинка".

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

Коллега с форума Битрикса посоветовала наследовать класс импорта и переопределить в нем функцию ImportElement.

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

Самым разумным решением показалось всё же использовать события. Правда, это было все же не OnBeforeIblockUpdate, а OnBeforeProductUpdate, так как поле "Доступное количество" относится именно к классу CProduct (как и другие свойства, касающиеся интернет-магазина), а в IBlock хранятся описания, название, свойства товара (кстати, поле "Новинка" как раз среди них).

Для "эмуляции" работы 1с был скачан вот такой прекрасный скрипт.
Также от клиента была получена выгрузка, состоящая из 4 товаров для тестирования.

Какие же параметры поддерживает наше событие? Что хранится в arResult?
А хранится там как раз нужное нам количество QUANTITY и ряд других ненужных нам свойств (например, о включении налога и прочее).

Ну что ж, теперь мы знаем что количество, которое пришло из 1с, внутри события хранится в arResult[QUANTITY]. А с чем сравнивать будем? 

Тут следует отметить, что в событиях типа update, помимо ArResult, передается также id изменяемого элемента. Он нам и понадобится, чтобы добраться до элемента инфоблока и его свойства Новинка. 

Обращаемся к классу CIBlockElement, используя метод getByID, получаем наш товар.
Смотрим, как называется свойство - newproduct.
И тут - внимание. - нужно обязательно учитывать, что при обновлении одного свойства остальные затираются! Так что нам нужно использовать цикл:
    $ELEMENT_ID = $ID;  // код элемента
    $PROPERTY_CODE = "NEWPRODUCT";  // код свойства
    $PROPERTY_VALUE = "211";  // значение свойства

    // Установим новое значение для данного свойства данного элемента
    $dbr = CIBlockElement::GetList(array(), array("=ID"=>$ELEMENT_ID), false, false, array("ID", "IBLOCK_ID"));
    if ($dbr_arr = $dbr->Fetch())
    {
      $IBLOCK_ID = $dbr_arr["IBLOCK_ID"];
      CIBlockElement::SetPropertyValues($ELEMENT_ID, $IBLOCK_ID, $PROPERTY_VALUE, $PROPERTY_CODE);
    }

При этом свойству Новинка должно быть присвоено не просто Y, как могло показаться в начале. 
Это свойство у нас импортировано из 1с, так что нам нужно узнать id нужного нам значения. Это оказалось "211".

Ну вот мы и получили работающий скрипт. Теперь нужно будет также учесть ситуацию, когда добавляется товар совсем новый, которого еще нет в каталоге. 
И еще реализовать пожелание клиента снимать галочку новинки по прошествии 30 дней (этот параметр должен задаться администратором сайта через админку).

О моих последующих работах с этой задачей будут написаны следующие посты. 
А вот и полный код
AddEventHandler("catalog", "OnBeforeProductUpdate", "MyOnBeforeProductUpdate");
function MyOnBeforeProductUpdate($ID,$arFields)
{
  $product=CCatalogProduct::GetByID($ID); //достаем массив значений для изменяемого товара (кол-во, цена)
  $old_quantity=$product["QUANTITY"]; //сохраняем предыдущее количество
  if ($old_quantity<$arFields["QUANTITY"]) //если предыдущее количество меньше нового (добавился товар)
  {
    //выставлять флаг новинки
    $element=CCatalogProduct::GetByIDEx($ID); //достаем массив значений для инфоблока товара (название, описание, свойства)
    

    $ELEMENT_ID = $ID;  // код элемента
    $PROPERTY_CODE = "NEWPRODUCT";  // код свойства
    $PROPERTY_VALUE = "211";  // значение свойства

    // Установим новое значение для данного свойства данного элемента
    $dbr = CIBlockElement::GetList(array(), array("=ID"=>$ELEMENT_ID), false, false, array("ID", "IBLOCK_ID"));
    if ($dbr_arr = $dbr->Fetch())
    {
      $IBLOCK_ID = $dbr_arr["IBLOCK_ID"];
      CIBlockElement::SetPropertyValues($ELEMENT_ID, $IBLOCK_ID, $PROPERTY_VALUE, $PROPERTY_CODE);
    }

  /*echo '
'; echo $old_quantity; print_r($element); echo '
'; die();*/
    
  }
}

Собственно, строка:
    $element=CCatalogProduct::GetByIDEx($ID); //достаем массив значений для инфоблока товара (название, описание, свойства)
нужна только для отладки, чтобы вывести редактируемый элемент ниже (закомментированные строки с print_r), поэтому по окончании отладки их можно (даже нужно) убрать.

Комментарии

Популярные сообщения из этого блога

Новый шаблон sale.order.ajax: кастомизация

Вывод пользовательского свойства раздела в компонентах catalog.section и news.list

Если при полной выгрузке из 1С в битрикс товары и разделы приходят неактивными