Untitled

 avatar
unknown
plain_text
a year ago
32 kB
3
Indexable
<?php

namespace App\BitrixCatalogProviders;

use Bitrix\Catalog;
use Bitrix\Catalog\Product\Price;
use Bitrix\Currency;
use Bitrix\Iblock;
use Bitrix\Main;
use Bitrix\Main\Localization\Loc;
use Bitrix\Sale;
use Bitrix\Sale\DiscountCouponsManager;
use CCatalogDiscount;
use CCatalogDiscountSave;
use CCatalogMeasure;
use CCatalogProduct;
use CCatalogProductProvider;
use CIBlockElement;
use CModule;
use CSaleLang;
use CUser;

if (!CModule::IncludeModule("sale") || !CModule::IncludeModule("catalog")) {
    return false;
}

IncludeModuleLangFile(__FILE__);

class IdolCatalogProductProvider extends CCatalogProductProvider
{
    /**
     * @param array $arParams
     * @return array|false
     */
    public static function GetProductData($arParams)
    {
        $adminSection = (defined('ADMIN_SECTION') && ADMIN_SECTION === true);

        $useSaleDiscountOnly = CCatalogDiscount::isUsedSaleDiscountOnly();

        if (!isset($arParams['QUANTITY']) || (float)$arParams['QUANTITY'] <= 0) {
            $arParams['QUANTITY'] = 0;
        }

        if ($useSaleDiscountOnly && !isset($arParams['CHECK_DISCOUNT'])) {
            $arParams['CHECK_DISCOUNT'] = 'N';
        }

        $arParams['RENEWAL'] = (isset($arParams['RENEWAL']) && $arParams['RENEWAL'] == 'Y' ? 'Y' : 'N');
        $arParams['CHECK_QUANTITY'] = (isset($arParams['CHECK_QUANTITY']) && $arParams["CHECK_QUANTITY"] == 'N' ? 'N' : 'Y');
        $arParams['CHECK_PRICE'] = (isset($arParams['CHECK_PRICE']) && $arParams['CHECK_PRICE'] == 'N' ? 'N' : 'Y');
        $arParams['CHECK_DISCOUNT'] = (isset($arParams['CHECK_DISCOUNT']) && $arParams['CHECK_DISCOUNT'] == 'N' ? 'N' : 'Y');
        $arParams['CHECK_COUPONS'] = (isset($arParams['CHECK_COUPONS']) && $arParams['CHECK_COUPONS'] == 'N' ? 'N' : 'Y');
        if (!$useSaleDiscountOnly) {
            if ($arParams['CHECK_DISCOUNT'] == 'N') {
                $arParams['CHECK_COUPONS'] = 'N';
            }
        }

        $arParams['AVAILABLE_QUANTITY'] = (isset($arParams['AVAILABLE_QUANTITY']) && $arParams['AVAILABLE_QUANTITY'] == 'Y' ? 'Y' : 'N');
        $arParams['SELECT_QUANTITY_TRACE'] = (isset($arParams['SELECT_QUANTITY_TRACE']) && $arParams['SELECT_QUANTITY_TRACE'] == 'Y' ? 'Y' : 'N');
        $arParams['SELECT_CHECK_MAX_QUANTITY'] = (isset($arParams['SELECT_CHECK_MAX_QUANTITY']) && $arParams['SELECT_CHECK_MAX_QUANTITY'] == 'Y' ? 'Y' : 'N');
        $arParams['BASKET_ID'] = (string)(isset($arParams['BASKET_ID']) ? $arParams['BASKET_ID'] : '0');
        $arParams['USER_ID'] = (isset($arParams['USER_ID']) ? (int)$arParams['USER_ID'] : 0);
        if ($arParams['USER_ID'] < 0) {
            $arParams['USER_ID'] = 0;
        }
        $arParams['SITE_ID'] = (isset($arParams['SITE_ID']) ? $arParams['SITE_ID'] : false);
        $strSiteID = $arParams['SITE_ID'];

        $arParams['CURRENCY'] = (isset($arParams['CURRENCY']) ? Currency\CurrencyManager::checkCurrencyID($arParams['CURRENCY']) : false);
        if ($arParams['CURRENCY'] === false) {
            $arParams['CURRENCY'] = CSaleLang::GetLangCurrency($strSiteID ? $strSiteID : SITE_ID);
        }

        $productID = (int)$arParams['PRODUCT_ID'];
        $quantity = (float)$arParams['QUANTITY'];
        $intUserID = (int)$arParams['USER_ID'];

        global $USER, $APPLICATION;

        $emptyResult = [];

        if ($adminSection) {
            if (!$userGroups = static::getHitCache(self::CACHE_USER_GROUPS, $intUserID)) {
                $userGroups = self::getUserGroups($intUserID);
                static::setHitCache(self::CACHE_USER_GROUPS, $intUserID, $userGroups);
            }

            if (empty($userGroups)) {
                return $emptyResult;
            }
        } else {
            //TODO: fix for crm
            $userGroups = [2];
            if (isset($USER) && $USER instanceof CUser) {
                $userGroups = $USER->GetUserGroupArray();
            }
        }

        if (!$arProduct = static::getHitCache(self::CACHE_ITEM_WITH_RIGHTS, $productID)) {
            $elementFilter = [
                'ID' => $productID,
                'ACTIVE' => 'Y',
                'ACTIVE_DATE' => 'Y',
                'CHECK_PERMISSIONS' => 'Y',
                'MIN_PERMISSION' => 'R',
            ];
            if ($adminSection) {
                $elementFilter['PERMISSIONS_BY'] = $intUserID;
            }

            $iterator = CIBlockElement::GetList(
                [],
                $elementFilter,
                false,
                false,
                ['ID', 'IBLOCK_ID', 'NAME', 'DETAIL_PAGE_URL', 'XML_ID']
            );
            if ($arProduct = $iterator->GetNext()) {
                static::setHitCache(self::CACHE_ITEM_WITH_RIGHTS, $productID, $arProduct);
            }
            unset($dbIBlockElement, $elementFilter);
        }

        if (empty($arProduct) || !is_array($arProduct)) {
            return $emptyResult;
        }

        if (!isset(self::$catalogList[$arProduct['IBLOCK_ID']])) {
            self::$catalogList[$arProduct['IBLOCK_ID']] = Catalog\CatalogIblockTable::getList([
                'select' => ['IBLOCK_ID', 'SUBSCRIPTION', 'PRODUCT_IBLOCK_ID', 'CATALOG_XML_ID' => 'IBLOCK.XML_ID'],
                'filter' => ['=IBLOCK_ID' => $arProduct['IBLOCK_ID']],
            ])->fetch();
        }
        if (empty(self::$catalogList[$arProduct['IBLOCK_ID']]) || !is_array(self::$catalogList[$arProduct['IBLOCK_ID']])) {
            return $emptyResult;
        }
        if (self::$catalogList[$arProduct['IBLOCK_ID']]['SUBSCRIPTION'] == 'Y') {
            $quantity = 1;
        }

        if (self::$catalogList[$arProduct['IBLOCK_ID']]['PRODUCT_IBLOCK_ID'] > 0) {
            if (!static::checkParentActivity($arProduct['ID'], $arProduct['IBLOCK_ID'])) {
                return $emptyResult;
            }
        }

        if (!$arCatalogProduct = static::getHitCache(self::CACHE_PRODUCT, $productID)) {
            $select = ['ID', 'TYPE', 'AVAILABLE',
                'QUANTITY', 'QUANTITY_TRACE', 'CAN_BUY_ZERO',
                'QUANTITY_RESERVED',
                'WEIGHT', 'WIDTH', 'HEIGHT', 'LENGTH',
                'BARCODE_MULTI',
                'MEASURE',
            ];
            $select = array_merge($select, Catalog\Product\SystemField::getProviderSelectFields());
            $arCatalogProduct = Catalog\ProductTable::getList([
                'select' => $select,
                'filter' => ['=ID' => $productID],
            ])->fetch();
            if (!empty($arCatalogProduct)) {
                $arCatalogProduct['ID'] = (int)$arCatalogProduct['ID'];
                $arCatalogProduct['TYPE'] = (int)$arCatalogProduct['TYPE'];
                $arCatalogProduct['QUANTITY'] = (float)$arCatalogProduct['QUANTITY'];
                $arCatalogProduct['QUANTITY_RESERVED'] = (float)$arCatalogProduct['QUANTITY_RESERVED'];
                Catalog\Product\SystemField::prepareRow($arCatalogProduct, Catalog\Product\SystemField::OPERATION_PROVIDER);

                static::setHitCache(self::CACHE_PRODUCT, $productID, $arCatalogProduct);
            }
        }
        if (empty($arCatalogProduct) || !is_array($arCatalogProduct)) {
            $APPLICATION->ThrowException(Loc::getMessage("CATALOG_ERR_NO_PRODUCT"), "CATALOG_NO_QUANTITY_PRODUCT");
            return $emptyResult;
        }

        if (
            ($arCatalogProduct['TYPE'] == Catalog\ProductTable::TYPE_SKU || $arCatalogProduct['TYPE'] == Catalog\ProductTable::TYPE_EMPTY_SKU)
            && (string)Main\Config\Option::get('catalog', 'show_catalog_tab_with_offers') != 'Y'
        ) {
            $APPLICATION->ThrowException(Loc::getMessage("CATALOG_ERR_SKU_PRODUCT"), 'CATALOG_SKU_PRODUCT');
            return $emptyResult;
        }

        if (
            $arParams["CHECK_QUANTITY"] == "Y"
            && $arCatalogProduct['AVAILABLE'] != Catalog\ProductTable::STATUS_YES
        ) {
            $APPLICATION->ThrowException(
                Loc::getMessage("CATALOG_NO_QUANTITY_PRODUCT", ["#NAME#" => $arProduct["NAME"]]),
                "CATALOG_NO_QUANTITY_PRODUCT"
            );
            return $emptyResult;
        }

        if ($arCatalogProduct['TYPE'] == Catalog\ProductTable::TYPE_SET) {
            static::$errors = [];
            if (!static::checkProductSet($productID)) {
                $APPLICATION->ThrowException(implode(', ', static::$errors), 'NO_PRODUCT');
                static::$errors = [];
                return $emptyResult;
            }
        }

        if ($arCatalogProduct['TYPE'] == Catalog\ProductTable::TYPE_OFFER) {
            if (mb_strpos($arProduct["~XML_ID"], '#') === false) {
                $parent = \CCatalogSku::GetProductInfo($arProduct['ID'], $arProduct['IBLOCK_ID']);
                if (!empty($parent)) {
                    $parentIterator = Iblock\ElementTable::getList([
                        'select' => ['ID', 'XML_ID'],
                        'filter' => ['=ID' => $parent['ID']],
                    ]);
                    $parentData = $parentIterator->fetch();
                    if (!empty($parentData)) {
                        $arProduct['~XML_ID'] = $parentData['XML_ID'] . '#' . $arProduct['~XML_ID'];
                    }
                    unset($parentData, $parentIterator);
                }
                unset($parent);
            }
        }

        $dblQuantity = $arCatalogProduct['QUANTITY'];
        $quantityLimited = ($arCatalogProduct['QUANTITY_TRACE'] == Catalog\ProductTable::STATUS_YES
            && $arCatalogProduct['CAN_BUY_ZERO'] == Catalog\ProductTable::STATUS_NO);
        $quantityLimitExceeded = ($quantityLimited && $dblQuantity < $quantity);

        $arCatalogProduct['MEASURE'] = (int)$arCatalogProduct['MEASURE'];
        $arCatalogProduct['MEASURE_NAME'] = '';
        $arCatalogProduct['MEASURE_CODE'] = 0;
        if ($arCatalogProduct['MEASURE'] <= 0) {
            $arMeasure = CCatalogMeasure::getDefaultMeasure(true, true);
            $arCatalogProduct['MEASURE_NAME'] = $arMeasure['~SYMBOL_RUS'];
            $arCatalogProduct['MEASURE_CODE'] = $arMeasure['CODE'];
        } else {
            $rsMeasures = CCatalogMeasure::getList(
                [],
                ['ID' => $arCatalogProduct['MEASURE']],
                false,
                false,
                ['ID', 'SYMBOL_RUS', 'CODE']
            );
            if ($arMeasure = $rsMeasures->Fetch()) {
                $arCatalogProduct['MEASURE_NAME'] = $arMeasure['SYMBOL_RUS'];
                $arCatalogProduct['MEASURE_CODE'] = $arMeasure['CODE'];
            }
        }

        $arResult = [
//            "NAME" => $arProduct["~NAME"],
            "CAN_BUY" => "Y",
            "DETAIL_PAGE_URL" => $arProduct['~DETAIL_PAGE_URL'],
            "BARCODE_MULTI" => $arCatalogProduct["BARCODE_MULTI"],
            "WEIGHT" => (float)$arCatalogProduct['WEIGHT'],
            "DIMENSIONS" => serialize([
                "WIDTH" => $arCatalogProduct["WIDTH"],
                "HEIGHT" => $arCatalogProduct["HEIGHT"],
                "LENGTH" => $arCatalogProduct["LENGTH"],
            ]),
            "VAT_INCLUDED" => "Y",
            "MEASURE_ID" => $arCatalogProduct['MEASURE'],
            "MEASURE_NAME" => $arCatalogProduct['MEASURE_NAME'],
            "MEASURE_CODE" => $arCatalogProduct['MEASURE_CODE'],
            "CATALOG_XML_ID" => self::$catalogList[$arProduct['IBLOCK_ID']]['CATALOG_XML_ID'],
            "PRODUCT_XML_ID" => $arProduct['~XML_ID'],
        ];
        switch ($arCatalogProduct['TYPE']) {
            case Catalog\ProductTable::TYPE_SET:
                $arResult['TYPE'] = Sale\BasketItem::TYPE_SET;
                break;
            case Catalog\ProductTable::TYPE_SERVICE:
                $arResult['TYPE'] = Sale\BasketItem::TYPE_SERVICE;
                break;
            default:
                $arResult['TYPE'] = null;
                break;
        }
        foreach (Catalog\Product\SystemField::getProviderSelectFields() as $index => $value) {
            $field = is_string($index) ? $index : $value;
            $arResult[$field] = $arCatalogProduct[$field];
        }

        if ($arParams['SELECT_QUANTITY_TRACE'] == "Y") {
            $arResult["QUANTITY_TRACE"] = $arCatalogProduct["QUANTITY_TRACE"];
        }
        if ($arParams['SELECT_CHECK_MAX_QUANTITY'] == 'Y') {
            $arResult['CHECK_MAX_QUANTITY'] = ($quantityLimited ? 'Y' : 'N');
        }

        if ($arParams["CHECK_QUANTITY"] == "Y") {
            $arResult["QUANTITY"] = ($quantityLimitExceeded ? $dblQuantity : $quantity);
            if ($quantityLimitExceeded) {
                $APPLICATION->ThrowException(
                    Loc::getMessage(
                        "CATALOG_QUANTITY_NOT_ENOGH",
                        [
                            "#NAME#" => $arProduct["NAME"],
                            "#CATALOG_QUANTITY#" => $dblQuantity,
                            "#QUANTITY#" => $quantity,
                            '#MEASURE_NAME#' => $arCatalogProduct['MEASURE_NAME'],
                        ]
                    ),
                    "CATALOG_QUANTITY_NOT_ENOGH"
                );
            }
        } else {
            $arResult["QUANTITY"] = $arParams["QUANTITY"];
        }

        if ($arParams["AVAILABLE_QUANTITY"] == "Y") {
            $arResult["AVAILABLE_QUANTITY"] = ($quantityLimitExceeded ? $dblQuantity : $quantity);
        }

        if ($arParams["CHECK_PRICE"] == "Y") {
            $productHash = [
                'MODULE_ID' => ($useSaleDiscountOnly ? 'sale' : 'catalog'),
                'PRODUCT_ID' => $productID,
                'BASKET_ID' => $arParams['BASKET_ID'],
            ];

            $arCoupons = [];
            if ($arParams['CHECK_COUPONS'] == 'Y') {
                if ($useSaleDiscountOnly) {
                    $arCoupons = DiscountCouponsManager::getForApply(['MODULE_ID' => 'sale'], $productHash, true);
                } else {
                    $arCoupons = DiscountCouponsManager::getForApply(['MODULE_ID' => 'catalog'], $productHash, true);
                }
                if (!empty($arCoupons)) {
                    $arCoupons = array_keys($arCoupons);
                }
            }
            if ($adminSection) {
                if ($intUserID > 0) {
                    CCatalogDiscountSave::SetDiscountUserID($intUserID);
                } else {
                    CCatalogDiscountSave::Disable();
                }
            }

            Price\Calculation::pushConfig();
            Price\Calculation::setConfig([
                'CURRENCY' => $arParams['CURRENCY'],
                'PRECISION' => (int)Main\Config\Option::get('sale', 'value_precision'),
                'USE_DISCOUNTS' => $arParams['CHECK_DISCOUNT'] == 'Y',
                'RESULT_WITH_VAT' => true,
                'RESULT_MODE' => Catalog\Product\Price\Calculation::RESULT_MODE_RAW,
            ]);

            $arPrice = CCatalogProduct::GetOptimalPrice(
                $productID,
                $quantity,
                $userGroups,
                $arParams['RENEWAL'],
                [],
                ($adminSection ? $strSiteID : false),
                $arCoupons
            );

            if (empty($arPrice)) {
                if ($nearestQuantity = CCatalogProduct::GetNearestQuantityPrice($productID, $quantity, $userGroups)) {
                    $quantity = $nearestQuantity;
                    $arPrice = CCatalogProduct::GetOptimalPrice(
                        $productID,
                        $quantity,
                        $userGroups,
                        $arParams['RENEWAL'],
                        [],
                        ($adminSection ? $strSiteID : false),
                        $arCoupons
                    );
                }
            }

            Price\Calculation::popConfig();

            unset($userGroups);

            if ($adminSection) {
                if ($intUserID > 0) {
                    CCatalogDiscountSave::ClearDiscountUserID();
                } else {
                    CCatalogDiscountSave::Enable();
                }
            }

            if (empty($arPrice)) {
                return $emptyResult;
            }

            $arDiscountList = [];
            if (empty($arPrice['DISCOUNT_LIST']) && !empty($arPrice['DISCOUNT']) && is_array($arPrice['DISCOUNT'])) {
                $arPrice['DISCOUNT_LIST'] = [$arPrice['DISCOUNT']];
            }
            if (!empty($arPrice['DISCOUNT_LIST'])) {
                $appliedCoupons = [];
                foreach ($arPrice['DISCOUNT_LIST'] as &$arOneDiscount) {
                    $arDiscountList[] = CCatalogDiscount::getDiscountDescription($arOneDiscount);

                    if (!empty($arOneDiscount['COUPON'])) {
                        $appliedCoupons[] = $arOneDiscount['COUPON'];
                    }
                }
                unset($arOneDiscount);
                if (!empty($appliedCoupons)) {
                    $resultApply = DiscountCouponsManager::setApplyByProduct($productHash, $appliedCoupons);
                }
                unset($resultApply, $appliedCoupons);
            }

            if (empty($arPrice['PRICE']['CATALOG_GROUP_NAME'])) {
                if (!empty($arPrice['PRICE']['CATALOG_GROUP_ID'])) {
                    $priceName = self::getPriceTitle($arPrice['PRICE']['CATALOG_GROUP_ID']);
                    if ($priceName != '') {
                        $arPrice['PRICE']['CATALOG_GROUP_NAME'] = $priceName;
                    }
                    unset($priceName);
                }
            }

            $arResult['PRODUCT_PRICE_ID'] = $arPrice['RESULT_PRICE']['ID'];
            $arResult['NOTES'] = $arPrice['PRICE']['CATALOG_GROUP_NAME'];
            $arResult['VAT_RATE'] = $arPrice['RESULT_PRICE']['VAT_RATE'];
            $arResult['VAT_INCLUDED'] = $arPrice['RESULT_PRICE']['VAT_INCLUDED'];
            $arResult['DISCOUNT_NAME'] = null;
            $arResult['DISCOUNT_COUPON'] = null;
            $arResult['DISCOUNT_VALUE'] = null;
            $arResult['DISCOUNT_LIST'] = [];

            if (empty($arPrice['RESULT_PRICE']) || !is_array($arPrice['RESULT_PRICE'])) {
                $arPrice['RESULT_PRICE'] = CCatalogDiscount::calculateDiscountList($arPrice['PRICE'], $arParams['CURRENCY'], $arDiscountList, true);
            }

            $arResult['PRICE_TYPE_ID'] = $arPrice['RESULT_PRICE']['PRICE_TYPE_ID'];
            $arResult['BASE_PRICE'] = $arPrice['RESULT_PRICE']['BASE_PRICE'];
            $arResult['PRICE'] = $arPrice['RESULT_PRICE']['DISCOUNT_PRICE'];
            $arResult['CURRENCY'] = $arPrice['RESULT_PRICE']['CURRENCY'];
            $arResult['DISCOUNT_PRICE'] = $arPrice['RESULT_PRICE']['DISCOUNT'];
            if ($arParams['CHECK_DISCOUNT'] == 'Y') {
                if (isset($arPrice['RESULT_PRICE']['PERCENT'])) {
                    $arResult['DISCOUNT_VALUE'] = ($arPrice['RESULT_PRICE']['PERCENT'] > 0 ? $arPrice['RESULT_PRICE']['PERCENT'] . '%' : null);
                }
            }

            if (!empty($arDiscountList)) {
                $arResult['DISCOUNT_LIST'] = $arDiscountList;
            }
            if (!empty($arPrice['DISCOUNT'])) {
                $arResult['DISCOUNT_NAME'] = '[' . $arPrice['DISCOUNT']['ID'] . '] ' . $arPrice['DISCOUNT']['NAME'];
                if (!empty($arPrice['DISCOUNT']['COUPON'])) {
                    $arResult['DISCOUNT_COUPON'] = $arPrice['DISCOUNT']['COUPON'];
                }

                if (empty($arResult['DISCOUNT_LIST'])) {
                    $arResult['DISCOUNT_LIST'] = [$arPrice['DISCOUNT']];
                }
            }
        } else {
            $vatRate = null;

            if (!$arVAT = static::getHitCache(self::CACHE_VAT, $productID)) {
                $arVat = CCatalogProduct::GetVATDataByID($productID);
                if (!empty($arVAT)) {
                    static::setHitCache(self::CACHE_VAT, $productID, $arVAT);
                }
            }

            if (isset($arVAT) && is_array($arVAT)) {
                if ($arVat['EXCLUDE_VAT'] === 'N') {
                    $vatRate = $arVAT['RATE'] * 0.01;
                }
            }

            $arResult['VAT_RATE'] = $vatRate;
        }

        return $arResult;
    }

    /**
     * @param array $arParams
     * @return array|false
     */
    public static function OrderProduct($arParams)
    {
        $adminSection = (defined('ADMIN_SECTION') && ADMIN_SECTION === true);

        $useSaleDiscountOnly = CCatalogDiscount::isUsedSaleDiscountOnly();

        if ($useSaleDiscountOnly && !isset($arParams['CHECK_DISCOUNT'])) {
            $arParams['CHECK_DISCOUNT'] = 'N';
        }

        $arParams['RENEWAL'] = (isset($arParams['RENEWAL']) && $arParams['RENEWAL'] == 'Y' ? 'Y' : 'N');
        $arParams['CHECK_QUANTITY'] = (isset($arParams['CHECK_QUANTITY']) && $arParams['CHECK_QUANTITY'] == 'N' ? 'N' : 'Y');
        $arParams['CHECK_DISCOUNT'] = (isset($arParams['CHECK_DISCOUNT']) && $arParams['CHECK_DISCOUNT'] == 'N' ? 'N' : 'Y');
        $arParams['USER_ID'] = (isset($arParams['USER_ID']) ? (int)$arParams['USER_ID'] : 0);
        if ($arParams['USER_ID'] < 0) {
            $arParams['USER_ID'] = 0;
        }
        $arParams['SITE_ID'] = (isset($arParams['SITE_ID']) ? $arParams['SITE_ID'] : false);
        $strSiteID = $arParams['SITE_ID'];
        $arParams['BASKET_ID'] = (string)(isset($arParams['BASKET_ID']) ? $arParams['BASKET_ID'] : '0');

        $arParams['CURRENCY'] = (isset($arParams['CURRENCY']) ? Currency\CurrencyManager::checkCurrencyID($arParams['CURRENCY']) : false);
        if ($arParams['CURRENCY'] === false) {
            $arParams['CURRENCY'] = CSaleLang::GetLangCurrency($strSiteID ? $strSiteID : SITE_ID);
        }

        global $USER;

        $productID = (int)$arParams['PRODUCT_ID'];
        $quantity = (float)$arParams['QUANTITY'];
        $intUserID = (int)$arParams['USER_ID'];

        $arResult = [];

        if ($adminSection) {
            if ($intUserID == 0) {
                return $arResult;
            }

            if (!$userGroups = static::getHitCache(self::CACHE_USER_GROUPS, $intUserID)) {
                $userGroups = self::getUserGroups($intUserID);
                static::setHitCache(self::CACHE_USER_GROUPS, $intUserID, $userGroups);
            }

            if (empty($userGroups)) {
                return $arResult;
            }
        } else {
            $userGroups = [2];
            if (isset($USER) && $USER instanceof CUser) {
                $userGroups = $USER->GetUserGroupArray();
            }
        }

        if (!$arProduct = static::getHitCache(self::CACHE_ITEM_WITH_RIGHTS, $productID)) {
            $elementFilter = [
                'ID' => $productID,
                'ACTIVE' => 'Y',
                'ACTIVE_DATE' => 'Y',
                'CHECK_PERMISSIONS' => 'Y',
                'MIN_PERMISSION' => 'R',
            ];
            if ($adminSection) {
                $elementFilter['PERMISSIONS_BY'] = $intUserID;
            }

            $iterator = CIBlockElement::GetList(
                [],
                $elementFilter,
                false,
                false,
                ['ID', 'IBLOCK_ID', 'NAME', 'DETAIL_PAGE_URL']
            );
            if ($arProduct = $iterator->GetNext()) {
                static::setHitCache(self::CACHE_ITEM_WITH_RIGHTS, $productID, $arProduct);
            }
            unset($dbIBlockElement, $elementFilter);
        }

        if (empty($arProduct) || !is_array($arProduct)) {
            return $arResult;
        }

        if (!static::checkParentActivity($arProduct['ID'], $arProduct['IBLOCK_ID'])) {
            return $arResult;
        }

        if (!$arCatalogProduct = static::getHitCache(self::CACHE_PRODUCT, $productID)) {
            $select = ['ID', 'TYPE', 'AVAILABLE',
                'QUANTITY', 'QUANTITY_TRACE', 'CAN_BUY_ZERO',
                'WEIGHT', 'WIDTH', 'HEIGHT', 'LENGTH',
                'BARCODE_MULTI',
                'MEASURE',
            ];
            $select = array_merge($select, Catalog\Product\SystemField::getProviderSelectFields());
            $arCatalogProduct = Catalog\ProductTable::getList([
                'select' => $select,
                'filter' => ['=ID' => $productID],
            ])->fetch();
            if (!empty($arCatalogProduct)) {
                Catalog\Product\SystemField::prepareRow($arCatalogProduct, Catalog\Product\SystemField::OPERATION_PROVIDER);
                $arCatalogProduct['QUANTITY'] = (float)$arCatalogProduct['QUANTITY'];
                static::setHitCache(self::CACHE_PRODUCT, $productID, $arCatalogProduct);
            }
        }

        if (empty($arCatalogProduct) || !is_array($arCatalogProduct)) {
            return $arResult;
        }

        if (
            ($arCatalogProduct['TYPE'] == Catalog\ProductTable::TYPE_SKU || $arCatalogProduct['TYPE'] == Catalog\ProductTable::TYPE_EMPTY_SKU)
            && (string)Main\Config\Option::get('catalog', 'show_catalog_tab_with_offers') != 'Y'
        ) {
            return $arResult;
        }

        if (
            $arParams["CHECK_QUANTITY"] == "Y"
            && $arCatalogProduct['AVAILABLE'] != Catalog\ProductTable::STATUS_YES
        ) {
            return $arResult;
        }

        if ($arCatalogProduct['TYPE'] == Catalog\ProductTable::TYPE_SET) {
            static::$errors = [];
            if (!static::checkProductSet($productID)) {
                static::$errors = [];
                return $arResult;
            }
        }

        if ($adminSection) {
            CCatalogDiscountSave::SetDiscountUserID($intUserID);
        }

        $productHash = [
            'MODULE' => ($useSaleDiscountOnly ? 'sale' : 'catalog'),
            'PRODUCT_ID' => $productID,
            'BASKET_ID' => $arParams['BASKET_ID'],
        ];
        $arCoupons = DiscountCouponsManager::getForApply([], $productHash, true);

        if (!empty($arCoupons)) {
            $arCoupons = array_keys($arCoupons);
        }

        Price\Calculation::pushConfig();
        Price\Calculation::setConfig([
            'CURRENCY' => $arParams['CURRENCY'],
            'PRECISION' => (int)Main\Config\Option::get('sale', 'value_precision'),
            'USE_DISCOUNTS' => $arParams['CHECK_DISCOUNT'] == 'Y',
            'RESULT_WITH_VAT' => true,
            'RESULT_MODE' => Catalog\Product\Price\Calculation::RESULT_MODE_RAW,
        ]);

        $arPrice = CCatalogProduct::GetOptimalPrice(
            $productID,
            $quantity,
            $userGroups,
            $arParams['RENEWAL'],
            [],
            ($adminSection ? $strSiteID : false),
            $arCoupons
        );

        if (empty($arPrice)) {
            if ($nearestQuantity = CCatalogProduct::GetNearestQuantityPrice($productID, $quantity, $userGroups)) {
                $quantity = $nearestQuantity;
                $arPrice = CCatalogProduct::GetOptimalPrice(
                    $productID,
                    $quantity,
                    $userGroups,
                    $arParams['RENEWAL'],
                    [],
                    ($adminSection ? $strSiteID : false),
                    $arCoupons
                );
            }
        }

        Price\Calculation::popConfig();

        unset($userGroups);
        if ($adminSection) {
            CCatalogDiscountSave::ClearDiscountUserID();
        }

        if (empty($arPrice)) {
            return $arResult;
        }

        $arDiscountList = [];
        if (empty($arPrice['DISCOUNT_LIST']) && !empty($arPrice['DISCOUNT']) && is_array($arPrice['DISCOUNT'])) {
            $arPrice['DISCOUNT_LIST'] = [$arPrice['DISCOUNT']];
        }
        if (!empty($arPrice['DISCOUNT_LIST'])) {
            $appliedCoupons = [];
            foreach ($arPrice['DISCOUNT_LIST'] as &$arOneDiscount) {
                $arDiscountList[] = CCatalogDiscount::getDiscountDescription($arOneDiscount);

                if (!empty($arOneDiscount['COUPON'])) {
                    $appliedCoupons[] = $arOneDiscount['COUPON'];
                }
            }
            unset($arOneDiscount);
            if (!empty($appliedCoupons)) {
                $resultApply = DiscountCouponsManager::setApplyByProduct($productHash, $appliedCoupons);
            }
            unset($resultApply, $appliedCoupons);
        }

        if (empty($arPrice['PRICE']['CATALOG_GROUP_NAME'])) {
            if (!empty($arPrice['PRICE']['CATALOG_GROUP_ID'])) {
                $priceName = self::getPriceTitle($arPrice['PRICE']['CATALOG_GROUP_ID']);
                if ($priceName != '') {
                    $arPrice['PRICE']['CATALOG_GROUP_NAME'] = $priceName;
                }
                unset($priceName);
            }
        }

        if (empty($arPrice['RESULT_PRICE']) || !is_array($arPrice['RESULT_PRICE'])) {
            $arPrice['RESULT_PRICE'] = CCatalogDiscount::calculateDiscountList($arPrice['PRICE'], $arParams['CURRENCY'], $arDiscountList, true);
        }

        $arResult = [
            'PRODUCT_PRICE_ID' => $arPrice['RESULT_PRICE']['ID'],
//			"AVAILABLE_QUANTITY" => $arCatalogProduct["QUANTITY"],
            'PRICE_TYPE_ID' => $arPrice['RESULT_PRICE']['PRICE_TYPE_ID'],
//            'BASE_PRICE' => $arPrice['RESULT_PRICE']['BASE_PRICE'],
            'PRICE' => $arPrice['RESULT_PRICE']['DISCOUNT_PRICE'],
            'VAT_RATE' => $arPrice['RESULT_PRICE']['VAT_RATE'],
            'VAT_INCLUDED' => $arPrice['RESULT_PRICE']['VAT_INCLUDED'],
            "CURRENCY" => $arPrice['RESULT_PRICE']['CURRENCY'],
            "WEIGHT" => (float)$arCatalogProduct["WEIGHT"],
            "DIMENSIONS" => serialize([
                "WIDTH" => $arCatalogProduct["WIDTH"],
                "HEIGHT" => $arCatalogProduct["HEIGHT"],
                "LENGTH" => $arCatalogProduct["LENGTH"],
            ]),
            "NAME" => $arProduct["~NAME"],
            "CAN_BUY" => "Y",
            "DETAIL_PAGE_URL" => $arProduct['~DETAIL_PAGE_URL'],
            "NOTES" => $arPrice["PRICE"]["CATALOG_GROUP_NAME"],
            "DISCOUNT_PRICE" => $arPrice['RESULT_PRICE']['DISCOUNT'],
            "DISCOUNT_VALUE" => ($arPrice['RESULT_PRICE']['PERCENT'] > 0 ? $arPrice['RESULT_PRICE']['PERCENT'] . '%' : null),
            "DISCOUNT_NAME" => null,
            "DISCOUNT_COUPON" => null,
            "DISCOUNT_LIST" => [],
        ];
        switch ($arCatalogProduct['TYPE']) {
            case Catalog\ProductTable::TYPE_SET:
                $arResult['TYPE'] = Sale\BasketItem::TYPE_SET;
                break;
            case Catalog\ProductTable::TYPE_SERVICE:
                $arResult['TYPE'] = Sale\BasketItem::TYPE_SERVICE;
                break;
            default:
                $arResult['TYPE'] = null;
                break;
        }
        foreach (Catalog\Product\SystemField::getProviderSelectFields() as $index => $value) {
            $field = is_string($index) ? $index : $value;
            $arResult[$field] = $arCatalogProduct[$field];
        }

        if ($arParams["CHECK_QUANTITY"] == "Y") {
            $arResult["QUANTITY"] = $quantity;
        } else {
            $arResult["QUANTITY"] = $arParams["QUANTITY"];
        }

        if (!empty($arDiscountList)) {
            $arResult['DISCOUNT_LIST'] = $arDiscountList;
        }
        if (!empty($arPrice['DISCOUNT'])) {
            $arResult['DISCOUNT_NAME'] = '[' . $arPrice['DISCOUNT']['ID'] . '] ' . $arPrice['DISCOUNT']['NAME'];
            if (!empty($arPrice['DISCOUNT']['COUPON'])) {
                $arResult['DISCOUNT_COUPON'] = $arPrice['DISCOUNT']['COUPON'];
            }

            if (empty($arResult['DISCOUNT_LIST'])) {
                $arResult['DISCOUNT_LIST'] = [$arPrice['DISCOUNT']];
            }
        }

        return $arResult;
    }
}