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

Каталог 1С-Битрикс - комплекты, скидки, склады, доступность

Продолжение темы магазина: «тяжёлая» часть каталога. Товары-комплекты, скидки с купонами, складской учёт с документами и резервом, расчёт доступности и итоговой цены. Здесь больше всего мест, где интуиция подводит.

Как это работает

Комплект - это тип товара. Чтобы товар стал составным, его тип меняют на тип комплекта, и только после этого заполняют состав. Обратный порядок не работает: состав добавится, но продаваемой позицией с составом товар не станет.

Один класс обслуживает два сценария. Комплект - покупатель берёт одну позицию, а система учитывает несколько товаров в её составе. Набор рекомендаций - это блок «купить вместе»: он не меняет состав продаваемого товара и не требует смены типа. В комплект и набор можно включать товары и торговые предложения, в набор - ещё и комплекты.

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

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

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

Резерв и свободный остаток. По паре «товар плюс склад» хранятся общий остаток и зарезервированное количество. Отдельного поля свободного остатка нет - его считают в коде как разницу. Ссылки на заказ, создавший резерв, в таблице тоже нет. Снимать резерв правильно документом отмены, а не прямым уменьшением числа.

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

Примеры

1. Комплект

use Bitrix\Catalog\Model\Product;
use Bitrix\Catalog\ProductTable;
// шаг 1: сменить тип товара
Product::update($productId, ['TYPE' => ProductTable::TYPE_SET]);
// шаг 2: заполнить состав
CCatalogProductSet::add([
'TYPE' => CCatalogProductSet::TYPE_SET,
'ITEM_ID' => $productId,
'ITEMS' => [
['ITEM_ID' => $tableId, 'QUANTITY' => 1],
['ITEM_ID' => $lampId, 'QUANTITY' => 1],
['ITEM_ID' => $chairId, 'QUANTITY' => 1],
],
]);

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

2. Скидка с купоном

// 1. скидка - валюта обязательна даже для процентной
$discountId = CCatalogDiscount::Add([
'SITE_ID' => SITE_ID,
'ACTIVE' => 'Y',
'NAME' => 'Осенняя скидка',
'VALUE_TYPE' => 'P',
'VALUE' => 10,
'CURRENCY' => 'RUB',
'CONDITIONS' => $conditionsTree,
]);
// 2. купон
\Bitrix\Catalog\DiscountCouponTable::add([
'DISCOUNT_ID' => $discountId,
'COUPON' => 'AUTUMN10',
'TYPE' => \Bitrix\Catalog\DiscountCouponTable::TYPE_BASKET_ROW,
'ACTIVE' => 'Y',
]);
// 3. включить использование купонов
\Bitrix\Catalog\DiscountTable::setUseCoupons($discountId, 'Y');
// 4. добавить купон в расчёт (модуль sale)
\Bitrix\Sale\DiscountCouponsManager::add('AUTUMN10');

Три частые ошибки на этом пути: попытка включить купоны параметром при создании скидки, отсутствие валюты (метод вернёт отрицательный результат, а причина окажется в исключении приложения) и добавление купона устаревшими способами вместо менеджера купонов.

Проверить, какие скидки применились к товару, можно отдельным методом получения скидок по товару.

3. Складские документы

// создание черновика прихода
$documentId = CCatalogDocs::add([
'DOC_TYPE' => \Bitrix\Catalog\StoreDocumentTable::TYPE_ARRIVAL,
'SITE_ID' => SITE_ID,
'CURRENCY' => 'RUB',
'ELEMENT' => [
[
'ELEMENT_ID' => $productId,
'STORE_TO' => $storeId,
'AMOUNT' => 100,
'PURCHASING_PRICE' => 500,
],
],
]);
// проведение - только теперь остатки изменятся
CCatalogDocs::conductDocument($documentId);
// отмена влияния проведённого документа
CCatalogDocs::cancellationDocument($documentId);
// свободный остаток считаем сами
$free = $row['AMOUNT'] - $row['QUANTITY_RESERVED'];
// включён ли складской учёт
if (\Bitrix\Catalog\Config\State::isUsedInventoryManagement()) {
// остатки менять только документами
}

Справочник API

APIНазначениеОсобенности
ProductTable::TYPE_SETтип «комплект»тип меняют до заполнения состава
CCatalogProductSetсостав комплекта и наборыобновление заменяет состав целиком
CCatalogDiscount::Add()скидка каталогавалюта обязательна, условия деревом
DiscountTable::setUseCoupons()включение купонов у скидкине параметр при создании
DiscountCouponTableкупонысоздаются отдельно от скидки
Sale\DiscountCouponsManager::add()купон в расчётединственный корректный способ
CCatalogDiscount::GetDiscountByProduct()активные скидки товарадля проверки
CCatalogDocs::add()складской документ-черновикостатки ещё не меняются
CCatalogDocs::conductDocument()проведение документадвижение остатков
CCatalogDocs::cancellationDocument()отмена проведенияобратное движение, документ остаётся
StoreDocumentTable::TYPE_*типы документовприход, перемещение, списание, возврат, отмена резерва
StoreProductTableостатки по складамобщий остаток и резерв, свободный считают в коде
Config\State::isUsedInventoryManagement()режим складского учётаопределяет способ изменения остатков
CCatalogProduct::GetOptimalPrice()итоговая ценаучитывает скидки, купоны, диапазоны, права
SubscribeTableподписка на поступление

Частые ошибки

Состав заполнили до смены типа. Комплект не станет продаваемой позицией с составом. Сначала тип, потом состав.

После правки в комплекте осталась одна позиция. Обновление заменяет состав целиком - передавайте полный новый список.

Купоны не работают. Их включают отдельным методом у скидки, а в расчёт добавляют менеджером купонов из модуля продаж.

Скидка не создалась. Чаще всего не передана валюта - она обязательна даже для процентной скидки. Текст ошибки лежит в исключении приложения.

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

Документ создали, но остатки не изменились. Документ - черновик, нужно проведение.

Резерв уменьшают прямой записью. Правильный способ - провести документ отмены резервирования.

Полагаются на автоматически рассчитанную доступность. Она не учитывает права группы на тип цены и активность элемента.

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

Чем комплект отличается от набора рекомендаций?

Комплект - это продаваемая позиция со своим составом: покупатель берёт одну карточку, а система учитывает несколько товаров внутри. Для этого товару меняют тип. Набор рекомендаций - блок «с этим покупают»: он ничего не меняет в составе товара и смены типа не требует. Технически ими управляет один класс, но режимы разные.

Как правильно менять остатки?

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

Почему свободного остатка нет отдельным полем?

Платформа хранит по паре «товар и склад» два значения: общий остаток и зарезервированное количество. Свободный остаток - это их разница, и считают её в коде. Заодно учтите, что ссылки на заказ, который создал резерв, в таблице нет, а снимать резерв нужно документом отмены резервирования, а не уменьшением числа.

Скидка создана, но не применяется. Что смотреть?

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

Связанные темы

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