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

Недоступные варианты в карточке - скрытие, выбор по умолчанию, остатки

Настраиваем карточку товара, у которого часть вариантов кончилась: скрытие недоступных комбинаций, выбор доступного варианта по умолчанию и остатки по складам.

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

Доступность варианта платформа считает сама после записи товарных данных. Вариант недоступен, когда включён учёт остатка, запрещена покупка при нуле и количество опустилось до нуля.

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

Решение о показе принимают заранее, потому что рабочих вариантов поведения ровно два. Скрытые комбинации дают чистую карточку, а показанные неактивными сообщают покупателю об ассортименте и собирают подписки на поступление.

Шаги

  1. Решить, скрывать недоступные варианты или показывать их неактивными с подписью о поступлении.
  2. Задать поведение параметрами компонента карточки, а затем повторить его в списке раздела.
  3. Проверить, что карточка открывается на доступном варианте, а не на первом по алфавиту.
  4. Показать свободный остаток по складам и пунктам выдачи, когда покупатель выбирает самовывоз.
  5. Предложить подписку на поступление для тех вариантов, которых сейчас нет на складе.

Решение

Задаём поведение параметрами карточки:

$APPLICATION->IncludeComponent('bitrix:catalog.element', 'my', [
'IBLOCK_ID' => $iblockId,
'HIDE_NOT_AVAILABLE' => 'Y', // товар целиком без доступных вариантов не показывать
'HIDE_NOT_AVAILABLE_OFFERS' => 'N', // сами варианты показывать, но неактивными
'OFFERS_SORT_FIELD' => 'catalog_QUANTITY', // доступные варианты идут первыми
'OFFERS_SORT_ORDER' => 'DESC',
'PRODUCT_SUBSCRIPTION' => 'Y', // кнопка подписки на поступление
]);

Значение скрытия у товара и у вариантов задаётся отдельно. Первый параметр решает судьбу всей карточки, второй - судьбу конкретных размеров внутри неё.

Смотрим доступность вариантов одним запросом:

\Bitrix\Main\Loader::includeModule('catalog');
$rows = \Bitrix\Catalog\ProductTable::getList(['filter' => ['@ID' => $offerIds],
'select' => ['ID', 'AVAILABLE', 'QUANTITY', 'QUANTITY_TRACE', 'CAN_BUY_ZERO']])->fetchAll();
print_r($rows);
// AVAILABLE = N при учёте остатка, запрете покупки при нуле и нулевом количестве

Оставляем в шаблоне только доступные варианты:

// result_modifier.php шаблона карточки
$arResult['OFFERS'] = array_values(array_filter($arResult['OFFERS'],
static fn(array $offer): bool => $offer['CATALOG_AVAILABLE'] === 'Y'));
// после фильтрации дерево выбора собирается заново уже без пустых комбинаций

Фильтровать варианты в шаблоне стоит только вместе со сбросом дерева выбора. Иначе покупатель увидит кнопку размера, за которой не осталось ни одного предложения, и карточка выдаст пустую цену.

Разрешаем покупку при нуле для отдельных вариантов:

$result = \Bitrix\Catalog\Model\Product::update($offerId, [
'QUANTITY_TRACE' => 'Y', 'CAN_BUY_ZERO' => 'Y',
]);
printf("доступность пересчитана: %s\n", $result->isSuccess() ? 'да' : 'нет');
// запись моделью каталога пересчитывает доступность варианта и его родителя

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

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

$stock = \Bitrix\Catalog\StoreProductTable::getList(['filter' => ['=PRODUCT_ID' => $offerId],
'select' => ['STORE_ID', 'AMOUNT', 'QUANTITY_RESERVED']])->fetchAll();
foreach ($stock as $row) {
printf("склад %d: свободно %s\n", $row['STORE_ID'], $row['AMOUNT'] - $row['QUANTITY_RESERVED']);
}
// отдельного поля со свободным остатком нет, его считают вычитанием резерва

Покупателю показывают именно свободный остаток, а не общее количество на складе. Число без вычета резерва обещает наличие, которое уже занято чужими неоплаченными заказами.

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

Товар пропал из каталога, хотя один размер есть.

Скрытие недоступных товаров работает по родителю, а у него слетела доступность после прямой правки остатка. Остатки меняют моделью каталога: она пересчитывает доступность варианта и его родительской карточки.

Карточка открывается на варианте, которого нет.

Порядок вариантов задан сортировкой по имени, поэтому первым в карточке идёт кончившийся размер. Сортировку вариантов задают по остатку, тогда доступные размеры встают в начало списка.

Кнопка размера есть, а цена пустая.

Варианты отфильтрованы в шаблоне, а дерево выбора собрано по прежнему полному списку предложений. Фильтровать варианты нужно до сборки дерева либо параметром компонента, а не после вывода.

Покупатель заказал товар, которого нет на складе.

У варианта разрешена покупка при нулевом остатке, а витрина об этом не сообщает. Такие варианты помечают сроком поставки прямо в карточке, рядом с кнопкой покупки.

В пункте выдачи товара не оказалось.

Карточка показывает общий остаток вместо свободного количества на выбранном покупателем пункте выдачи. Резерв вычитают из складского количества ещё до вывода числа на витрину покупателю.

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

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

Скрывать, когда ассортимент постоянный и пустые кнопки раздражают. Показывать неактивными, когда размеры возвращаются: такая карточка собирает подписки на поступление.

Почему товар исчез из каталога целиком?

У всех его вариантов доступность стала отрицательной, и родитель тоже стал недоступен. Проверяют товарные данные вариантов, а не карточку товара.

Как открыть карточку сразу на доступном размере?

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

Можно ли продавать вариант при нулевом остатке?

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

Какое число показывать покупателю?

Свободный остаток, то есть складское количество за вычетом резерва. Общий остаток обещает наличие, которое уже занято чужими заказами.

Смежное

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