Yandex Metrika
sanches.free

Подарки в интернет-магазине: Gift\Manager, коллекции и тип товара в D7

Откуда берутся правила

Условия «при покупке подарить товар» задаются в админке: Маркетинг → Товарный маркетинг → Правила работы с корзиной. Сам по себе подарок не «прилетает» на склад заказа: покупатель должен добавить подарочную позицию в корзину. Тогда строка обычно уходит со 100 % скидкой; при количестве больше одной единицы поведение уже подчиняется встроенной логике ядра магазина (в типовых сценариях подарок сопровождает именно один экземпляр).

Зачем DiscountCompatibility

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

Коллекции для уже собранной корзины

Корзина берётся из хранилища текущего Fuser и сайта. Менеджер подарков — синглтон \Bitrix\Sale\Discount\Gift\Manager. Если покупатель авторизован, стоит передать его ID, чтобы подбор учитывал персональные ограничения. Результат — набор «коллекций»; каждая дальше перебирается во вложенном цикле.

use Bitrix\Main\Context;
use Bitrix\Main\Engine\CurrentUser;
use Bitrix\Sale\Basket\Storage;
use Bitrix\Sale\Compatible\DiscountCompatibility;
use Bitrix\Sale\Discount\Gift\Manager as GiftDirector;
use Bitrix\Sale\Fuser;

DiscountCompatibility::stopUsageCompatible();

$siteCode = Context::getCurrent()->getSite();
$basketVault = Storage::getInstance(Fuser::getId(), $siteCode);
$liveBasket = $basketVault->getBasket();

$giftDirector = GiftDirector::getInstance();
if ($buyerId = CurrentUser::get()->getId()) {
    $giftDirector->setUserId($buyerId);
}

$bundleMatrix = $giftDirector->getCollectionsByBasket($liveBasket);

DiscountCompatibility::revertUsageCompatible();

Коллекции относительно конкретного товара

Иногда нужно понять, какие подарки «цепляются» к выбранной позиции каталога, не дожидаясь оформления. Первый аргумент — та же корзина, что и в других местах страницы; второй — товарный объект из вашего потока (часто это позиция корзины, строка каталога или SKU из компонента — тип должен совпадать с тем, что ожидает метод в вашей версии модуля sale).

use Bitrix\Main\Context;
use Bitrix\Sale\Basket;
use Bitrix\Sale\Compatible\DiscountCompatibility;
use Bitrix\Sale\Discount\Gift\Manager as GiftDirector;
use Bitrix\Sale\Fuser;

DiscountCompatibility::stopUsageCompatible();

$giftDirector = GiftDirector::getInstance();
$visitorBasket = Basket::loadItemsForFUser(Fuser::getId(), Context::getCurrent()->getSite());

// $offerAnchor — товар/позиция из компонента каталога или корзины
$segmentStacks = $giftDirector->getCollectionsByProduct($visitorBasket, $offerAnchor);

DiscountCompatibility::revertUsageCompatible();

Строка подарка и тип товара в каталоге

Внутри коллекции элементы можно сопоставить с метаданными каталога: по getProductId() читают строку из ProductTable и смотрят TYPE — от торгового товара и SKU до набора и пустого SKU. Так проще решить, рисовать ли карточку, какой компонент подключать или нужно ли смотреть торговые предложения.

use Bitrix\Catalog\ProductTable;

foreach ($segmentStacks as $segment) {
    foreach ($segment as $giftRow) {
        $catalogProbe = ProductTable::getById($giftRow->getProductId())->fetch();
        if (!$catalogProbe) {
            continue;
        }
        switch ($catalogProbe['TYPE']) {
            case ProductTable::TYPE_PRODUCT:
            case ProductTable::TYPE_SKU:
                // простой или конфигурируемый товар
                break;
            case ProductTable::TYPE_OFFER:
                // торговое предложение
                break;
            case ProductTable::TYPE_SET:
            case ProductTable::TYPE_EMPTY_SKU:
            case ProductTable::TYPE_FREE_OFFER:
                // набор и особые варианты
                break;
        }
    }
}

На что смотреть в продакшене

  • Не забывайте Loader::includeModule('sale') и при работе с каталогом catalog, прежде чем трогать таблицы.
  • После изменения состава корзины пересчёт подарков может отличаться; для фронта лучше вызывать логику в том же месте, где уже обновились скидки.
  • Тяжёлые циклы по коллекциям лучше не выполнять на каждый хит без кеша — согласуйте частоту с правилами акции.

Не хотите копаться сами?

Починю за 1-3 дня. Без предоплаты — оплата по результату.

15+ лет опыта с 1С-Битрикс · Без предоплаты · 7 дней гарантии