Перейти к содержимому

Создание торговых предложений из кода - привязка, цены, остатки

Заводим варианты товара скриптом: инфоблок предложений, свойство привязки, создание элемента, цена, остаток и проверка результата на витрине.

Что нужно знать заранее

Торговое предложение - обычный элемент другого инфоблока. Особенным его делает свойство привязки к товару, а всё остальное работает как у любого элемента каталога.

Цена и остаток не хранятся в самом элементе. Они лежат в таблицах торгового каталога, и записывают их отдельными вызовами после создания элемента.

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

Шаги

  1. Найти инфоблок предложений и свойство привязки по инфоблоку товаров.
  2. Создать элемент предложения с заполненной привязкой к нужному товару.
  3. Пометить предложение товаром каталога и задать его остаток.
  4. Поставить базовую цену предложения в нужной валюте.
  5. Проверить вывод варианта в карточке товара и в выборке.

Решение

Находим инфоблок предложений и привязку:

\Bitrix\Main\Loader::includeModule('catalog');
$sku = \CCatalogSKU::GetInfoByProductIBlock($catalogIblockId);
printf("предложения: %d, свойство привязки: %d\n",
$sku['IBLOCK_ID'], $sku['SKU_PROPERTY_ID']);
// пустой ответ означает, что предложения у этого каталога не включены

Связка каталога и предложений задаётся один раз в настройках. Скрипт её не меняет, а читает, и это единственный правильный способ узнать нужные номера на конкретном стенде.

Создаём предложение с привязкой:

$el = new \CIBlockElement();
$offerId = $el->Add([
'IBLOCK_ID' => $sku['IBLOCK_ID'],
'NAME' => $product['NAME'] . ' - ' . $size,
'XML_ID' => $product['XML_ID'] . '#' . $size, // код для повторных запусков
'PROPERTY_VALUES' => [$sku['SKU_PROPERTY_ID'] => $productId, 'SIZE' => $size],
]);
if (!$offerId) { echo $el->LAST_ERROR; }

Внешний код предложения собирают из кода товара и признака варианта. Тогда повторный запуск скрипта находит уже созданное предложение и обновляет его, а не плодит вторые копии.

Делаем предложение товаром и задаём остаток:

\CCatalogProduct::Add(['ID' => $offerId, 'QUANTITY' => 10,
'QUANTITY_TRACE' => 'Y', 'CAN_BUY_ZERO' => 'N',
'WEIGHT' => 300]); // вес нужен для расчёта доставки
// без этой записи элемент останется обычным элементом инфоблока

Элемент без записи товарных параметров не продаётся. Он виден в списке, но не попадает в корзину, и это самая частая причина «предложение есть, а купить нельзя».

Ставим цену предложения:

\CPrice::SetBasePrice($offerId, 1990, 'RUB');
// для других типов цен используют запись цены с указанием типа

Цену ставят у предложения, а не у товара. Товар с предложениями своей цены не имеет: на витрине показывается минимальная цена среди его вариантов.

Проверяем результат выборкой:

$rs = \CIBlockElement::GetList([], ['IBLOCK_ID' => $sku['IBLOCK_ID'],
'PROPERTY_' . $sku['SKU_PROPERTY_ID'] => $productId], false, false,
['ID', 'NAME', 'CATALOG_QUANTITY', 'CATALOG_PRICE_1']);
while ($row = $rs->Fetch()) { print_r($row); }

Типичные проблемы

Предложение создано, но в карточке товара его нет.

Не заполнено свойство привязки к товару или заполнено не тем идентификатором. Номер свойства привязки берут из настроек каталога, а не пишут числом в коде.

Вариант виден, но кнопка покупки не работает.

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

На витрине у товара нет цены.

Цена задана у самого товара, а не у его торговых предложений. Товар с предложениями показывает минимальную цену среди вариантов, своей цены у него нет.

Повторный запуск скрипта наплодил дубли вариантов.

Предложения создаются без внешнего кода и без поиска уже существующих. Внешний код собирают из кода товара и признака варианта, а перед созданием ищут по нему.

После массового создания витрина показывает старые данные.

Кэш каталога и фасетный индекс не пересобирались после скрипта. После массовых операций сбрасывают кэш и помечают индекс на пересборку.

Частые вопросы

Как узнать инфоблок предложений в коде?

Спросить его по инфоблоку товаров штатным методом каталога. Он же вернёт номер свойства привязки, который нужен для создания варианта.

Можно ли создавать предложения обычным добавлением элемента?

Да, предложение и есть элемент инфоблока, но без привязки и товарных параметров оно бесполезно. Оба шага делают сразу за созданием.

Где задавать цену: у товара или у предложения?

У предложения. Товар с предложениями своей цены не имеет, а на витрине показывается минимальная цена среди вариантов.

Как обновлять уже созданные варианты?

Искать по внешнему коду и вызывать обновление вместо создания. Такой скрипт можно запускать повторно без страха развести дубли.

Что делать после массового создания?

Сбросить кэш каталога и пересобрать фасетный индекс обоих инфоблоков. Иначе фильтр и витрина какое-то время показывают прежнюю картину.

Смежное

Первоисточник