• Модуль: sale
  • Путь к файлу: ~/bitrix/modules/sale/lib/discount/actions.php
  • Класс: BitrixSaleDiscountActions
  • Вызов: Actions::applyCumulativeToBasket
static function applyCumulativeToBasket(array &$order, array $ranges, array $configuration = array(), $filter = null)
{
	static::increaseApplyCounter();

	MainTypeCollection::sortByColumn($ranges, 'sum');

	$sumConfiguration = $configuration['sum']?: array();
	$applyIfMoreProfitable = $configuration['apply_if_more_profitable'] === 'Y';

	if (static::checkUseMode(array(self::MODE_MANUAL, self::MODE_MIXED)))
	{
		$actionStoredData = self::getActionStoredData();
		$cumulativeOrderUserValue = $actionStoredData['cumulative_value'];
	}
	else
	{
		$cumulativeCalculator = new CumulativeCalculator((int)$order['USER_ID'], $order['SITE_ID']);
		$cumulativeCalculator->setSumConfiguration(
			array(
				'type_sum_period' => $sumConfiguration['type_sum_period'],
				'sum_period_data' => array(
					'order_start' => $sumConfiguration['sum_period_data']['discount_sum_order_start'],
					'order_end' => $sumConfiguration['sum_period_data']['discount_sum_order_end'],
					'period_value' => $sumConfiguration['sum_period_data']['discount_sum_period_value'],
					'period_type' => $sumConfiguration['sum_period_data']['discount_sum_period_type'],
				),
			)
		);
		$cumulativeOrderUserValue = $cumulativeCalculator->calculate();
	}

	$rangeToApply = null;
	foreach ($ranges as $range)
	{
		if ($cumulativeOrderUserValue >= $range['sum'])
		{
			$rangeToApply = $range;
		}
	}

	if (!$rangeToApply)
	{
		return;
	}

	$action = array(
		'VALUE' => -$rangeToApply['value'],
		'UNIT' => $rangeToApply['type'],
	);

	if (!isset($action['VALUE']) || !isset($action['UNIT']))
		return;

	$orderCurrency = static::getCurrency();
	$value = (float)$action['VALUE'];
	$limitValue = (int)$action['LIMIT_VALUE'];
	$unit = (string)$action['UNIT'];
	$currency = (isset($action['CURRENCY']) ? $action['CURRENCY'] : $orderCurrency);
	$maxBound = false;
	if ($unit == self::VALUE_TYPE_FIX && $value < 0)
		$maxBound = (isset($action['MAX_BOUND']) && $action['MAX_BOUND'] == 'Y');
	$valueAction = Formatter::VALUE_ACTION_CUMULATIVE;

	$actionDescription = array(
		'ACTION_TYPE' => Formatter::TYPE_VALUE,
		'VALUE' => abs($value),
		'VALUE_ACTION' => $valueAction
	);
	switch ($unit)
	{
		case self::VALUE_TYPE_PERCENT:
			$actionDescription['VALUE_TYPE'] = Formatter::VALUE_TYPE_PERCENT;
			break;
		case self::VALUE_TYPE_FIX:
			$actionDescription['VALUE_TYPE'] = Formatter::VALUE_TYPE_CURRENCY;
			$actionDescription['VALUE_UNIT'] = $currency;
			if ($maxBound)
				$actionDescription['ACTION_TYPE'] = Formatter::TYPE_MAX_BOUND;
			break;
		default:
			return;
	}

	if ($unit == self::VALUE_TYPE_FIX && $currency != $orderCurrency)
	{
		$value = CCurrencyRates::ConvertCurrency($value, $currency, $orderCurrency);
	}

	$value = static::roundZeroValue($value);
	if ($value == 0)
	{
		return;
	}

	if(!empty($limitValue))
	{
		$actionDescription['ACTION_TYPE'] = Formatter::TYPE_LIMIT_VALUE;
		$actionDescription['LIMIT_TYPE'] = Formatter::LIMIT_MAX;
		$actionDescription['LIMIT_UNIT'] = $orderCurrency;
		$actionDescription['LIMIT_VALUE'] = $limitValue;
	}

	static::setActionDescription(self::RESULT_ENTITY_BASKET, $actionDescription);

	if (empty($order['BASKET_ITEMS']) || !is_array($order['BASKET_ITEMS']))
		return;

	static::enableBasketFilter();

	if ($applyIfMoreProfitable)
	{
		if ($filter === null)
		{
			$filter = function(){
				return true;
			};
		}
		$filter = self::wrapFilterToFindMoreProfitableForCumulative($filter, $unit, $value, $limitValue, $maxBound);
	}

	$filteredBasket = static::getBasketForApply($order['BASKET_ITEMS'], $filter, $action);
	if (empty($filteredBasket))
		return;


	$applyBasket = array_filter($filteredBasket, 'BitrixSaleDiscountActions::filterBasketForAction');
	unset($filteredBasket);
	if (empty($applyBasket))
		return;

	foreach ($applyBasket as $basketCode => $basketRow)
	{
		if ($applyIfMoreProfitable)
		{
			$basketRow['PRICE'] = $basketRow['BASE_PRICE'];
			$basketRow['DISCOUNT_PRICE'] = 0;
		}

		list($calculateValue, $result) = self::calculateDiscountPrice(
			$value,
			$unit,
			$basketRow,
			$limitValue,
			$maxBound
		);
		if ($result >= 0)
		{
			self::fillDiscountPrice($basketRow, $result, -$calculateValue);

			$order['BASKET_ITEMS'][$basketCode] = $basketRow;

			$rowActionDescription = $actionDescription;
			$rowActionDescription['BASKET_CODE'] = $basketCode;
			$rowActionDescription['RESULT_VALUE'] = abs($calculateValue);
			$rowActionDescription['RESULT_UNIT'] = $orderCurrency;

			if(!empty($limitValue))
			{
				$rowActionDescription['ACTION_TYPE'] = Formatter::TYPE_LIMIT_VALUE;
				$rowActionDescription['LIMIT_TYPE'] = Formatter::LIMIT_MAX;
				$rowActionDescription['LIMIT_UNIT'] = $orderCurrency;
				$rowActionDescription['LIMIT_VALUE'] = $limitValue;
			}

			if ($applyIfMoreProfitable)
			{
				//TODO: remove this hack
				//revert apply on affected basket items
				$rowActionDescription['REVERT_APPLY'] = true;
			}

			static::setActionResult(self::RESULT_ENTITY_BASKET, $rowActionDescription);
			unset($rowActionDescription);
		}
		unset($result);
	}
	unset($basketCode, $basketRow);

	if (self::getUseMode() == self::MODE_CALCULATE)
	{
		self::setActionStoredData(
			array(
				'cumulative_value' => $cumulativeOrderUserValue,
			)
		);
	}
}