В прошлой заметке я рассказал как применять только большую скидку из всех. А в этой расскажу, как дать скидку по купону на первый заказ больше определенной суммы заказа.

Как и в прошлый раз на помощь приходят два события: OnGetDiscount и OnGetDiscountResult модуля «Торговый каталог».

<?php
 
// {{{ Применении скидки по купону, только если заказ больше определённой суммы
 
\Bitrix\Main\EventManager::getInstance()->addEventHandler("catalog", "OnGetDiscount",
    array("WeProductDiscountHandler", "OnGetDiscount")
); 
 
\Bitrix\Main\EventManager::getInstance()->addEventHandler("catalog", "OnGetDiscountResult",
    array("WeProductDiscountHandler", "OnGetDiscountResult")
); 
 
 
class WeProductDiscountHandler{
 
    const COUPON_CODE = 'CP-0ZMA0-QDIMFQI';
    const TOTAL_SUMM_ORDER = 3000;
 
    protected static $basketItems = null;
    protected static $productPrice = null;
    protected static $totalCountOrders = null;
 
    /**
     * Вызывается в методе CCatalogDiscount::GetDiscount перед получением всех скидок
     * @return bool true
     */
    public function OnGetDiscount($intProductID, $intIBlockID, $arCatalogGroups, 
        $arUserGroups, $strRenewal, $siteID, $arDiscountCoupons, $boolSKU, $boolGetIDS){
 
        // получение цены товара
        $curProductPrice = CPrice::GetBasePrice($intProductID, false, false, false);
        if($curProductPrice != false){
            self::$productPrice = $curProductPrice;
        }
 
        return true;
    }
 
    /**
     * Возвращает товары в корзине пользователя
     * @return (array)
     */
    public static function getBasketItems(){
 
        if(self::$basketItems === null){
            \Bitrix\Main\Loader::includeModule('sale');
 
            $arItems = array();
            $resBasket = CSaleBasket::GetList(
                array(), 
                array(
                    "FUSER_ID" => CSaleBasket::GetBasketUserID(), 
                    "LID" => SITE_ID, 
                    "ORDER_ID" => "NULL"
                    )
            );
            while($arItem = $resBasket->Fetch()){
                $arItems[] = $arItem;
            }
 
            self::$basketItems = $arItems;
        }
 
        return self::$basketItems;
 
    }   
 
    /**
     * Возвращает общую сумму товаров в корзине 
     * @return (int)
     */
    public static function getTotalSumBasketItems(){
        $basketItems = self::getBasketItems();
 
        $totalSum = 0;
        foreach($basketItems as $item){
            $totalSum += ($item['PRICE'] + $item['DISCOUNT_PRICE']) * $item['QUANTITY'];
        }
 
        return $totalSum;
 
    }
 
    /**
     * Возвращает количество оформленных заказов текущего пользователя
     * @return (int)
     */
    public static function getCountOrdersByUser(){
 
        global $USER;
        if(self::$totalCountOrders === null){
 
            self::$totalCountOrders = 0;
 
            if ($USER->IsAuthorized()){
                \Bitrix\Main\Loader::includeModule('sale');
 
                $dbSales = CSaleOrder::GetList(
                    array(), 
                    array(
                        "USER_ID" => $USER->GetID()
                    ), 
                    array(
                        "COUNT" => "ID"
                    )
                );
                while ($arSales = $dbSales->Fetch()){
                    if(isset($arSales['ID'])){
                        self::$totalCountOrders = intval($arSales['ID']);
                    }
                }
            }
        }
 
        return self::$totalCountOrders;
 
    }
 
 
    /**
     * Вызывается в методе CCatalogDiscount::GetDiscount после получения 
     * и обработки всех скидок для товара
     * @return array() возвращаем только нужную нам скидку
     */
    public function OnGetDiscountResult(&$arResult){
 
        if(self::$productPrice === null) return;
 
        $boolHasCoupon = false;
 
        $discounts = array();
        foreach($arResult as $key_discount => &$discount){
            if(isset($discount['COUPON_ACTIVE'], $discount['COUPON']) 
                && $discount['COUPON_ACTIVE'] == 'Y' 
                && $discount['COUPON'] === self::COUPON_CODE){
 
                $boolHasCoupon = true;
                if(self::getTotalSumBasketItems() >= self::TOTAL_SUMM_ORDER){
                    $discount['VALUE'] = $discount['VALUE'] * self::$productPrice['PRICE'] 
                        / self::getTotalSumBasketItems();
                    $discounts[] = $discount;
                }
                break;
            }
        }
 
        if($boolHasCoupon){
            if(self::getCountOrdersByUser() == 0){
                $arResult = $discounts;
            }else{
                $arResult = array();
            }
        }
 
    }
 
}
 
// }}}

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

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