Вывод скидок в процедуре заказа

Модуль расширенного управления меню для битрикс

Март 6, 2019

Теги: Магазин, Как это сделать?

Отображение применяемых скидок или наценок (правила работы с корзиной) в процедуре заказа (компонент "bitrix:sale.order.ajax").

Оформление заказа 2019-03-06 00-41-59.png

Вы также можете заказать данную доработку, стоимость - 6 000 р. для некастомизированной процедуры заказа. Контакты.

Для начала необходимо скопировать компонент с собственное пространство имен и отнаследовать класс компонента:


CBitrixComponent::includeComponentClass("bitrix:sale.order.ajax");


class 
MySaleOrderAjax extends SaleOrderAjax
{

}

Далее необходимо отнаследовать и изменить 3 функции, obtainBasket, obtainTotal и getJsDataResult (данный код может учитывать не все типы скидок, возможно, он еще будет прорабатываться):


/**

     * Set basket items data from order object to $this->arResult
     */
    
public function obtainBasket()
    {
        
$arResult =& $this->arResult;

        
$arResult["MAX_DIMENSIONS"] = $arResult["ITEMS_DIMENSIONS"] = array();
        
$arResult["BASKET_ITEMS"] = array();

        
$this->calculateBasket $this->order->getBasket()->createClone();

        
/* Добавлено */

        
$discounts $this->order->getDiscount();
        
$showPrices $discounts->getShowPrices();
                
        if (!empty(
$showPrices['BASKET']))
        {
            foreach (
$showPrices['BASKET'] as $basketCode => $data)
            {
                
$basketItem $this->calculateBasket->getItemByBasketCode($basketCode);
                if (
$basketItem instanceof Sale\BasketItemBase)
                {
                    
$basketItem->setFieldNoDemand('BASE_PRICE'$data['SHOW_BASE_PRICE']);
                    
$basketItem->setFieldNoDemand('PRICE'$data['SHOW_PRICE']);
                    
$basketItem->setFieldNoDemand('DISCOUNT_PRICE'$data['SHOW_DISCOUNT']);
                }
            }
        }
        
        
/* /Добавлено */
        
        /** @var Sale\BasketItem $basketItem */
        
foreach ($this->calculateBasket as $basketItem)
        {
            
$arBasketItem $basketItem->getFieldValues();
            if (
$basketItem->getVatRate() > 0)
            {
                
$arResult["bUsingVat"] = "Y";
                
$arBasketItem["VAT_VALUE"] = $basketItem->getVat();
            }
            
$arBasketItem["QUANTITY"] = $basketItem->getQuantity();
            
$arBasketItem["PRICE_FORMATED"] = SaleFormatCurrency($basketItem->getPrice(), $this->order->getCurrency());
            
$arBasketItem["WEIGHT_FORMATED"] = roundEx(doubleval($basketItem->getWeight()/$arResult["WEIGHT_KOEF"]), SALE_WEIGHT_PRECISION)." ".$arResult["WEIGHT_UNIT"];
            
$arBasketItem["DISCOUNT_PRICE"] = $basketItem->getDiscountPrice();

            
$arBasketItem["DISCOUNT_PRICE_PERCENT"] = 0;
            if (
$arBasketItem['CUSTOM_PRICE'] != 'Y')
            {
                
$arBasketItem['DISCOUNT_PRICE_PERCENT'] = Sale\Discount::calculateDiscountPercent(
                    
$arBasketItem['BASE_PRICE'],
                    
$arBasketItem['DISCOUNT_PRICE']
                );
                if (
$arBasketItem['DISCOUNT_PRICE_PERCENT'] === null)
                    
$arBasketItem['DISCOUNT_PRICE_PERCENT'] = 0;
            }
            
$arBasketItem["DISCOUNT_PRICE_PERCENT_FORMATED"] = $arBasketItem['DISCOUNT_PRICE_PERCENT'].'%';

            
$arBasketItem["BASE_PRICE_FORMATED"] = SaleFormatCurrency($basketItem->getBasePrice(), $this->order->getCurrency());

            
$arDim unserialize($basketItem->getField('DIMENSIONS'));
            if (
is_array($arDim))
            {
                
$arResult["MAX_DIMENSIONS"] = CSaleDeliveryHelper::getMaxDimensions(
                    array(
                        
$arDim["WIDTH"],
                        
$arDim["HEIGHT"],
                        
$arDim["LENGTH"]
                    ),
                    
$arResult["MAX_DIMENSIONS"]);

                
$arResult["ITEMS_DIMENSIONS"][] = $arDim;
            }

            
$arBasketItem["PROPS"] = array();
            
/** @var Sale\BasketPropertiesCollection $propertyCollection */
            
$propertyCollection $basketItem->getPropertyCollection();
            
$propList $propertyCollection->getPropertyValues();
            foreach (
$propList as $key => &$prop)
            {
                if (
$prop['CODE'] == 'CATALOG.XML_ID' || $prop['CODE'] == 'PRODUCT.XML_ID' || $prop['CODE'] == 'SUM_OF_CHARGE')
                    continue;

                
$prop array_filter($prop, array("CSaleBasketHelper""filterFields"));
                
$arBasketItem["PROPS"][] = $prop;
            }

            
$this->arElementId[] = $arBasketItem["PRODUCT_ID"];
            
$arBasketItem["SUM_NUM"] = $basketItem->getPrice() * $basketItem->getQuantity();
            
$arBasketItem["SUM"] = SaleFormatCurrency($basketItem->getPrice() * $basketItem->getQuantity(), $this->order->getCurrency());
            
$arBasketItem["SUM_BASE"] = $basketItem->getBasePrice() * $basketItem->getQuantity();
            
$arBasketItem["SUM_BASE_FORMATED"] = SaleFormatCurrency($basketItem->getBasePrice() * $basketItem->getQuantity(), $this->order->getCurrency());

            
/* Добавлено */

            
$arBasketItem['REAL_BASE_PRICE'] = $showPrices['BASKET'][$basketItem->getId()]['REAL_BASE_PRICE'];
            
$arBasketItem["REAL_BASE_PRICE_FORMATED"] = SaleFormatCurrency($arBasketItem["REAL_BASE_PRICE"], $this->order->getCurrency());
            
$arBasketItem['REAL_PRICE'] = $showPrices['BASKET'][$basketItem->getId()]['REAL_PRICE'];
            
$arBasketItem['REAL_DISCOUNT'] = $showPrices['BASKET'][$basketItem->getId()]['REAL_DISCOUNT'];
            
$arBasketItem["SUM_REAL_BASE"] = $arBasketItem['REAL_BASE_PRICE'] * $basketItem->getQuantity();
            
$arBasketItem["SUM_REAL_BASE_FORMATED"] = SaleFormatCurrency($arBasketItem["SUM_REAL_BASE"], $this->order->getCurrency());

            
/* /Добавлено */

            
$arResult["BASKET_ITEMS"][] = $arBasketItem;
        }
        
        unset(
$showPrices); // Moved.SE
    
}
    
    
/**
     * Set order total prices data from order object to $this->arResult
     */
    
protected function obtainTotal()
    {
        
$arResult =& $this->arResult;

        
$locationAltPropDisplayManual $this->request->get('LOCATION_ALT_PROP_DISPLAY_MANUAL');
        if (!empty(
$locationAltPropDisplayManual) && is_array($locationAltPropDisplayManual))
        {
            foreach (
$locationAltPropDisplayManual as $propId => $switch)
            {
                if (
intval($propId))
                {
                    
$arResult['LOCATION_ALT_PROP_DISPLAY_MANUAL'][intval($propId)] = !!$switch;
                }
            }
        }

        
$basket $this->calculateBasket;
        
        
/* Добавлено */
        
$discounts $this->order->getDiscount();
        
$showPrices $discounts->getShowPrices();
        
$arResult['REAL_BASE_PRICE'] = 0.0;
        if (!empty(
$showPrices['BASKET']))
        {
            foreach (
$showPrices['BASKET'] as $basketCode => $data)
            {
                
$basketItem $this->calculateBasket->getItemByBasketCode($basketCode);
                if (
$basketItem instanceof Sale\BasketItemBase)
                {
                    
$arResult['REAL_BASE_PRICE'] += $data['REAL_BASE_PRICE']*$basketItem->getQuantity();
                }
            }
        }
        
$arResult['REAL_BASE_PRICE_FORMATED'] = SaleFormatCurrency($arResult['REAL_BASE_PRICE'], $this->order->getCurrency());

        
$applyResult $discounts->getApplyResult();
        
$arResult["DISCOUNTS"] = array();
        
        foreach(
$applyResult['DISCOUNT_LIST'] as $discount)
        {
            
$sum 0.0;
            foreach(
$applyResult['ORDER'] as $applyDiscount)
            {
                if(
                    
$applyDiscount['DISCOUNT_ID']!=$discount['ID']
                    || !
is_array($applyDiscount['RESULT']['BASKET'])
                )
                    continue;
                foreach(
$applyDiscount['RESULT']['BASKET'] as $applyDiscountResult)
                {
                    if(!
is_array($applyDiscountResult['DESCR_DATA']))
                        continue;

                    
$basketItem $this->calculateBasket->getItemByBasketCode($applyDiscountResult['BASKET_ID']);
                    if (!(
$basketItem instanceof Sale\BasketItemBase))
                        continue;
                    foreach(
$applyDiscountResult['DESCR_DATA'] as $applyDiscountResultValue)
                    {
                        if(
$applyDiscountResultValue['RESULT_UNIT']!=$this->order->getCurrency())
                            continue;
                        
$sum += $applyDiscountResultValue['RESULT_VALUE']*$basketItem->getQuantity();
                    }    
                }
            }
            
            if(
$sum!=0)
            {
                
$arResult["DISCOUNTS"][] = array(
                    
"NAME"=>$discount['NAME'],
                    
"SUM"=>$sum,
                    
"SUM_FORMATED"=>SaleFormatCurrency($sum$this->order->getCurrency()),
                );
            }
            
        }
        
        
/* /Добавлено */

        
$arResult['ORDER_PRICE'] = $basket->getPrice();
        
$arResult['ORDER_PRICE_FORMATED'] = SaleFormatCurrency($arResult['ORDER_PRICE'], $this->order->getCurrency());

        
$arResult['ORDER_WEIGHT'] = $basket->getWeight();
        
$arResult['ORDER_WEIGHT_FORMATED'] = roundEx(floatval($arResult['ORDER_WEIGHT'] / $arResult['WEIGHT_KOEF']), SALE_WEIGHT_PRECISION).' '.$arResult['WEIGHT_UNIT'];

        
$arResult['PRICE_WITHOUT_DISCOUNT_VALUE'] = $basket->getBasePrice();
        
$arResult['PRICE_WITHOUT_DISCOUNT'] = SaleFormatCurrency($arResult['PRICE_WITHOUT_DISCOUNT_VALUE'], $this->order->getCurrency());

        
$arResult['DISCOUNT_PRICE'] = Sale\PriceMaths::roundPrecision(
            
$this->order->getDiscountPrice() + ($arResult['PRICE_WITHOUT_DISCOUNT_VALUE'] - $arResult['ORDER_PRICE'])
        );
        
$arResult['DISCOUNT_PRICE_FORMATED'] = SaleFormatCurrency($arResult['DISCOUNT_PRICE'], $this->order->getCurrency());

        
$arResult['DELIVERY_PRICE'] = Sale\PriceMaths::roundPrecision($this->order->getDeliveryPrice());
        
$arResult['DELIVERY_PRICE_FORMATED'] = SaleFormatCurrency($arResult['DELIVERY_PRICE'], $this->order->getCurrency());

        
$arResult['ORDER_TOTAL_PRICE'] = Sale\PriceMaths::roundPrecision($this->order->getPrice());
        
$arResult['ORDER_TOTAL_PRICE_FORMATED'] = SaleFormatCurrency($arResult['ORDER_TOTAL_PRICE'], $this->order->getCurrency());
    }

    public function 
getJsDataResult()
    {
        global 
$USER;
        
$arResult =& $this->arResult;
        
$result =& $this->arResult['JS_DATA'];

        
/* Заменено */
        
parent::getJsDataResult();

        
$result['TOTAL']['REAL_BASE_PRICE'] = $arResult['REAL_BASE_PRICE'];
        
$result['TOTAL']['REAL_BASE_PRICE_FORMATED'] = $arResult['REAL_BASE_PRICE_FORMATED'];
        
$result['TOTAL']['DISCOUNTS'] = $arResult['DISCOUNTS'];
        
/* /Заменено */
    
}

Чтобы добавить данные о скидках в блок "Итого" процедуры заказа, а также сделать, чтобы исходная цена товаров отображалась без скидки, нужно изменить функцию editTotalBlock в файл "order_ajax.js" шаблона компонента следующим образом:


if (parseFloat(total.ORDER_PRICE) === 0)

            {
                
priceHtml this.params.MESS_PRICE_FREE;
                
params.free true;
            }
            else
            {
                
priceHtml total.REAL_BASE_PRICE_FORMATED//Изменено, оригинал: total.ORDER_PRICE_FORMATED; 
            
}

            if (
this.options.showPriceWithoutDiscount)
            {
                
priceHtml += '<br><span class="bx-price-old">' total.PRICE_WITHOUT_DISCOUNT '</span>';
            }

            
this.totalInfoBlockNode.appendChild(this.createTotalUnit(BX.message('SOA_SUM_SUMMARY'), priceHtmlparams));

            if (
this.options.showOrderWeight)
            {
                
this.totalInfoBlockNode.appendChild(this.createTotalUnit(BX.message('SOA_SUM_WEIGHT_SUM'), total.ORDER_WEIGHT_FORMATED));
            }

            
/* Добавлено */
            
            
if(total.DISCOUNTS)
            {
                for(var 
i in total.DISCOUNTS)
                {
                    
this.totalInfoBlockNode.appendChild(
                        
this.createTotalUnit(
                            
total.DISCOUNTS[i].NAME ':',
                            
total.DISCOUNTS[i].SUM_FORMATED
                        
)
                    );
                }
            }
            
            
/* /Добавлено */

Для того, чтобы в блоке "Товары в заказе" процедуры заказа отображалась цена на товары без скидок и наценок, в файле "order_ajax.js" нужно изменить функцию createBasketItemColumn в следующих местах:


if (column.id === 'PRICE_FORMATED')

            {
                
textNode.appendChild(BX.create('STRONG', {props: {className'bx-price'}, htmldata.REAL_BASE_PRICE_FORMATED /* Изменено, оригинал: data.PRICE_FORMATED */}));
                if (
parseFloat(data.DISCOUNT_PRICE) > 0)
                {
                    
textNode.appendChild(BX.create('BR'));
                    
textNode.appendChild(BX.create('STRONG', {
                        
props: {className'bx-price-old'},
                        
htmldata.BASE_PRICE_FORMATED
                    
}));
                }

                if (
this.options.showPriceNotesInBasket && active)
                {
                    
textNode.appendChild(BX.create('BR'));
                    
textNode.appendChild(BX.create('SMALL', {textdata.NOTES}));
                }
            }
            else if (
column.id === 'SUM')
            {
                
textNode.appendChild(BX.create('STRONG', {props: {className'bx-price all'}, htmldata.SUM_REAL_BASE_FORMATED /* Изменено, оригинал: data.SUM */ }));
                if (
parseFloat(data.DISCOUNT_PRICE) > 0)
                {
                    
textNode.appendChild(BX.create('BR'));
                    
textNode.appendChild(BX.create('STRONG', {
                        
props: {className'bx-price-old'},
                        
htmldata.SUM_BASE_FORMATED
                    
}));
                }
            }

См. также:

← Переход к списку