Цена товара не выводится, а импорт каждый раз создаёт новую запись. Обычно код обновляет по PRODUCT_ID, хотя update ожидает ID самой записи цены. Исправление — сначала найти запись по товару и типу цены, затем вызвать add или update по результату.
Это код для защищённого административного скрипта или CLI на тестовой копии. Не делайте из него публичный URL, который принимает сумму и ID товара.
Условия перед запуском
Пример рассчитан на одну цену без диапазонов количества. PRODUCT_ID — ID товара или SKU, CATALOG_GROUP_ID — ID существующего типа цены, а ID — ID строки цены. Для оптовых диапазонов сначала выбирайте запись с точными QUANTITY_FROM и QUANTITY_TO; нельзя обновлять первую попавшуюся цену.
Поиск, добавление или обновление
<?php
use Bitrix\Catalog\Model\Price;
use Bitrix\Main\Loader;
if (!Loader::includeModule('catalog')) {
throw new RuntimeException('Не подключён модуль catalog');
}
$productId = 123; // ID существующего товара или SKU.
$priceTypeId = 1; // ID существующего типа цены.
$newPrice = 1500.00;
$currency = 'RUB'; // Код существующей валюты.
$price = Price::getRow(array(
'select' => array('ID', 'PRODUCT_ID', 'CATALOG_GROUP_ID'),
'filter' => array(
'=PRODUCT_ID' => $productId,
'=CATALOG_GROUP_ID' => $priceTypeId,
'=QUANTITY_FROM' => false,
'=QUANTITY_TO' => false,
),
));
$data = array('fields' => array(
'PRODUCT_ID' => $productId,
'CATALOG_GROUP_ID' => $priceTypeId,
'PRICE' => $newPrice,
'CURRENCY' => $currency,
'QUANTITY_FROM' => null,
'QUANTITY_TO' => null,
));
$result = $price
? Price::update((int)$price['ID'], $data)
: Price::add($data);
if (!$result->isSuccess()) {
throw new RuntimeException(implode('; ', $result->getErrorMessages()));
}
echo $price ? 'Цена обновлена' : 'Цена добавлена';
В фильтре false выбирает только запись без границ количества; при записи модель получает null, как требует D7-документация для отсутствующих границ. Так код не перезапишет первую найденную цену диапазона. Price::getRow — официальный метод, который возвращает первую строку ORM-выборки или null. Price::add возвращает результат с ID созданной цены, а Price::update принимает ID цены больше нуля и возвращает объект с ошибками или успехом. Не игнорируйте isSuccess(): тогда импорт не сообщит «готово» после неудачной записи.
Перед запуском проверьте, что ID указывает на товар, а не на родительский товар вариации. Цена, созданная для родителя вместо SKU, может сохраниться успешно, но не попасть в карточку выбранного торгового предложения.
Проверьте, что исправлена нужная запись
- Запускайте код только в административном контексте или CLI тестовой копии с правом менять каталог.
- До запуска сохраните ID товара, тип цены, прежнюю цену и валюту.
- После успеха прочитайте цену тем же фильтром и убедитесь, что изменился ожидаемый ID.
- Откройте нужный SKU под обычным посетителем и проверьте тип цены, валюту, право просмотра и количество.
Если цена приходит из 1С, ручное исправление может быть перезаписано следующим обменом. В этом случае включайте описанную логику в согласованный импорт либо меняйте первичный источник, а не шаблон товара.
Код сверён с официальными сигнатурами 4 октября 2026 года. На изолированном стенде Битрикс с тестовым SKU цена создалась как 101.00 и обновилась до 202.00; повторное чтение подтвердило тот же ID записи. См. Price::getRow, Price::add, Price::update и PriceTable. Исходный вопрос и ответ от 11 марта 2026 года: форум «1С-Битрикс».