На одном из проектов, нужно было единоразово заполнить цены товаров из свойства инфоблока. Сделать это можно через API, методами CPrice::Update и CPrice::Add.
Копируем цену из свойства используя D7
Итак: имеем инфоблок, в котором, у каждого элемента заполнено свойство типа срока и называется "Минимальная цена" c кодом "ATT_PRICE". Нам нужно заполнить этим свойством, базовую цену. По сути, скопировать значение этого свойства в цену элемента.
Cоздаем в корне сайта файл addprice.php и добавляем в него код:
require($_SERVER["DOCUMENT_ROOT"] . "/bitrix/modules/main/include/prolog_before.php");
use Bitrix\Catalog\Model\Price;
use Bitrix\Main\Loader;
use Bitrix\Iblock\ElementPropertyTable;
use Bitrix\Iblock\ElementTable;
Loader::includeModule('catalog');
$iblockId = 3; // Идентификатор инфоблока
$catalogGroupId = 1; // ID типа цены
$propertyId = 33; // ID свойства из которого копируем
$elements = ElementTable::getList([
'filter' => ['IBLOCK_ID' => $iblockId],
'select' => ['ID'],
]);
while ($element = $elements->fetch()) {
$propertyValue = ElementPropertyTable::getList([
'filter' => [
'IBLOCK_ELEMENT_ID' => $element['ID'],
'IBLOCK_PROPERTY_ID' => $propertyId,
],
'select' => ['VALUE'],
])->fetch();
if ($propertyValue) {
$priceValue = $propertyValue['VALUE'];
$priceData = [
'PRODUCT_ID' => $element['ID'],
'CATALOG_GROUP_ID' => $catalogGroupId,
'PRICE' => $priceValue,
'CURRENCY' => 'RUB',
];
$existingPrice = Price::getList([
'filter' => [
'PRODUCT_ID' => $element['ID'],
'CATALOG_GROUP_ID' => $catalogGroupId,
],
])->fetch();
if ($existingPrice) {
Price::update($existingPrice['ID'], $priceData);
} else {
Price::add($priceData);
}
}
}
require($_SERVER["DOCUMENT_ROOT"] . "/bitrix/modules/main/include/epilog_after.php");
Открываем в браузере и ждем выполнения. Этот код использует D7 и методы \Bitrix\Catalog\Model\Price::add и \Bitrix\Catalog\Model\Price::update, как рекомендовано в документации. Он также использует \Bitrix\Iblock\ElementTable для получения элементов инфоблока, что является более современным подходом.
Постоянное обновление цены из свойства. Cron задание.
Если нужно, что бы цена обновлялась из свойства постоянно. Например, каталог обновляется автоимпортом, каждую ночь и цена пишется именно в свойство, а не в нормальное поле. Можно создать скрипт обновления и запускать его по cron. В директории /bitrix/php_interface/include/ создаем файл cron_price_refresher.php и добавляем в него:
$_SERVER["DOCUMENT_ROOT"] = realpath(dirname(__FILE__)."/../../..");
$DOCUMENT_ROOT = $_SERVER["DOCUMENT_ROOT"];
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_before.php");
@set_time_limit(0);
define("NO_KEEP_STATISTIC", true);
define("NOT_CHECK_PERMISSIONS", true);
use Bitrix\Catalog\Model\Price;
use Bitrix\Main\Loader;
use Bitrix\Iblock\ElementPropertyTable;
use Bitrix\Iblock\ElementTable;
Loader::includeModule('catalog');
$iblockId = 3; // Идентификатор инфоблока
$catalogGroupId = 1; // ID типа цены
$propertyId = 33; // ID свойства из которого копируем
$elements = ElementTable::getList([
'filter' => ['IBLOCK_ID' => $iblockId],
'select' => ['ID'],
]);
while ($element = $elements->fetch()) {
$propertyValue = ElementPropertyTable::getList([
'filter' => [
'IBLOCK_ELEMENT_ID' => $element['ID'],
'IBLOCK_PROPERTY_ID' => $propertyId,
],
'select' => ['VALUE'],
])->fetch();
if ($propertyValue) {
$priceValue = $propertyValue['VALUE'];
$priceData = [
'PRODUCT_ID' => $element['ID'],
'CATALOG_GROUP_ID' => $catalogGroupId,
'PRICE' => $priceValue,
'CURRENCY' => 'RUB',
];
$existingPrice = Price::getList([
'filter' => [
'PRODUCT_ID' => $element['ID'],
'CATALOG_GROUP_ID' => $catalogGroupId,
],
])->fetch();
if ($existingPrice) {
Price::update($existingPrice['ID'], $priceData);
} else {
Price::add($priceData);
}
}
}
require($_SERVER["DOCUMENT_ROOT"] . "/bitrix/modules/main/include/epilog_after.php");
Здесь мы, подключили ядро битрикс, без шаблона и отключили статистику с проверкой прав. Добавляем выполнение этого кода в cron задания (в примере, каждое утро в 7 часов). Это /usr/bin/php81/bin/php -f - путь к интерпритатору php, на вашем окружении может отличаться
0 7 * * * /usr/bin/php81/bin/php -f /ПУТЬ_ДО_САЙТА_НА_СЕРВЕРЕ/bitrix/php_interface/include/cron_price_refresher.php
PS: Понятное дело, можно добавить обработчик с событиями обновления добавления элементов в init.php - но это не всегда подходит. Обновление цен с параллельной загрузкой каталога- ресурсоемкая процедура. На больших каталогах, потребуется либо мощный, дорогой сервер.