Товар создан, но не продаётся - разбор причин
Элемент завели скриптом или обменом, в списке раздела он виден, а цены и кнопки покупки у него нет. Корзина такую позицию не принимает даже из кода. Разбираем причины по убыванию частоты, начиная с того, есть ли у элемента запись товара в торговом каталоге.
С чего начать
Смотрим, есть ли у элемента запись товара:
\Bitrix\Main\Loader::requireModule('catalog');$product = \Bitrix\Catalog\ProductTable::getList([ 'select' => ['ID', 'TYPE', 'AVAILABLE', 'QUANTITY'], 'filter' => ['=ID' => $elementId], // ID товарной записи равен ID элемента])->fetch();var_dump($product); // false означает, что элемент товаром так и не сталОдин этот вызов делит причины пополам. Пустой результат уводит к первым двум причинам: товарной записи нет, и продавать пока просто нечего. Найденная запись переводит разбор к типу товара, ценам и правам групп.
Считаем такие элементы по всему инфоблоку:
$elements = \CIBlockElement::GetList([], ['IBLOCK_ID' => $iblockId], false, false, ['ID']);$ids = [];while ($row = $elements->Fetch()) { $ids[] = (int)$row['ID'];}$withProduct = \Bitrix\Catalog\ProductTable::getList([ 'select' => ['ID'], 'filter' => ['@ID' => $ids], // читаем только те, у кого товарная запись есть])->fetchAll();printf("элементов %d, товаров %d\n", count($ids), count($withProduct));Расхождение чисел показывает масштаб. Один сбойный товар - ошибка оператора, а сотни - скрипт или профиль обмена, который заводит элементы мимо каталога.
Проверяем, что инфоблок вообще торговый каталог:
$catalog = \CCatalogSKU::getInfoByIBlock($iblockId);// CATALOG_TYPE: D - каталог, P - товары с предложениями, O - предложения, X - всё сразуprintf("тип каталога: %s\n", $catalog ? $catalog['CATALOG_TYPE'] : 'инфоблок не каталог');Пустой ответ означает, что инфоблок к модулю каталога не привязан. В таком инфоблоке товарная запись не появится, сколько раз её ни добавляй скриптом.
Смотрим цены товара и права групп на их типы:
$prices = \Bitrix\Catalog\PriceTable::getList([ 'select' => ['ID', 'CATALOG_GROUP_ID', 'PRICE', 'CURRENCY'], 'filter' => ['=PRODUCT_ID' => $elementId],])->fetchAll();
$access = \Bitrix\Catalog\GroupAccessTable::getList([ 'filter' => ['=CATALOG_GROUP_ID' => $priceTypeId], // ACCESS_VIEW и ACCESS_BUY])->fetchAll();Цена привязана к паре товар плюс тип цены, а не к элементу вообще. Строка цены есть, а права группы на этот тип нет - покупатель не увидит ни суммы, ни кнопки.
Заводим недостающую товарную запись и цену:
$result = \Bitrix\Catalog\Model\Product::add([ 'ID' => $elementId, // всегда равен ID элемента инфоблока 'TYPE' => \Bitrix\Catalog\ProductTable::TYPE_PRODUCT, 'QUANTITY' => 15, 'QUANTITY_TRACE' => 'Y', // вести количественный учёт 'CAN_BUY_ZERO' => 'N', // не продавать при нулевом остатке]);if (!$result->isSuccess()) { throw new \RuntimeException(implode('; ', $result->getErrorMessages()));}Создание товара всегда двухшаговое: сначала элемент инфоблока, следом товарная запись с тем же идентификатором. После успешного вызова платформа сама пересчитывает признак доступности, отдельно его выставлять не нужно.
Причины
-
Элемент создан без записи товара в каталоге примерно 30% случаев
ПризнакКарточка открывается как обычная новость: ни цены, ни кнопки покупки на ней нет.
ПроверкаЧитаем товарную запись по идентификатору элемента выборкой выше: у сбойных позиций она пустая.
Что делатьДобавляем товарные параметры сразу после создания элемента, в том же скрипте или обработчике импорта.
-
Инфоблок не привязан к торговому каталогу примерно 20% случаев
ПризнакПусто у всех элементов инфоблока разом, и вкладки торгового каталога в админке нет.
ПроверкаСмотрим тип каталога по инфоблоку: пустой ответ означает, что привязки к модулю нет.
Что делатьРегистрируем инфоблок торговым каталогом; для связки с предложениями инфоблок товаров и свойство привязки задаются только вместе.
-
Тип товара не рассчитан на продажу напрямую примерно 16% случаев
ПризнакРодительская карточка показывает цену от вариантов, но сама в корзину не уходит.
ПроверкаСмотрим поле типа у товарной записи: родитель с предложениями и родитель без них не продаются.
Что делатьПродаём предложения, а не родителя; простому товару ставим обычный тип, услуге - тип услуги.
-
Цена заведена родителю вместо торгового предложения примерно 14% случаев
ПризнакВ админке цена у товара видна, а на витрине выбор варианта обнуляет её и прячет кнопку.
ПроверкаСверяем идентификатор в строке цены с идентификатором предложения, а не родительской карточки.
Что делатьПереносим цену на предложение, а перед записью ищем существующую пару товар плюс тип цены.
-
Группе покупателей закрыт нужный тип цены примерно 12% случаев
ПризнакГость цены не видит, а под администратором та же карточка показывает и сумму, и кнопку.
ПроверкаЧитаем права групп на тип цены: нужны и право видеть, и право покупать.
Что делатьВыдаём группе право покупать по нужному типу цены: без него корзина позицию не примет.
-
Нулевой остаток при включённом количественном учёте примерно 8% случаев
ПризнакКнопка пропала у части позиций, и это ровно те, у которых обмен обнулил остаток.
ПроверкаСмотрим количество и признак доступности товарной записи вместе с разрешением покупки при нуле.
Что делатьРазрешаем покупку при нулевом остатке там, где товар идёт под заказ, либо пополняем количество.
Частые вопросы
Почему товар виден в списке, но у него нет цены?
Элемент инфоблока и товар каталога - две разные записи с одним идентификатором. Пока товарная запись не создана, цену привязывать не к чему, и компонент выводит карточку как обычный контент.
Создал элемент через CIBlockElement::Add, что ещё нужно?
Нужен второй шаг: товарные параметры через Model\Product::add с тем же идентификатором. Дальше цена по паре товар плюс тип цены, иначе покупать по-прежнему нечего.
После обмена с 1С часть товаров без цен, как найти их разом?
Выборкой товаров, у которых нет строки цены нужного типа. Такие позиции появляются пачками, когда номенклатуру завели раньше, чем проставили цены в учётной системе.
Признак доступности стоит в «да», а купить всё равно нельзя. Почему?
Доступность считается по остатку и настройкам учёта количества. Компоненты и корзина дополнительно проверяют активность элемента, даты публикации и права группы на тип цены.
Можно ли хранить цену в свойстве инфоблока?
Технически можно, но корзина, заказы, скидки и склад такое свойство не увидят. Продажные данные живут в объектах каталога, а не в свойствах элемента инфоблока.
Смежное
- Каталог товаров - оглавление подтемы
- Каталог и продажи - устройство магазина целиком
- Не работает кнопка «В корзину» - кнопка есть, но молчит: там разбирают запрос браузера
- Цена на витрине не та - цена выводится, но не та: там разбирают саму сумму
- Ссылка на товар ведёт в 404 - карточка вообще не открывается
- Товары под заказ - продажа при нулевом остатке и сроки поставки
- Типы цен - права групп на видимость и покупку
- Торговые предложения - когда продаётся вариант, а не родитель
- Массовая правка товаров - как дозавести записи пачкой
- Аудит каталога - регулярный поиск товаров без цены