Пошаговое обновление цен товаров каталога Битрикс

Если нужно в большом количестве обновлять цены товаров, то лучше это сделать пошагово. В примере обновление цен по разделам, для этого были созданы свойства UF_MARKUP_SUM и UF_MARKUP_COEFF где прописываются наценки для каждого раздела, сумма и коэффициент, и по формуле от базовой цены делается наценка на товар, новая цена прописывается в другой тип цены.

При каждом шаге записывается в файл айди товара и раздел по которому было последнее обновление, чтобы следующий шаг обновления цен начать с этого места. Скрипт можно установить на cron, или выполнять  в фоновом режиме на ajax.
logo
logo
PHP
<?
require_once($_SERVER['DOCUMENT_ROOT']."/bitrix/modules/main/include/prolog_before.php");

class Price {

    public  $catalog_id     = 32;         //Айди каталога
    public  $price_type     = 2;          //Тип цены
    public  $file           = "data.txt"; //Файл для записи последнего обновленного товара и его раздела
    public  $limit_products = 1000;       //Лимит обновления товаров за один шаг


    //Выбираем разделы каталога
    public function getSectionsCatalog()
    {
        CModule::IncludeModule("iblock");

        $arFilter = array('IBLOCK_ID' => $this->catalog_id, "ACTIVE" => "Y");
        $rsSect = CIBlockSection::GetList(array('SORT' => 'ASC'), $arFilter, false, Array("UF_*"));
        $sections = [];

        while($arSect = $rsSect->GetNext())
        {
            $sections[] = $arSect;
        }

        return $sections;
    }


    //Обновляем цены товаров по разделам
    public function updatePricesProductsSection($sections)
    {
        $data = $this->readDataFile($this->file);

        foreach($sections as $section)
        {
            if(!empty($data) && $data['product_id'] > 0)
            {
                if($data['section_id'] == $section["ID"])
                {
                    $this->updatePricesProducts($section, $data['product_id']);
                    break;
                }
            }
            else
            {
                //Если незаполнены наценки, пропускаем раздел
                if(empty($section["UF_MARKUP_SUM"]) && empty($section["UF_MARKUP_COEFF"]))
                    continue;

                //Если в разделе обновлены все цены товаров, пропускаем раздел
                if((!empty($data) && $data['product_id'] == 0) && $data['section_id'] == $section["ID"])
                    continue;

                $this->updatePricesProducts($section);
                break;
            }
        }

    }


    //Обновляем цены товаров
    public function updatePricesProducts($section, $product_id = false)
    {
        CModule::IncludeModule("iblock");
        CModule::IncludeModule("catalog");

        if($product_id > 0)
        {
            $arFilter = Array("IBLOCK_ID" => $this->catalog_id, "ACTIVE" => "Y", "IBLOCK_SECTION_ID" => $section['ID'], ">ID" => $product_id);
        }
        else
        {
            $arFilter = Array("IBLOCK_ID" => $this->catalog_id, "ACTIVE" => "Y", "IBLOCK_SECTION_ID" => $section['ID']);
        }

        $res = CIBlockElement::GetList(Array("ID" => "ASC",), $arFilter, false, Array("nPageSize" => $this->limit_products), Array());

        $product_id = 0;
        $section_id = $section['ID'];

        while($ob = $res->GetNextElement())
        {
            $arFields = $ob->GetFields();
            $arr_base = CPrice::GetBasePrice($arFields['ID']);

            if(empty($arr_base['PRICE']))
                continue;

            $price = $arr_base['PRICE'];
            $currency = $arr_base['CURRENCY'];

            $price = ($price + $section["UF_MARKUP_SUM"]) * $section["UF_MARKUP_COEFF"];
            $this->updatePriceProduct($arFields['ID'], $price, $currency, $this->price_type);

            $product_id = $arFields['ID'];
        }

        $data = ['product_id' => $product_id, "section_id" => $section_id];
        $this->writeDataFile($data, $this->file);

    }


    //Обновляем цену товара
    public function updatePriceProduct($product_id, $price, $currency, $price_type)
    {
        CModule::IncludeModule("catalog");

        $arFields = Array(
            "PRODUCT_ID"       => $product_id,
            "CATALOG_GROUP_ID" => $price_type,
            "PRICE"            => $price,
            "CURRENCY"         => $currency,
            "QUANTITY_FROM"    => false,
            "QUANTITY_TO"      => false
        );

        $res = CPrice::getList(
            array(),
            array(
                "PRODUCT_ID"       => $product_id,
                "CATALOG_GROUP_ID" => $price_type
            )
        );

        if($arr = $res->Fetch())
        {
            CPrice::Update($arr["ID"], $arFields);
        }
        else
        {
            CPrice::Add($arFields);
        }
    }


    //Чтение данных с файла
    public function readDataFile($file)
    {
        if(!file_exists($file))
        {
            fopen($file , 'w');
            fclose($file);
        }

        $fp = fopen($file, "r");
        if($fp)
        {
            while (!feof($fp))
            {
                $json = fgets($fp, 999);
            }
        }
        fclose($fp);
        $data = json_decode($json, true);
        return $data;
    }


    //Запись данных в файл
    public function writeDataFile($data, $file)
    {
        if(!file_exists($file))
        {
            fopen($file , 'w');
            fclose($file);
        }

        $json = json_encode($data);

        print $json;

        $fp = fopen($file, "w+");
        fwrite($fp, $json);
        fclose($fp);
    }


}


$price = new Price();
$sections = $price->getSectionsCatalog();
$price->updatePricesProductsSection($sections);


Спасибо! Заявка успешно отправлена, мы с Вами свяжемся в ближайшее время!