Last active
April 18, 2022 12:36
-
-
Save EscApp2/cdea9cb3bb06a179dd15afc0c1d5afa2 to your computer and use it in GitHub Desktop.
basket_price_change OnGetOptimalPrice GetOptimalPrice Get Optimal Price
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<? | |
CModule::IncludeModule('catalog'); | |
CModule::IncludeModule('sale'); | |
use Bitrix\Main\Localization\Loc, | |
Bitrix\Main, | |
Bitrix\Currency, | |
Bitrix\Catalog, | |
Bitrix\Sale; | |
class CCatalogProductCustom extends CCatalogProduct{ | |
public static function GetOptimalPriceCustom( | |
$intProductID, $quantity = 1, $arUserGroups = array(), | |
$renewal = "N", $priceList = array(), $siteID = false, | |
$arDiscountCoupons = false) | |
{ | |
global $APPLICATION; | |
$intProductID = (int)$intProductID; | |
if ($intProductID <= 0) | |
{ | |
$APPLICATION->ThrowException(Loc::getMessage("BT_MOD_CATALOG_PROD_ERR_PRODUCT_ID_ABSENT"), "NO_PRODUCT_ID"); | |
return false; | |
} | |
$quantity = (float)$quantity; | |
if ($quantity <= 0) | |
{ | |
$APPLICATION->ThrowException(Loc::getMessage("BT_MOD_CATALOG_PROD_ERR_QUANTITY_ABSENT"), "NO_QUANTITY"); | |
return false; | |
} | |
if (!is_array($arUserGroups) && (int)$arUserGroups.'|' == (string)$arUserGroups.'|') | |
$arUserGroups = array((int)$arUserGroups); | |
if (!is_array($arUserGroups)) | |
$arUserGroups = array(); | |
if (!in_array(2, $arUserGroups)) | |
$arUserGroups[] = 2; | |
Main\Type\Collection::normalizeArrayValuesByInt($arUserGroups); | |
$renewal = ($renewal == 'Y' ? 'Y' : 'N'); | |
if ($siteID === false) | |
$siteID = SITE_ID; | |
$resultCurrency = Catalog\Product\Price\Calculation::getCurrency(); | |
if (empty($resultCurrency)) | |
{ | |
$APPLICATION->ThrowException(Loc::getMessage("BT_MOD_CATALOG_PROD_ERR_NO_RESULT_CURRENCY")); | |
return false; | |
} | |
$intIBlockID = (int)CIBlockElement::GetIBlockByID($intProductID); | |
if ($intIBlockID <= 0) | |
{ | |
$APPLICATION->ThrowException( | |
Loc::getMessage( | |
'BT_MOD_CATALOG_PROD_ERR_ELEMENT_ID_NOT_FOUND', | |
array('#ID#' => $intProductID) | |
), | |
'NO_ELEMENT' | |
); | |
return false; | |
} | |
if (!isset($priceList) || !is_array($priceList)) | |
$priceList = array(); | |
if (empty($priceList)) | |
{ | |
$priceTypeList = self::getAllowedPriceTypesCustom($arUserGroups); | |
if (empty($priceTypeList)) | |
return false; | |
$iterator = Catalog\PriceTable::getList(array( | |
'select' => array('ID', 'CATALOG_GROUP_ID', 'PRICE', 'CURRENCY'), | |
'filter' => array( | |
'=PRODUCT_ID' => $intProductID, | |
'@CATALOG_GROUP_ID' => $priceTypeList, | |
array( | |
'LOGIC' => 'OR', | |
'<=QUANTITY_FROM' => $quantity, | |
'=QUANTITY_FROM' => null | |
), | |
array( | |
'LOGIC' => 'OR', | |
'>=QUANTITY_TO' => $quantity, | |
'=QUANTITY_TO' => null | |
) | |
), | |
'order' => array('CATALOG_GROUP_ID' => 'ASC') | |
)); | |
while ($row = $iterator->fetch()) | |
{ | |
$row['ELEMENT_IBLOCK_ID'] = $intIBlockID; | |
$priceList[] = $row; | |
} | |
unset($row, $iterator); | |
unset($priceTypeList); | |
} | |
else | |
{ | |
foreach (array_keys($priceList) as $priceIndex) | |
$priceList[$priceIndex]['ELEMENT_IBLOCK_ID'] = $intIBlockID; | |
unset($priceIndex); | |
} | |
if (empty($priceList)) | |
return false; | |
$vat = CCatalogProduct::GetVATDataByID($intProductID); | |
if (!empty($vat)) | |
{ | |
$vat['RATE'] = (float)$vat['RATE'] * 0.01; | |
} | |
else | |
{ | |
$vat = array('RATE' => 0.0, 'VAT_INCLUDED' => 'N'); | |
} | |
unset($iterator); | |
$isNeedDiscounts = Catalog\Product\Price\Calculation::isAllowedUseDiscounts(); | |
$resultWithVat = Catalog\Product\Price\Calculation::isIncludingVat(); | |
if ($isNeedDiscounts) | |
{ | |
if ($arDiscountCoupons === false) | |
$arDiscountCoupons = CCatalogDiscountCoupon::GetCoupons(); | |
} | |
// $boolDiscountVat = ('N' != COption::GetOptionString('catalog', 'discount_vat', 'Y')); | |
$boolDiscountVat = true; | |
$minimalPrice = array(); | |
if (self::$saleIncluded === null) | |
self::initSaleSettingsCustom(); | |
$isNeedleToMinimizeCatalogGroup = self::isNeedleToMinimizeCatalogGroupCustom($priceList); | |
foreach ($priceList as $priceData) | |
{ | |
$priceData['VAT_RATE'] = $vat['RATE']; | |
$priceData['VAT_INCLUDED'] = $vat['VAT_INCLUDED']; | |
$currentPrice = (float)$priceData['PRICE']; | |
if ($boolDiscountVat) | |
{ | |
if ($priceData['VAT_INCLUDED'] == 'N') | |
$currentPrice *= (1 + $priceData['VAT_RATE']); | |
} | |
else | |
{ | |
if ($priceData['VAT_INCLUDED'] == 'Y') | |
$currentPrice /= (1 + $priceData['VAT_RATE']); | |
} | |
if ($priceData['CURRENCY'] != $resultCurrency) | |
$currentPrice = CCurrencyRates::ConvertCurrency($currentPrice, $priceData['CURRENCY'], $resultCurrency); | |
$currentPrice = Catalog\Product\Price\Calculation::roundPrecision($currentPrice); | |
$result = array( | |
'BASE_PRICE' => $currentPrice, | |
'COMPARE_PRICE' => $currentPrice, | |
'PRICE' => $currentPrice, | |
'CURRENCY' => $resultCurrency, | |
'DISCOUNT_LIST' => array(), | |
'RAW_PRICE' => $priceData | |
); | |
if ($isNeedDiscounts) | |
{ | |
$arDiscounts = CCatalogDiscount::GetDiscount( | |
$intProductID, | |
$intIBlockID, | |
array($priceData['CATALOG_GROUP_ID']), | |
$arUserGroups, | |
$renewal, | |
$siteID, | |
$arDiscountCoupons | |
); | |
$discountResult = CCatalogDiscount::applyDiscountList($currentPrice, $resultCurrency, $arDiscounts); | |
unset($arDiscounts); | |
if ($discountResult === false) | |
return false; | |
$result['PRICE'] = $discountResult['PRICE']; | |
$result['COMPARE_PRICE'] = $discountResult['PRICE']; | |
$result['DISCOUNT_LIST'] = $discountResult['DISCOUNT_LIST']; | |
unset($discountResult); | |
} | |
elseif($isNeedleToMinimizeCatalogGroup) | |
{ | |
$calculateData = $priceData; | |
$calculateData['PRICE'] = $currentPrice; | |
$calculateData['CURRENCY'] = $resultCurrency; | |
$possibleSalePrice = self::getPossibleSalePriceCustom( | |
$intProductID, | |
$calculateData, | |
$quantity, | |
$siteID, | |
$arUserGroups, | |
$arDiscountCoupons | |
); | |
unset($calculateData); | |
if ($possibleSalePrice === null) | |
return false; | |
$result['COMPARE_PRICE'] = $possibleSalePrice; | |
unset($possibleSalePrice); | |
} | |
if ($boolDiscountVat) | |
{ | |
if (!$resultWithVat) | |
{ | |
$result['PRICE'] /= (1 + $priceData['VAT_RATE']); | |
$result['COMPARE_PRICE'] /= (1 + $priceData['VAT_RATE']); | |
$result['BASE_PRICE'] /= (1 + $priceData['VAT_RATE']); | |
} | |
} | |
else | |
{ | |
if ($resultWithVat) | |
{ | |
$result['PRICE'] *= (1 + $priceData['VAT_RATE']); | |
$result['COMPARE_PRICE'] *= (1 + $priceData['VAT_RATE']); | |
$result['BASE_PRICE'] *= (1 + $priceData['VAT_RATE']); | |
} | |
} | |
$result['UNROUND_PRICE'] = $result['PRICE']; | |
$result['UNROUND_BASE_PRICE'] = $result['BASE_PRICE']; | |
if (Catalog\Product\Price\Calculation::isComponentResultMode()) | |
{ | |
$result['BASE_PRICE'] = Catalog\Product\Price::roundPrice( | |
$priceData['CATALOG_GROUP_ID'], | |
$result['BASE_PRICE'], | |
$resultCurrency | |
); | |
$result['PRICE'] = Catalog\Product\Price::roundPrice( | |
$priceData['CATALOG_GROUP_ID'], | |
$result['PRICE'], | |
$resultCurrency | |
); | |
if ( | |
empty($result['DISCOUNT_LIST']) | |
|| Catalog\Product\Price\Calculation::compare($result['BASE_PRICE'], $result['PRICE'], '<=') | |
) | |
{ | |
$result['BASE_PRICE'] = $result['PRICE']; | |
} | |
$result['COMPARE_PRICE'] = $result['PRICE']; | |
} | |
if (empty($minimalPrice) || $minimalPrice['COMPARE_PRICE'] > $result['COMPARE_PRICE']) | |
{ | |
$minimalPrice = $result; | |
} | |
unset($currentPrice, $result); | |
} | |
unset($priceData); | |
unset($vat); | |
$discountValue = ($minimalPrice['BASE_PRICE'] - $minimalPrice['PRICE']); | |
$arResult = array( | |
'PRICE' => $minimalPrice['RAW_PRICE'], | |
'RESULT_PRICE' => array( | |
'PRICE_TYPE_ID' => $minimalPrice['RAW_PRICE']['CATALOG_GROUP_ID'], | |
'BASE_PRICE' => $minimalPrice['BASE_PRICE'], | |
'DISCOUNT_PRICE' => $minimalPrice['PRICE'], | |
'CURRENCY' => $resultCurrency, | |
'DISCOUNT' => $discountValue, | |
'PERCENT' => ( | |
$minimalPrice['BASE_PRICE'] > 0 && $discountValue > 0 | |
? round((100*$discountValue)/$minimalPrice['BASE_PRICE'], 0) | |
: 0 | |
), | |
'VAT_RATE' => $minimalPrice['RAW_PRICE']['VAT_RATE'], | |
'VAT_INCLUDED' => ($resultWithVat ? 'Y' : 'N'), | |
'UNROUND_BASE_PRICE' => $minimalPrice['UNROUND_BASE_PRICE'], | |
'UNROUND_DISCOUNT_PRICE' => $minimalPrice['UNROUND_PRICE'] | |
), | |
'DISCOUNT_PRICE' => $minimalPrice['PRICE'], | |
'DISCOUNT' => array(), | |
'DISCOUNT_LIST' => array(), | |
'PRODUCT_ID' => $intProductID | |
); | |
if (!empty($minimalPrice['DISCOUNT_LIST'])) | |
{ | |
reset($minimalPrice['DISCOUNT_LIST']); | |
$arResult['DISCOUNT'] = current($minimalPrice['DISCOUNT_LIST']); | |
$arResult['DISCOUNT_LIST'] = $minimalPrice['DISCOUNT_LIST']; | |
} | |
unset($minimalPrice); | |
return $arResult; | |
} | |
public static function getAllowedPriceTypesCustom(array $userGroups){ | |
static $priceTypeCache = array(); | |
Main\Type\Collection::normalizeArrayValuesByInt($userGroups, true); | |
if (empty($userGroups)) | |
return array(); | |
$cacheKey = 'U'.implode('_', $userGroups); | |
if (!isset($priceTypeCache[$cacheKey])) | |
{ | |
$priceTypeCache[$cacheKey] = array(); | |
$priceIterator = Catalog\GroupAccessTable::getList(array( | |
'select' => array('CATALOG_GROUP_ID'), | |
'filter' => array('@GROUP_ID' => $userGroups, '=ACCESS' => Catalog\GroupAccessTable::ACCESS_BUY), | |
'order' => array('CATALOG_GROUP_ID' => 'ASC') | |
)); | |
while ($priceType = $priceIterator->fetch()) | |
{ | |
$priceTypeId = (int)$priceType['CATALOG_GROUP_ID']; | |
$priceTypeCache[$cacheKey][$priceTypeId] = $priceTypeId; | |
unset($priceTypeId); | |
} | |
unset($priceType, $priceIterator); | |
} | |
return $priceTypeCache[$cacheKey]; | |
} | |
public static $existPriceTypeDiscountsCustom = false; | |
public static function initSaleSettingsCustom() | |
{ | |
if (self::$saleIncluded === null) | |
self::$saleIncluded = Main\Loader::includeModule('sale'); | |
if (self::$saleIncluded) | |
{ | |
self::$useSaleDiscount = (string)Main\Config\Option::get('sale', 'use_sale_discount_only') == 'Y'; | |
if (self::$useSaleDiscount) | |
{ | |
//TODO: replace runtime to reference after sale 17.5.2 will be stable | |
$row = Sale\Internals\DiscountEntitiesTable::getList(array( | |
'select' => array('ID'), | |
'filter' => array( | |
'=MODULE_ID' => 'catalog', | |
'=ENTITY' => 'PRICE', | |
'=FIELD_ENTITY' => 'CATALOG_GROUP_ID', | |
'=FIELD_TABLE' => 'CATALOG_GROUP_ID', | |
'=ACTIVE_DISCOUNT.ACTIVE' => 'Y' | |
), | |
'runtime' => array( | |
new Main\Entity\ReferenceField( | |
'ACTIVE_DISCOUNT', | |
'Bitrix\Sale\Internals\Discount', | |
array('=this.DISCOUNT_ID' => 'ref.ID'), | |
array('join_type' => 'LEFT') | |
) | |
), | |
'limit' => 1, | |
))->fetch(); | |
self::$existPriceTypeDiscountsCustom = !empty($row); | |
unset($row); | |
} | |
} | |
} | |
public static function isNeedleToMinimizeCatalogGroupCustom(array $priceList) | |
{ | |
if (self::$saleIncluded === null) | |
self::initSaleSettingsCustom(); | |
if ( | |
!self::$saleIncluded || | |
!self::$useSaleDiscount || | |
count($priceList) < 2 | |
) | |
return false; | |
return self::$existPriceTypeDiscountsCustom; | |
} | |
public static function getPossibleSalePriceCustom($intProductID, array $priceData, $quantity, $siteID, array $userGroups, $coupons) | |
{ | |
$possibleSalePrice = null; | |
if (empty($priceData)) | |
return $possibleSalePrice; | |
$isCompatibilityUsed = Sale\Compatible\DiscountCompatibility::isUsed(); | |
Sale\Compatible\DiscountCompatibility::stopUsageCompatible(); | |
$freezeCoupons = (empty($coupons) && is_array($coupons)); | |
if ($freezeCoupons) | |
Sale\DiscountCouponsManager::freezeCouponStorage(); | |
/** @var \Bitrix\Sale\Basket $basket */ | |
static $basket = null, | |
/** @var \Bitrix\Sale\BasketItem $basketItem */ | |
$basketItem = null; | |
if ($basket !== null) | |
{ | |
if ($basket->getSiteId() != $siteID) | |
{ | |
$basket = null; | |
$basketItem = null; | |
} | |
} | |
if ($basket === null) | |
{ | |
$basket = Sale\Basket::create($siteID); | |
$basketItem = $basket->createItem('catalog', $intProductID); | |
} | |
$fields = array( | |
'PRODUCT_ID' => $intProductID, | |
'QUANTITY' => $quantity, | |
'LID' => $siteID, | |
'PRODUCT_PRICE_ID' => $priceData['ID'], | |
'PRICE' => $priceData['PRICE'], | |
'BASE_PRICE' => $priceData['PRICE'], | |
'DISCOUNT_PRICE' => 0, | |
'CURRENCY' => $priceData['CURRENCY'], | |
'CAN_BUY' => 'Y', | |
'DELAY' => 'N', | |
'PRICE_TYPE_ID' => (int)$priceData['CATALOG_GROUP_ID'] | |
); | |
/** @noinspection PhpInternalEntityUsedInspection */ | |
$basketItem->setFieldsNoDemand($fields); | |
$discount = Sale\Discount::buildFromBasket($basket, new Sale\Discount\Context\UserGroup($userGroups)); | |
$discount->setExecuteModuleFilter(array('all', 'catalog')); | |
$discount->calculate(); | |
$calcResults = $discount->getApplyResult(true); | |
if ($calcResults && !empty($calcResults['PRICES']['BASKET'])) | |
{ | |
$possibleSalePrice = reset($calcResults['PRICES']['BASKET']); | |
$possibleSalePrice = $possibleSalePrice['PRICE']; | |
} | |
if ($freezeCoupons) | |
Sale\DiscountCouponsManager::unFreezeCouponStorage(); | |
$discount->setExecuteModuleFilter(array('all', 'sale', 'catalog')); | |
if ($isCompatibilityUsed === true) | |
{ | |
Sale\Compatible\DiscountCompatibility::revertUsageCompatible(); | |
} | |
return $possibleSalePrice; | |
} | |
} | |
$eventManager = Bitrix\Main\EventManager::getInstance(); | |
$eventManager->addEventHandler('catalog', 'OnGetOptimalPrice', function( | |
$intProductID, | |
$quantity = 1, | |
$arUserGroups = [], | |
$renewal = "N", | |
$arPrices = [], | |
$siteID = false, | |
$arDiscountCoupons = false){ | |
//inside CCatalogProduct::GetOptimalPrice() | |
$ActionPrice = 4; | |
$prices = \CCatalogProduct::GetByIDEx($intProductID); | |
//$db_props = CIBlockElement::GetProperty(38, $intProductID, array("sort" => "asc"), Array("CODE"=>"AKTSIYA")); | |
//if($ar_props = $db_props->Fetch()){ | |
// $ar_props['VALUE_XML_ID']; // false; | |
//} | |
$price = $prices['PRICES'][$ActionPrice]['PRICE']; | |
if(isset($prices['PRICES'][$ActionPrice]) && empty($price)){ | |
if (!is_array($arUserGroups)) | |
$arUserGroups = array(); | |
if (!in_array(2, $arUserGroups)) | |
$arUserGroups[] = 2; | |
$priceTypeList = CCatalogProductCustom::getAllowedPriceTypesCustom($arUserGroups); | |
$iterator = Catalog\PriceTable::getList(array( | |
'select' => array('ID', 'CATALOG_GROUP_ID', 'PRICE', 'CURRENCY'), | |
'filter' => array( | |
'=PRODUCT_ID' => $intProductID, | |
'@CATALOG_GROUP_ID' => $priceTypeList, | |
array( | |
'LOGIC' => 'OR', | |
'<=QUANTITY_FROM' => $quantity, | |
'=QUANTITY_FROM' => null | |
), | |
array( | |
'LOGIC' => 'OR', | |
'>=QUANTITY_TO' => $quantity, | |
'=QUANTITY_TO' => null | |
) | |
), | |
'order' => array('CATALOG_GROUP_ID' => 'ASC') | |
)); | |
while ($row = $iterator->fetch()) | |
{ | |
$priceList[$row['CATALOG_GROUP_ID']] = $row; | |
} | |
unset($priceList[$ActionPrice]); | |
$priceList = array_values($priceList); | |
return CCatalogProductCustom::GetOptimalPriceCustom($intProductID, $quantity, $arUserGroups, $renewal, $priceList, $siteID, $arDiscountCoupons); | |
} | |
return true; | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<? | |
CModule::IncludeModule('catalog'); | |
CModule::IncludeModule('sale'); | |
use Bitrix\Main\Localization\Loc, | |
Bitrix\Main, | |
Bitrix\Currency, | |
Bitrix\Catalog, | |
Bitrix\Sale; | |
//2021 | |
class CCatalogProductCustom extends CCatalogProduct{ | |
public static function GetOptimalPriceCustom( | |
$intProductID, $quantity = 1, $arUserGroups = array(), | |
$renewal = "N", $priceList = array(), $siteID = false, | |
$arDiscountCoupons = false) | |
{ | |
global $APPLICATION; | |
$intProductID = (int)$intProductID; | |
if ($intProductID <= 0) | |
{ | |
$APPLICATION->ThrowException(Loc::getMessage("BT_MOD_CATALOG_PROD_ERR_PRODUCT_ID_ABSENT"), "NO_PRODUCT_ID"); | |
return false; | |
} | |
$quantity = (float)$quantity; | |
if ($quantity <= 0) | |
{ | |
$APPLICATION->ThrowException(Loc::getMessage("BT_MOD_CATALOG_PROD_ERR_QUANTITY_ABSENT"), "NO_QUANTITY"); | |
return false; | |
} | |
if (!is_array($arUserGroups) && (int)$arUserGroups.'|' == (string)$arUserGroups.'|') | |
$arUserGroups = array((int)$arUserGroups); | |
if (!is_array($arUserGroups)) | |
$arUserGroups = array(); | |
if (!in_array(2, $arUserGroups)) | |
$arUserGroups[] = 2; | |
Main\Type\Collection::normalizeArrayValuesByInt($arUserGroups); | |
$renewal = ($renewal == 'Y' ? 'Y' : 'N'); | |
if ($siteID === false) | |
$siteID = SITE_ID; | |
$resultCurrency = Catalog\Product\Price\Calculation::getCurrency(); | |
if (empty($resultCurrency)) | |
{ | |
$APPLICATION->ThrowException(Loc::getMessage("BT_MOD_CATALOG_PROD_ERR_NO_RESULT_CURRENCY")); | |
return false; | |
} | |
$intIBlockID = (int)CIBlockElement::GetIBlockByID($intProductID); | |
if ($intIBlockID <= 0) | |
{ | |
$APPLICATION->ThrowException( | |
Loc::getMessage( | |
'BT_MOD_CATALOG_PROD_ERR_ELEMENT_ID_NOT_FOUND', | |
array('#ID#' => $intProductID) | |
), | |
'NO_ELEMENT' | |
); | |
return false; | |
} | |
if (!isset($priceList) || !is_array($priceList)) | |
$priceList = array(); | |
if (empty($priceList)) | |
{ | |
$priceTypeList = self::getAllowedPriceTypesCustom($arUserGroups); | |
if (empty($priceTypeList)) | |
return false; | |
$iterator = Catalog\PriceTable::getList(array( | |
'select' => array('ID', 'CATALOG_GROUP_ID', 'PRICE', 'CURRENCY', 'PRICE_SCALE'), | |
'filter' => array( | |
'=PRODUCT_ID' => $intProductID, | |
'@CATALOG_GROUP_ID' => $priceTypeList, | |
array( | |
'LOGIC' => 'OR', | |
'<=QUANTITY_FROM' => $quantity, | |
'=QUANTITY_FROM' => null | |
), | |
array( | |
'LOGIC' => 'OR', | |
'>=QUANTITY_TO' => $quantity, | |
'=QUANTITY_TO' => null | |
) | |
), | |
'order' => array('CATALOG_GROUP_ID' => 'ASC') | |
)); | |
while ($row = $iterator->fetch()) | |
{ | |
$row['ELEMENT_IBLOCK_ID'] = $intIBlockID; | |
$priceList[] = $row; | |
} | |
unset($row, $iterator); | |
unset($priceTypeList); | |
} | |
else | |
{ | |
foreach (array_keys($priceList) as $priceIndex) | |
$priceList[$priceIndex]['ELEMENT_IBLOCK_ID'] = $intIBlockID; | |
unset($priceIndex); | |
} | |
if (empty($priceList)) | |
return false; | |
$vat = CCatalogProduct::GetVATDataByID($intProductID); | |
if (!empty($vat)) | |
{ | |
$vat['RATE'] = (float)$vat['RATE'] * 0.01; | |
} | |
else | |
{ | |
$vat = array('RATE' => 0.0, 'VAT_INCLUDED' => 'N'); | |
} | |
unset($iterator); | |
$isNeedDiscounts = Catalog\Product\Price\Calculation::isAllowedUseDiscounts(); | |
$resultWithVat = Catalog\Product\Price\Calculation::isIncludingVat(); | |
if ($isNeedDiscounts) | |
{ | |
if ($arDiscountCoupons === false) | |
$arDiscountCoupons = CCatalogDiscountCoupon::GetCoupons(); | |
} | |
// $boolDiscountVat = ('N' != COption::GetOptionString('catalog', 'discount_vat', 'Y')); | |
$boolDiscountVat = true; | |
$minimalPrice = array(); | |
if (self::$saleIncluded === null) | |
self::initSaleSettingsCustom(); | |
$isNeedleToMinimizeCatalogGroup = self::isNeedleToMinimizeCatalogGroupCustom($priceList); | |
foreach ($priceList as $priceData) | |
{ | |
$priceData['VAT_RATE'] = $vat['RATE']; | |
$priceData['VAT_INCLUDED'] = $vat['VAT_INCLUDED']; | |
$currentPrice = (float)$priceData['PRICE']; | |
if ($boolDiscountVat) | |
{ | |
if ($priceData['VAT_INCLUDED'] == 'N') | |
$currentPrice *= (1 + $priceData['VAT_RATE']); | |
} | |
else | |
{ | |
if ($priceData['VAT_INCLUDED'] == 'Y') | |
$currentPrice /= (1 + $priceData['VAT_RATE']); | |
} | |
if ($priceData['CURRENCY'] != $resultCurrency) | |
$currentPrice = CCurrencyRates::ConvertCurrency($currentPrice, $priceData['CURRENCY'], $resultCurrency); | |
$currentPrice = Catalog\Product\Price\Calculation::roundPrecision($currentPrice); | |
$result = array( | |
'BASE_PRICE' => $currentPrice, | |
'COMPARE_PRICE' => $currentPrice, | |
'PRICE' => $currentPrice, | |
'CURRENCY' => $resultCurrency, | |
'DISCOUNT_LIST' => array(), | |
'RAW_PRICE' => $priceData | |
); | |
if ($isNeedDiscounts) | |
{ | |
$arDiscounts = CCatalogDiscount::GetDiscount( | |
$intProductID, | |
$intIBlockID, | |
array($priceData['CATALOG_GROUP_ID']), | |
$arUserGroups, | |
$renewal, | |
$siteID, | |
$arDiscountCoupons | |
); | |
$discountResult = CCatalogDiscount::applyDiscountList($currentPrice, $resultCurrency, $arDiscounts); | |
unset($arDiscounts); | |
if ($discountResult === false) | |
return false; | |
$result['PRICE'] = $discountResult['PRICE']; | |
$result['COMPARE_PRICE'] = $discountResult['PRICE']; | |
$result['DISCOUNT_LIST'] = $discountResult['DISCOUNT_LIST']; | |
unset($discountResult); | |
} | |
elseif($isNeedleToMinimizeCatalogGroup) | |
{ | |
$calculateData = $priceData; | |
$calculateData['PRICE'] = $currentPrice; | |
$calculateData['CURRENCY'] = $resultCurrency; | |
$possibleSalePrice = self::getPossibleSalePriceCustom( | |
$intProductID, | |
$calculateData, | |
$quantity, | |
$siteID, | |
$arUserGroups, | |
$arDiscountCoupons | |
); | |
unset($calculateData); | |
if ($possibleSalePrice === null) | |
return false; | |
$result['COMPARE_PRICE'] = $possibleSalePrice; | |
unset($possibleSalePrice); | |
} | |
if ($boolDiscountVat) | |
{ | |
if (!$resultWithVat) | |
{ | |
$result['PRICE'] /= (1 + $priceData['VAT_RATE']); | |
$result['COMPARE_PRICE'] /= (1 + $priceData['VAT_RATE']); | |
$result['BASE_PRICE'] /= (1 + $priceData['VAT_RATE']); | |
} | |
} | |
else | |
{ | |
if ($resultWithVat) | |
{ | |
$result['PRICE'] *= (1 + $priceData['VAT_RATE']); | |
$result['COMPARE_PRICE'] *= (1 + $priceData['VAT_RATE']); | |
$result['BASE_PRICE'] *= (1 + $priceData['VAT_RATE']); | |
} | |
} | |
$result['UNROUND_PRICE'] = $result['PRICE']; | |
$result['UNROUND_BASE_PRICE'] = $result['BASE_PRICE']; | |
if (Catalog\Product\Price\Calculation::isComponentResultMode()) | |
{ | |
$result['BASE_PRICE'] = Catalog\Product\Price::roundPrice( | |
$priceData['CATALOG_GROUP_ID'], | |
$result['BASE_PRICE'], | |
$resultCurrency | |
); | |
$result['PRICE'] = Catalog\Product\Price::roundPrice( | |
$priceData['CATALOG_GROUP_ID'], | |
$result['PRICE'], | |
$resultCurrency | |
); | |
if ( | |
empty($result['DISCOUNT_LIST']) | |
|| Catalog\Product\Price\Calculation::compare($result['BASE_PRICE'], $result['PRICE'], '<=') | |
) | |
{ | |
$result['BASE_PRICE'] = $result['PRICE']; | |
} | |
$result['COMPARE_PRICE'] = $result['PRICE']; | |
} | |
if (empty($minimalPrice) || $minimalPrice['COMPARE_PRICE'] > $result['COMPARE_PRICE']) | |
{ | |
$minimalPrice = $result; | |
} | |
elseif ( | |
$minimalPrice['COMPARE_PRICE'] == $result['COMPARE_PRICE'] | |
&& $minimalPrice['RAW_PRICE']['PRICE_SCALE'] > $result['RAW_PRICE']['PRICE_SCALE'] | |
) | |
{ | |
$minimalPrice = $result; | |
} | |
unset($currentPrice, $result); | |
} | |
unset($priceData); | |
unset($vat); | |
$discountValue = ($minimalPrice['BASE_PRICE'] - $minimalPrice['PRICE']); | |
unset($minimalPrice['RAW_PRICE']['PRICE_SCALE']); | |
$arResult = array( | |
'PRICE' => $minimalPrice['RAW_PRICE'], | |
'RESULT_PRICE' => array( | |
'ID' => $minimalPrice['RAW_PRICE']['ID'], | |
'PRICE_TYPE_ID' => $minimalPrice['RAW_PRICE']['CATALOG_GROUP_ID'], | |
'BASE_PRICE' => $minimalPrice['BASE_PRICE'], | |
'DISCOUNT_PRICE' => $minimalPrice['PRICE'], | |
'CURRENCY' => $resultCurrency, | |
'DISCOUNT' => $discountValue, | |
'PERCENT' => ( | |
$minimalPrice['BASE_PRICE'] > 0 && $discountValue > 0 | |
? round((100*$discountValue)/$minimalPrice['BASE_PRICE'], 0) | |
: 0 | |
), | |
'VAT_RATE' => $minimalPrice['RAW_PRICE']['VAT_RATE'], | |
'VAT_INCLUDED' => ($resultWithVat ? 'Y' : 'N'), | |
'UNROUND_BASE_PRICE' => $minimalPrice['UNROUND_BASE_PRICE'], | |
'UNROUND_DISCOUNT_PRICE' => $minimalPrice['UNROUND_PRICE'] | |
), | |
'DISCOUNT_PRICE' => $minimalPrice['PRICE'], | |
'DISCOUNT' => array(), | |
'DISCOUNT_LIST' => array(), | |
'PRODUCT_ID' => $intProductID | |
); | |
if (!empty($minimalPrice['DISCOUNT_LIST'])) | |
{ | |
reset($minimalPrice['DISCOUNT_LIST']); | |
$arResult['DISCOUNT'] = current($minimalPrice['DISCOUNT_LIST']); | |
$arResult['DISCOUNT_LIST'] = $minimalPrice['DISCOUNT_LIST']; | |
} | |
unset($minimalPrice); | |
return $arResult; | |
} | |
public static function getAllowedPriceTypesCustom(array $userGroups){ | |
static $priceTypeCache = array(); | |
Main\Type\Collection::normalizeArrayValuesByInt($userGroups, true); | |
if (empty($userGroups)) | |
return array(); | |
$cacheKey = 'U'.implode('_', $userGroups); | |
if (!isset($priceTypeCache[$cacheKey])) | |
{ | |
$priceTypeCache[$cacheKey] = array(); | |
$priceIterator = Catalog\GroupAccessTable::getList(array( | |
'select' => array('CATALOG_GROUP_ID'), | |
'filter' => array('@GROUP_ID' => $userGroups, '=ACCESS' => Catalog\GroupAccessTable::ACCESS_BUY), | |
'order' => array('CATALOG_GROUP_ID' => 'ASC') | |
)); | |
while ($priceType = $priceIterator->fetch()) | |
{ | |
$priceTypeId = (int)$priceType['CATALOG_GROUP_ID']; | |
$priceTypeCache[$cacheKey][$priceTypeId] = $priceTypeId; | |
unset($priceTypeId); | |
} | |
unset($priceType, $priceIterator); | |
} | |
return $priceTypeCache[$cacheKey]; | |
} | |
public static $existPriceTypeDiscountsCustom = false; | |
public static function initSaleSettingsCustom() | |
{ | |
if (self::$saleIncluded === null) | |
self::$saleIncluded = Main\Loader::includeModule('sale'); | |
if (self::$saleIncluded) | |
{ | |
self::$useSaleDiscount = (string)Main\Config\Option::get('sale', 'use_sale_discount_only') == 'Y'; | |
if (self::$useSaleDiscount) | |
{ | |
//TODO: replace runtime to reference after sale 17.5.2 will be stable | |
$row = Sale\Internals\DiscountEntitiesTable::getList(array( | |
'select' => array('ID'), | |
'filter' => array( | |
'=MODULE_ID' => 'catalog', | |
'=ENTITY' => 'PRICE', | |
'=FIELD_ENTITY' => 'CATALOG_GROUP_ID', | |
'=FIELD_TABLE' => 'CATALOG_GROUP_ID', | |
'=ACTIVE_DISCOUNT.ACTIVE' => 'Y' | |
), | |
'runtime' => array( | |
new Main\Entity\ReferenceField( | |
'ACTIVE_DISCOUNT', | |
'Bitrix\Sale\Internals\Discount', | |
array('=this.DISCOUNT_ID' => 'ref.ID'), | |
array('join_type' => 'LEFT') | |
) | |
), | |
'limit' => 1, | |
))->fetch(); | |
self::$existPriceTypeDiscountsCustom = !empty($row); | |
unset($row); | |
} | |
} | |
} | |
public static function isNeedleToMinimizeCatalogGroupCustom(array $priceList) | |
{ | |
if (self::$saleIncluded === null) | |
self::initSaleSettingsCustom(); | |
if ( | |
!self::$saleIncluded || | |
!self::$useSaleDiscount || | |
count($priceList) < 2 | |
) | |
return false; | |
return self::$existPriceTypeDiscountsCustom; | |
} | |
public static function getPossibleSalePriceCustom($intProductID, array $priceData, $quantity, $siteID, array $userGroups, $coupons) | |
{ | |
$possibleSalePrice = null; | |
$registry = Sale\Registry::getInstance(Sale\Registry::REGISTRY_TYPE_ORDER); | |
if (empty($priceData)) | |
return $possibleSalePrice; | |
$isCompatibilityUsed = Sale\Compatible\DiscountCompatibility::isUsed(); | |
Sale\Compatible\DiscountCompatibility::stopUsageCompatible(); | |
$freezeCoupons = (empty($coupons) && is_array($coupons)); | |
if ($freezeCoupons) | |
Sale\DiscountCouponsManager::freezeCouponStorage(); | |
/** @var \Bitrix\Sale\Basket $basket */ | |
static $basket = null, | |
/** @var \Bitrix\Sale\BasketItem $basketItem */ | |
$basketItem = null; | |
if ($basket !== null) | |
{ | |
if ($basket->getSiteId() != $siteID) | |
{ | |
$basket = null; | |
$basketItem = null; | |
} | |
} | |
if ($basket === null) | |
{ | |
/** @var Sale\Basket $basketClassName */ | |
$basketClassName = $registry->getBasketClassName(); | |
$basket = $basketClassName::create($siteID); | |
$basketItem = $basket->createItem('catalog', $intProductID); | |
} | |
$fields = array( | |
'PRODUCT_ID' => $intProductID, | |
'QUANTITY' => $quantity, | |
'LID' => $siteID, | |
'PRODUCT_PRICE_ID' => $priceData['ID'], | |
'PRICE' => $priceData['PRICE'], | |
'BASE_PRICE' => $priceData['PRICE'], | |
'DISCOUNT_PRICE' => 0, | |
'CURRENCY' => $priceData['CURRENCY'], | |
'CAN_BUY' => 'Y', | |
'DELAY' => 'N', | |
'PRICE_TYPE_ID' => (int)$priceData['CATALOG_GROUP_ID'] | |
); | |
/** @noinspection PhpInternalEntityUsedInspection */ | |
$basketItem->setFieldsNoDemand($fields); | |
$discount = Sale\Discount::buildFromBasket($basket, new Sale\Discount\Context\UserGroup($userGroups)); | |
$discount->setExecuteModuleFilter(array('all', 'catalog')); | |
$discount->calculate(); | |
$calcResults = $discount->getApplyResult(true); | |
if ($calcResults && !empty($calcResults['PRICES']['BASKET'])) | |
{ | |
$possibleSalePrice = reset($calcResults['PRICES']['BASKET']); | |
$possibleSalePrice = $possibleSalePrice['PRICE']; | |
} | |
if ($freezeCoupons) | |
Sale\DiscountCouponsManager::unFreezeCouponStorage(); | |
$discount->setExecuteModuleFilter(array('all', 'sale', 'catalog')); | |
if ($isCompatibilityUsed === true) | |
{ | |
Sale\Compatible\DiscountCompatibility::revertUsageCompatible(); | |
} | |
return $possibleSalePrice; | |
} | |
} | |
$eventManager = Bitrix\Main\EventManager::getInstance(); | |
$eventManager->addEventHandler('catalog', 'OnGetOptimalPrice', function( | |
$intProductID, | |
$quantity = 1, | |
$arUserGroups = [], | |
$renewal = "N", | |
$arPrices = [], | |
$siteID = false, | |
$arDiscountCoupons = false){ | |
/* | |
global $APPLICATION; | |
$dir = $APPLICATION->GetCurDir(); | |
if(strpos($dir, '/bitrix/admin/') !== false){ | |
return true; | |
} | |
if(strpos($dir, '/bitrix/gadgets/') !== false){ | |
return true; | |
} | |
if(strpos($dir, '/upload/') !== false){ | |
return true; | |
} | |
if(defined('ADMIN_SECTION')){ | |
return true; | |
} | |
*/ | |
global $USER; | |
if(!$USER->IsAdmin()){ | |
return true; | |
} | |
//pre1('OnGetOptimalPrice'); | |
if(!$siteID){ | |
if(!defined('ADMIN_SECTION')){ | |
$siteID = SITE_ID; | |
} | |
} | |
$arAllowPrices = array(); | |
if('s2' == $siteID){ | |
$arAllowPrices = array(10,11); | |
}elseif('s3' == $siteID){ | |
$arAllowPrices = array(9); | |
} | |
//pre1($arAllowPrices); | |
//pre1($arUserGroups); | |
if (!is_array($arUserGroups)) | |
$arUserGroups = array(); | |
if (!in_array(2, $arUserGroups)) | |
$arUserGroups[] = 2; | |
$priceTypeList = CCatalogProductCustom::getAllowedPriceTypesCustom($arUserGroups); | |
$iterator = Catalog\PriceTable::getList(array( | |
'select' => array('ID', 'CATALOG_GROUP_ID', 'PRICE', 'CURRENCY'), | |
'filter' => array( | |
'=PRODUCT_ID' => $intProductID, | |
'@CATALOG_GROUP_ID' => $priceTypeList, | |
array( | |
'LOGIC' => 'OR', | |
'<=QUANTITY_FROM' => $quantity, | |
'=QUANTITY_FROM' => null | |
), | |
array( | |
'LOGIC' => 'OR', | |
'>=QUANTITY_TO' => $quantity, | |
'=QUANTITY_TO' => null | |
) | |
), | |
'order' => array('CATALOG_GROUP_ID' => 'ASC') | |
)); | |
while ($row = $iterator->fetch()) | |
{ | |
$priceList[$row['CATALOG_GROUP_ID']] = $row; | |
} | |
//pre1($priceList); | |
//pre1($arAllowPrices); a | |
if(count($arAllowPrices)>0){ | |
foreach($priceList as $row){ | |
if(!in_array($row['CATALOG_GROUP_ID'],$arAllowPrices)){ | |
unset($priceList[$row['CATALOG_GROUP_ID']]); | |
} | |
} | |
} | |
$priceList = array_values($priceList); | |
//pre1($priceList); | |
return CCatalogProductCustom::GetOptimalPriceCustom($intProductID, $quantity, $arUserGroups, $renewal, $priceList, $siteID, $arDiscountCoupons); | |
// if return true product added to basket | |
//if return false product NOT added to basket | |
return true; | |
}); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment