progcode_D / PHP / WEB

Bitrix

Bitrix API. Создание (добавление) торгового предложения товара

Как связать товар и предложение через legacy API Bitrix, раздельно проверить создание, параметры каталога и цену.

В каталоге Bitrix товар и его торговые предложения хранятся в связанных инфоблоках. Сначала создаётся элемент товара, затем элемент предложения со свойством привязки, после чего предложению добавляют параметры каталога и цену. Ниже разобран старый API из заметки 2017 года; в новом коде выбирайте API вашей версии ядра.

Условия перед запуском

  • Пролог Bitrix подключён; код исполняется в доверенном обработчике с нужными правами, а не по открытому HTTP-запросу.
  • Инфоблок предложений уже настроен как каталог и связан с инфоблоком товаров.
  • Число 3 — пример идентификатора; замените его значением из своего проекта.
  • Пример создаёт новые элементы при каждом запуске. Для повторяемого импорта нужен внешний ключ и поиск существующих записей.

Создание и последовательные проверки

<?php
use Bitrix\Main\Loader;

if (!Loader::includeModule('iblock') || !Loader::includeModule('catalog')) {
    throw new RuntimeException('Не загружены модули iblock/catalog');
}

$offersIblockId = 3;
$catalog = CCatalog::GetByID($offersIblockId);
if (!$catalog || empty($catalog['PRODUCT_IBLOCK_ID']) || empty($catalog['SKU_PROPERTY_ID'])) {
    throw new RuntimeException('Не настроена связь инфоблоков товара и предложений');
}

$product = new CIBlockElement();
$productId = $product->Add([
    'NAME' => 'Товар',
    'IBLOCK_ID' => (int) $catalog['PRODUCT_IBLOCK_ID'],
    'ACTIVE' => 'Y',
]);
if (!$productId) {
    throw new RuntimeException('Товар: ' . $product->LAST_ERROR);
}

$offer = new CIBlockElement();
$offerId = $offer->Add([
    'NAME' => 'Торговое предложение',
    'IBLOCK_ID' => $offersIblockId,
    'ACTIVE' => 'Y',
    'PROPERTY_VALUES' => [(int) $catalog['SKU_PROPERTY_ID'] => $productId],
]);
if (!$offerId) {
    throw new RuntimeException('Предложение: ' . $offer->LAST_ERROR);
}

if (!CCatalogProduct::Add(['ID' => $offerId, 'VAT_INCLUDED' => 'Y'])) {
    throw new RuntimeException('Не добавлены параметры предложения в каталог');
}
if (!CPrice::SetBasePrice($offerId, 100.50, 'RUB')) {
    throw new RuntimeException('Не установлена базовая цена предложения');
}
// Успех: $productId и $offerId содержат созданные идентификаторы.
?>

Важно, что во всех последних вызовах используется один $offerId. Проверка добавления параметров и проверка цены разделены: успешная установка цены не должна попадать в ветку ошибки.

Товар связан с торговым предложением через свойство SKU; цена относится к ID предложения
ID свойства связи, ID товара и ID предложения решают разные задачи. Цена привязана к offerId.

Границы этого примера

Несколько успешных вызовов с последующей ошибкой могут оставить частично созданные данные. Перед применением в импорте продумайте транзакцию и компенсацию с учётом обработчиков событий вашей установки. Не удаляйте автоматически уже существующий товар при сбое предложения. Для промышленного сценария также нужны количество, доступность, свойства и правила налогообложения именно вашего каталога.

Документация CCatalogProduct::Add помечает метод как устаревший с версии 17.6.0 и указывает замену \Bitrix\Catalog\Model\Product::add. Перенос на неё требует собственного варианта примера: у D7 другой объект результата, поэтому механическая замена имени метода недостаточна.

Что проверить на тестовом каталоге

  • При корректной настройке созданы товар, предложение, привязка и базовая цена без исключения.
  • Неверный идентификатор инфоблока отклоняется до создания товара.
  • Отказ добавления предложения не маскируется ошибкой цены.
  • Отдельно воспроизведены отказ добавления параметров и отказ установки цены.
  • Повторный запуск не допускается как незаметный импорт дубликатов.

У CPrice::SetBasePrice при стандартном значении bGetID=false результат — true или false. Этот метод также устарел с 17.6.0; для новой реализации документация указывает модели Price::add и Price::update.

КОНЕЦ ЗАМЕТКИ↑ В начало