protected function calculatePriceBlock(array $product, array $priceBlock, $ratio, $defaultBlock = false)
{
if (empty($product) || empty($priceBlock))
return null;
$enableCompatible = $defaultBlock && $this->isEnableCompatible();
if ($enableCompatible && !$this->arParams['USE_PRICE_COUNT'])
$this->fillCompatibleRawPriceFields($product['ID'], $priceBlock);
$userGroups = $this->getUserGroups();
$baseCurrency = CurrencyCurrencyManager::getBaseCurrency();
/** @var null|array $minimalPrice */
$minimalPrice = null;
/** @var null|array $minimalBuyerPrice */
$minimalBuyerPrice = null;
$fullPrices = array();
$currencyConvert = $this->arParams['CONVERT_CURRENCY'] === 'Y';
$resultCurrency = ($currencyConvert ? $this->storage['CONVERT_CURRENCY']['CURRENCY_ID'] : null);
$vatRate = (float)$product['PRODUCT']['VAT_RATE'];
$percentVat = $vatRate * 0.01;
$percentPriceWithVat = 1 + $percentVat;
$vatInclude = $product['PRODUCT']['VAT_INCLUDED'] === 'Y';
$oldPrices = array();
$oldMinPrice = false;
$oldMatrix = false;
if ($enableCompatible && $this->arParams['USE_PRICE_COUNT'])
{
$oldMatrix = $this->getCompatibleFieldValue($product['ID'], 'PRICE_MATRIX');
if (empty($oldMatrix))
{
$oldMatrix = $this->getEmptyPriceMatrix();
$oldMatrix['AVAILABLE'] = $product['PRODUCT']['AVAILABLE'];
}
}
foreach ($priceBlock as $rawPrice)
{
$priceType = (int)$rawPrice['CATALOG_GROUP_ID'];
$price = (float)$rawPrice['PRICE'];
if (!$vatInclude)
$price *= $percentPriceWithVat;
$currency = $rawPrice['CURRENCY'];
$changeCurrency = $currencyConvert && $currency !== $resultCurrency;
if ($changeCurrency)
{
$price = CCurrencyRates::ConvertCurrency($price, $currency, $resultCurrency);
$currency = $resultCurrency;
}
$discounts = array();
if (CIBlockPriceTools::isEnabledCalculationDiscounts())
{
CCatalogDiscountSave::Disable();
$discounts = CCatalogDiscount::GetDiscount(
$product['ID'],
$product['IBLOCK_ID'],
array($priceType),
$userGroups,
'N',
$this->getSiteId(),
array()
);
CCatalogDiscountSave::Enable();
}
$discountPrice = CCatalogProduct::CountPriceWithDiscount(
$price,
$currency,
$discounts
);
if ($discountPrice !== false)
{
$priceWithVat = array(
'UNROUND_BASE_PRICE' => $price,
'UNROUND_PRICE' => $discountPrice,
'BASE_PRICE' => CatalogProductPrice::roundPrice(
$priceType,
$price,
$currency
),
'PRICE' => CatalogProductPrice::roundPrice(
$priceType,
$discountPrice,
$currency
)
);
$price /= $percentPriceWithVat;
$discountPrice /= $percentPriceWithVat;
$priceWithoutVat = array(
'UNROUND_BASE_PRICE' => $price,
'UNROUND_PRICE' => $discountPrice,
'BASE_PRICE' => CatalogProductPrice::roundPrice(
$priceType,
$price,
$currency
),
'PRICE' => CatalogProductPrice::roundPrice(
$priceType,
$discountPrice,
$currency
)
);
if ($this->arParams['PRICE_VAT_INCLUDE'])
$priceRow = $priceWithVat;
else
$priceRow = $priceWithoutVat;
$priceRow['ID'] = $rawPrice['ID'];
$priceRow['PRICE_TYPE_ID'] = $rawPrice['CATALOG_GROUP_ID'];
$priceRow['CURRENCY'] = $currency;
if (
empty($discounts)
|| ($priceRow['BASE_PRICE'] <= $priceRow['PRICE'])
)
{
$priceRow['BASE_PRICE'] = $priceRow['PRICE'];
$priceRow['DISCOUNT'] = 0;
$priceRow['PERCENT'] = 0;
}
else
{
$priceRow['DISCOUNT'] = $priceRow['BASE_PRICE'] - $priceRow['PRICE'];
$priceRow['PERCENT'] = roundEx(100*$priceRow['DISCOUNT']/$priceRow['BASE_PRICE'], 0);
}
if (isset($this->arParams['PRICE_VAT_SHOW_VALUE']) && $this->arParams['PRICE_VAT_SHOW_VALUE'])
$priceRow['VAT'] = ($vatRate > 0 ? $priceWithVat['PRICE'] - $priceWithoutVat['PRICE'] : 0);
if ($this->arParams['FILL_ITEM_ALL_PRICES'])
$fullPrices[$priceType] = $priceRow;
$priceRow['QUANTITY_FROM'] = $rawPrice['QUANTITY_FROM'];
$priceRow['QUANTITY_TO'] = $rawPrice['QUANTITY_TO'];
$priceRow['QUANTITY_HASH'] = $this->getQuantityRangeHash($rawPrice);
$priceRow['MEASURE_RATIO_ID'] = $rawPrice['MEASURE_RATIO_ID'] ?? null;
$priceRow['PRICE_SCALE'] = CCurrencyRates::ConvertCurrency(
$priceRow['PRICE'],
$priceRow['CURRENCY'],
$baseCurrency
);
$priceRow['BASE_PRICE_SCALE'] = $rawPrice['PRICE_SCALE'];
if (
$minimalPrice === null
|| $minimalPrice['PRICE_SCALE'] > $priceRow['PRICE_SCALE']
)
{
$minimalPrice = $priceRow;
}
elseif (
$minimalPrice['PRICE_SCALE'] == $priceRow['PRICE_SCALE']
&& $minimalPrice['BASE_PRICE_SCALE'] > $priceRow['BASE_PRICE_SCALE']
)
{
$minimalPrice = $priceRow;
}
if (isset($this->storage['PRICES_CAN_BUY'][$priceRow['PRICE_TYPE_ID']]))
{
if (
$minimalBuyerPrice === null
|| $minimalBuyerPrice['PRICE_SCALE'] > $priceRow['PRICE_SCALE']
)
{
$minimalBuyerPrice = $priceRow;
}
elseif (
$minimalBuyerPrice['PRICE_SCALE'] == $priceRow['PRICE_SCALE']
&& $minimalBuyerPrice['BASE_PRICE_SCALE'] > $priceRow['BASE_PRICE_SCALE']
)
{
$minimalBuyerPrice = $priceRow;
}
}
if ($enableCompatible)
{
if ($this->arParams['USE_PRICE_COUNT'])
{
$rowIndex = $this->getQuantityRangeHash($rawPrice);
$oldMatrix['ROWS'][$rowIndex] = array(
'QUANTITY_FROM' => (float)$rawPrice['QUANTITY_FROM'],
'QUANTITY_TO' => (float)$rawPrice['QUANTITY_TO']
);
if (!isset($oldMatrix['MATRIX'][$priceType]))
{
$oldMatrix['MATRIX'][$priceType] = array();
$oldMatrix['COLS'][$priceType] = $this->storage['PRICE_TYPES'][$priceType];
}
$oldMatrix['MATRIX'][$priceType][$rowIndex] = array(
'ID' => $priceRow['ID'],
'PRICE' => $priceRow['BASE_PRICE'],
'DISCOUNT_PRICE' => $priceRow['PRICE'],
'UNROUND_DISCOUNT_PRICE' => $priceRow['UNROUND_PRICE'],
'CURRENCY' => $priceRow['CURRENCY'],
'VAT_RATE' => $percentVat
);
if ($changeCurrency)
{
$oldMatrix['MATRIX'][$priceType][$rowIndex]['ORIG_CURRENCY'] = $rawPrice['CURRENCY'];
$oldMatrix['MATRIX'][$priceType][$rowIndex]['ORIG_PRICE'] = CCurrencyRates::ConvertCurrency(
$priceRow['BASE_PRICE'],
$priceRow['CURRENCY'],
$rawPrice['CURRENCY']
);
$oldMatrix['MATRIX'][$priceType][$rowIndex]['ORIG_DISCOUNT_PRICE'] = CCurrencyRates::ConvertCurrency(
$priceRow['PRICE'],
$priceRow['CURRENCY'],
$rawPrice['CURRENCY']
);
$oldMatrix['MATRIX'][$priceType][$rowIndex]['ORIG_VAT_RATE'] = $percentVat; // crazy key, but above all the compatibility
}
}
else
{
$priceCode = $this->storage['PRICES_MAP'][$priceType];
$oldPriceRow = array(
'PRICE_ID' => $priceRow['PRICE_TYPE_ID'],
'ID' => $priceRow['ID'],
'CAN_ACCESS' => ($this->storage['PRICES'][$priceCode]['CAN_VIEW'] ? 'Y' : 'N'),
'CAN_BUY' => ($this->storage['PRICES'][$priceCode]['CAN_BUY'] ? 'Y' : 'N'),
'MIN_PRICE' => 'N',
'CURRENCY' => $priceRow['CURRENCY'],
'VALUE_VAT' => $priceWithVat['UNROUND_BASE_PRICE'],
'VALUE_NOVAT' => $priceWithoutVat['UNROUND_BASE_PRICE'],
'DISCOUNT_VALUE_VAT' => $priceWithVat['UNROUND_PRICE'],
'DISCOUNT_VALUE_NOVAT' => $priceWithoutVat['UNROUND_PRICE'],
'ROUND_VALUE_VAT' => $priceWithVat['PRICE'],
'ROUND_VALUE_NOVAT' => $priceWithoutVat['PRICE'],
'VALUE' => $priceRow['BASE_PRICE'],
'UNROUND_DISCOUNT_VALUE' => $priceRow['UNROUND_PRICE'],
'DISCOUNT_VALUE' => $priceRow['PRICE'],
'DISCOUNT_DIFF' => $priceRow['DISCOUNT'],
'DISCOUNT_DIFF_PERCENT' => $priceRow['PERCENT']
);
$oldPriceRow['VATRATE_VALUE'] = $oldPriceRow['VALUE_VAT'] - $oldPriceRow['VALUE_NOVAT'];
$oldPriceRow['DISCOUNT_VATRATE_VALUE'] = $oldPriceRow['DISCOUNT_VALUE_VAT'] - $oldPriceRow['DISCOUNT_VALUE_NOVAT'];
$oldPriceRow['ROUND_VATRATE_VALUE'] = $oldPriceRow['ROUND_VALUE_VAT'] - $oldPriceRow['ROUND_VALUE_NOVAT'];
if ($changeCurrency)
$oldPriceRow['ORIG_CURRENCY'] = $rawPrice['CURRENCY'];
$oldPrices[$priceCode] = $oldPriceRow;
unset($oldPriceRow);
}
}
}
unset($discounts);
unset($priceType);
}
unset($price);
$minimalPriceId = null;
if (is_array($minimalBuyerPrice))
$minimalPrice = $minimalBuyerPrice;
if (is_array($minimalPrice))
{
unset($minimalPrice['PRICE_SCALE']);
unset($minimalPrice['BASE_PRICE_SCALE']);
$minimalPriceId = $minimalPrice['PRICE_TYPE_ID'];
$prepareFields = array(
'BASE_PRICE', 'PRICE', 'DISCOUNT'
);
if (isset($this->arParams['PRICE_VAT_SHOW_VALUE']) && $this->arParams['PRICE_VAT_SHOW_VALUE'])
$prepareFields[] = 'VAT';
foreach ($prepareFields as $fieldName)
{
$minimalPrice['PRINT_'.$fieldName] = CCurrencyLang::CurrencyFormat(
$minimalPrice[$fieldName],
$minimalPrice['CURRENCY'],
true
);
$minimalPrice['RATIO_'.$fieldName] = $minimalPrice[$fieldName]*$ratio;
$minimalPrice['PRINT_RATIO_'.$fieldName] = CCurrencyLang::CurrencyFormat(
$minimalPrice['RATIO_'.$fieldName],
$minimalPrice['CURRENCY'],
true
);
}
unset($fieldName);
if ($this->arParams['FILL_ITEM_ALL_PRICES'])
{
foreach (array_keys($fullPrices) as $priceType)
{
foreach ($prepareFields as $fieldName)
{
$fullPrices[$priceType]['PRINT_'.$fieldName] = CCurrencyLang::CurrencyFormat(
$fullPrices[$priceType][$fieldName],
$fullPrices[$priceType]['CURRENCY'],
true
);
$fullPrices[$priceType]['RATIO_'.$fieldName] = $fullPrices[$priceType][$fieldName]*$ratio;
$fullPrices[$priceType]['PRINT_RATIO_'.$fieldName] = CCurrencyLang::CurrencyFormat(
$minimalPrice['RATIO_'.$fieldName],
$minimalPrice['CURRENCY'],
true
);
}
unset($fieldName);
}
unset($priceType);
}
unset($prepareFields);
}
if ($enableCompatible)
{
if ($this->arParams['USE_PRICE_COUNT'])
{
$oldMatrix['CAN_BUY'] = array_values($this->storage['PRICES_CAN_BUY']);
$this->oldData[$product['ID']]['PRICE_MATRIX'] = $oldMatrix;
}
else
{
$convertFields = array(
'VALUE_NOVAT', 'VALUE_VAT', 'VATRATE_VALUE',
'DISCOUNT_VALUE_NOVAT', 'DISCOUNT_VALUE_VAT', 'DISCOUNT_VATRATE_VALUE'
);
$prepareFields = array(
'VALUE_NOVAT', 'VALUE_VAT', 'VATRATE_VALUE',
'DISCOUNT_VALUE_NOVAT', 'DISCOUNT_VALUE_VAT', 'DISCOUNT_VATRATE_VALUE',
'VALUE', 'DISCOUNT_VALUE', 'DISCOUNT_DIFF'
);
if (!empty($oldPrices))
{
foreach (array_keys($oldPrices) as $index)
{
foreach ($prepareFields as $fieldName)
$oldPrices[$index]['PRINT_'.$fieldName] = CCurrencyLang::CurrencyFormat(
$oldPrices[$index][$fieldName],
$oldPrices[$index]['CURRENCY'],
true
);
unset($fieldName);
if (isset($oldPrices[$index]['ORIG_CURRENCY']))
{
foreach ($convertFields as $fieldName)
$oldPrices[$index]['ORIG_' . $fieldName] = CCurrencyRates::ConvertCurrency(
$oldPrices[$index][$fieldName],
$oldPrices[$index]['CURRENCY'],
$oldPrices[$index]['ORIG_CURRENCY']
);
unset($fieldName);
}
if ($oldPrices[$index]['PRICE_ID'] === $minimalPriceId)
{
$oldPrices[$index]['MIN_PRICE'] = 'Y';
$oldMinPrice = $oldPrices[$index];
}
}
unset($index);
}
unset($prepareFields);
$this->oldData[$product['ID']]['PRICES'] = $oldPrices;
$this->oldData[$product['ID']]['MIN_PRICE'] = $oldMinPrice;
}
}
unset($oldMatrix, $oldMinPrice, $oldPrices);
if (!$this->arParams['FILL_ITEM_ALL_PRICES'])
return $minimalPrice;
return array(
'MINIMAL_PRICE' => $minimalPrice,
'ALL_PRICES' => array(
'QUANTITY_FROM' => $minimalPrice['QUANTITY_FROM'],
'QUANTITY_TO' => $minimalPrice['QUANTITY_TO'],
'QUANTITY_HASH' => $minimalPrice['QUANTITY_HASH'],
'MEASURE_RATIO_ID' => $minimalPrice['MEASURE_RATIO_ID'],
'PRICES' => $fullPrices
)
);
}