При классическом использовании функционала работы с купонами в Битриксе, размер скидки и обновление цен в корзине происходит в момент сохранения заказа. До этого момента объект Basket содержит «исходную» цену товара, а DiscountCouponsManager знает о примененных купонах.

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

Алгоритм прост и состоит из нескольких шагов:

  • создаем виртуальный клон корзины без сохранения в базу данных
  • применяем скидки к корзине
  • вычисляем реальную стоимость товаров

Реализуется это так:

$registry = Bitrix\Sale\Registry::getInstance(Bitrix\Sale\Registry::REGISTRY_TYPE_ORDER);
$basketClass = $registry->getBasketClassName();
/** Получаем текущую корзину пользователя */
$basket = $basketClass::loadItemsForFUser(
    Bitrix\Sale\Fuser::getId(),
    Bitrix\Main\Context::getCurrent()->getSite()
);

/** @var Sale\Basket $basketClone */
$basketClone = $basket->createClone();
$orderableBasket = $basketClone->getOrderableItems();
unset($basketClone);

$coupons = DiscountCouponsManager::get(false, [], false, true);

if (!empty($coupons) && !$orderableBasket->isEmpty()) {
    /** Магия расчета цен */
    $discounts = Sale\Discount::buildFromBasket(
        $orderableBasket,
        new Sale\Discount\Context\Fuser(Fuser::getId())
    );
    $discountResult = $discounts->calculate();
    if ($discountResult->isSuccess()) {
        /** Получение массива цен и обновление свойств виртуальной корзины */
        $showPrices = $discounts->getShowPrices();
        if (!empty($showPrices['BASKET'])) {
            foreach ($showPrices['BASKET'] as $basketCode => $data) {
                $basketItem = $orderableBasket->getItemByBasketCode($basketCode);
                if ($basketItem instanceof Sale\BasketItemBase) {
                    $basketItem->setFieldNoDemand('BASE_PRICE', $data['SHOW_BASE_PRICE']);
                    $basketItem->setFieldNoDemand('PRICE', $data['SHOW_PRICE']);
                }
            }
            unset($basketItem, $basketCode);
        }
        unset($showPrices);
    }
    unset($discountResult);
}
/** Формирование ответа для фронта или другие действия */

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

Больше статей и материалов по web-разработке в tg-канале - подписывайтесь!

Подписаться в telegram

Добавить комментарий

Ваш адрес email не будет опубликован.