Заполнить свойство инфоблока ценой из торгового каталога

Заполнить свойство инфоблока ценой из торгового каталога
Просмотров: 380 | Комментариев: 0

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

Итак: у нас есть инфоблок торгового каталога, в котором мы хотим заполнить свойство типа число (или строка) стоимостью элемента. В моем случае, код этого свойства "ATT_PRICE"

Единоразовое заполнение или по необходимости

Если нужно выполнить заполнение один раз или в ручную, по необходимости.

Создаем новую страничку на сайте (можно ограничить к ней доступ, только для администраторов) и вставляем туда такой код, подсказки по коду, прямо внутри:

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

$IBLOCK_ID = 34; //Инфоблок с которым работаем

//Получаем ID всех элементов
$addProps = CIBlockElement::GetList (
	Array("ID" => "ASC"),
	Array("IBLOCK_ID" => $IBLOCK_ID),
		false,
		false,
		Array(
			'ID'
		)
);
while($ar_fields = $addProps->GetNext())
{
$arProductID =  $ar_fields['ID'];
//Узнаем цену элемента
    $rsPrices = CPrice::GetList(
        array(),
        array(
            "PRODUCT_ID" => $arProductID,
        )
    );
    while($arPrice = $rsPrices->Fetch())
    //Передаем цену в переменную
    {
       $PropPrice = $arPrice["PRICE"];
    }
    //Заполняем свойство с кодом "ATT_PRICE" ценой
    CIBlockElement::SetPropertyValuesEx(
        $arProductID,
        $IBLOCK_ID,
        array(
            "ATT_PRICE" => $PropPrice,
        )
    );
}

Сохраняем и открываем в браузере. Скрипт отработает и у всех товаров заполнится свойство ATT_PRICE. Учтите, что если у вас большой каталог, это может занять некоторое время. Если каталог очень большой, убедитесь что работа не завершится по таймауту. Я пробовал на каталоге с 50 000-ами товаров. Код отработал за 12 секунд

Далее, можете выполнять этот код в ручную или повесить выполнение на крон.

Постоянная работа скрипта. Обработчик в init.php

Если вам нужно, что бы свойство ATT_PRICE обновлялось постоянно, при каждом добавлении товаров и обновлении цен. Например, при обмене с 1С

Можете добавить обработчик в init.php. Код основан на томже, что приведен выше, в принципе выполняет теже самые действия по событиям обновления/добавления элементов

AddEventHandler("iblock", "OnAfterIBlockElementUpdate", "DoIBlockAfterSave");
AddEventHandler("iblock", "OnAfterIBlockElementAdd", "DoIBlockAfterSave");
AddEventHandler("catalog", "OnPriceAdd", "DoIBlockAfterSave");
AddEventHandler("catalog", "OnPriceUpdate", "DoIBlockAfterSave");
function DoIBlockAfterSave($arg1, $arg2 = false) {
	
CModule::IncludeModule('iblock');
CModule::IncludeModule('catalog');
CModule::IncludeModule('currency');
 
    $IBLOCK_ID = 34;
	      if (is_array($arg2) && $arg2["PRODUCT_ID"] > 0) {
	         $ELEMENT_ID = $arg2["PRODUCT_ID"];
	      } elseif (is_array($arg1) && $arg1["ID"] > 0) {
	         $arElementFields = CIBlockElement::GetByID($arg1["ID"])->GetNext();
	         if(in_array($arElementFields["IBLOCK_ID"],array($IBLOCK_ID))) {
	            $ELEMENT_ID = $arg1["ID"];
	         }
	      }
      
        $arProductID = array($ELEMENT_ID);
       
        $rsProperty = CIBlockProperty::GetByID("PRICE", $IBLOCK_ID);
        $arProperty = $rsProperty->Fetch();
	$arPropCache[$IBLOCK_ID] = $arProperty["ID"];
		
	$rsPrices = CPrice::GetList(
            array(),
            array(
                "PRODUCT_ID" => $arProductID,
            )
        );
        while($arPrice = $rsPrices->Fetch())
        {
	$PRICE = $arPrice["PRICE"];
        $PropPrice = $PRICE;
        }
        CIBlockElement::SetPropertyValuesEx(
            $ELEMENT_ID,
            $IBLOCK_ID,
                array(
                    "ATT_PRICE" => $PropPrice,
            )
        );
}

Полезные дополнения:

Если хотите сконвертировать цену в другую валюту. Например: цена в каталоге указана в долларах, а в свойство должна попасть в рублях по курсу модуля валют.

Воспользуйтесь методом CCurrencyRates::ConvertCurrency в части получения цены товара

$strDefaultCurrency = CCurrency::GetBaseCurrency();
$arPrice["PRICE"] = CCurrencyRates::ConvertCurrency($arPrice["PRICE"], $arPrice["CURRENCY"], $strDefaultCurrency);
$PRICE = $arPrice["PRICE"];
$PropPrice = $PRICE;

Если нужно получить больше информации о свойстве ATT_PRICE. Например получить ее ID, проверить на заполненность итд. Воспользуйтесь методом CIBlockProperty::GetByID:

$rsProperty = CIBlockProperty::GetByID("ATT_PRICE", $IBLOCK_ID);
$arProperty = $rsProperty->Fetch();
$arPropCache[$IBLOCK_ID] = $arProperty["ID"];