/** * Create sale action. * * @param array &$discount Discount data. * @param array $params Manager parameters. * @return void */ protected static function createSaleAction(&$discount, $params) { $data = array('TYPE' => $discount['VALUE_TYPE'], 'VALUE' => $discount['VALUE'], 'CURRENCY' => $discount['CURRENCY'], 'USE_BASE_PRICE' => $params['USE_BASE_PRICE']); if ($discount['TYPE'] == Catalog\DiscountTable::VALUE_TYPE_PERCENT) { $data['MAX_VALUE'] = $discount['MAX_VALUE']; } $action = '\\Bitrix\\Catalog\\Discount\\DiscountManager::applyDiscount(' . $params['BASKET_ITEM'] . ', ' . var_export($data, true) . ');'; $discount['APPLICATION'] = 'function (&' . $params['BASKET_ITEM'] . '){' . $action . '};'; $discount['ACTIONS'] = $data; if (Loader::includeModule('sale')) { $type = ''; $descr = array('VALUE_ACTION' => $discount['TYPE'] == Catalog\DiscountTable::TYPE_DISCOUNT_SAVE ? Sale\OrderDiscountManager::DESCR_VALUE_ACTION_ACCUMULATE : Sale\OrderDiscountManager::DESCR_VALUE_ACTION_DISCOUNT, 'VALUE' => $discount['VALUE']); switch ($discount['VALUE_TYPE']) { case Catalog\DiscountTable::VALUE_TYPE_PERCENT: $type = $discount['MAX_VALUE'] > 0 ? Sale\OrderDiscountManager::DESCR_TYPE_LIMIT_VALUE : Sale\OrderDiscountManager::DESCR_TYPE_VALUE; $descr['VALUE_TYPE'] = Sale\OrderDiscountManager::DESCR_VALUE_TYPE_PERCENT; if ($discount['MAX_VALUE'] > 0) { $descr['LIMIT_TYPE'] = Sale\OrderDiscountManager::DESCR_LIMIT_MAX; $descr['LIMIT_UNIT'] = $discount['CURRENCY']; $descr['LIMIT_VALUE'] = $discount['MAX_VALUE']; } break; case Catalog\DiscountTable::VALUE_TYPE_FIX: $type = Sale\OrderDiscountManager::DESCR_TYPE_VALUE; $descr['VALUE_TYPE'] = Sale\OrderDiscountManager::DESCR_VALUE_TYPE_CURRENCY; $descr['VALUE_UNIT'] = $discount['CURRENCY']; break; case Catalog\DiscountTable::VALUE_TYPE_SALE: $type = Sale\OrderDiscountManager::DESCR_TYPE_FIXED; $descr['VALUE_UNIT'] = $discount['CURRENCY']; break; } $descrResult = Sale\OrderDiscountManager::prepareDiscountDescription($type, $descr); if ($descrResult->isSuccess()) { $discount['ACTIONS_DESCR'] = array('BASKET' => array(0 => $descrResult->getData())); } unset($descrResult, $descr, $type); } unset($action, $data); }
/** * Apply discount to basket. * * @param array &$order Order data. * @param callable $func Filter function. * @param float $value Discount value. * @param string $unit Value unit. * @return void */ public static function ApplyBasketDiscount(&$order, $func, $value, $unit) { if (empty($order['BASKET_ITEMS']) || !is_array($order['BASKET_ITEMS'])) { return; } $manualMode = self::isManualMode($order); if (self::$getPercentFromBasePrice === null) { if ($manualMode) { self::$getPercentFromBasePrice = isset($order['USE_BASE_PRICE']) && $order['USE_BASE_PRICE'] == 'Y'; } else { self::$getPercentFromBasePrice = (string) Option::get('sale', 'get_discount_percent_from_base_price') == 'Y'; } } if ($manualMode) { $discountBasket = array_filter($order['BASKET_ITEMS'], 'CSaleDiscountActionApply::filterApplied'); } else { $discountBasket = is_callable($func) ? array_filter($order['BASKET_ITEMS'], $func) : $order['BASKET_ITEMS']; } if (empty($discountBasket)) { return; } $allBasket = count($order['BASKET_ITEMS']) == count($discountBasket); $clearBasket = array_filter($discountBasket, 'CSaleDiscountActionApply::ClearBasket'); if (empty($clearBasket)) { return; } unset($discountBasket); $unit = (string) $unit; $value = (double) $value; $type = Sale\OrderDiscountManager::DESCR_TYPE_VALUE; $discountDescr = array('VALUE' => abs($value), 'VALUE_ACTION' => $value < 0 ? Sale\OrderDiscountManager::DESCR_VALUE_ACTION_DISCOUNT : Sale\OrderDiscountManager::DESCR_VALUE_ACTION_EXTRA); switch ($unit) { case self::VALUE_TYPE_SUMM: $discountDescr['VALUE_TYPE'] = $allBasket ? Sale\OrderDiscountManager::DESCR_VALUE_TYPE_SUMM_BASKET : Sale\OrderDiscountManager::DESCR_VALUE_TYPE_SUMM; if (isset($order['CURRENCY'])) { $discountDescr['VALUE_UNIT'] = $order['CURRENCY']; } break; case self::VALUE_TYPE_PERCENT: $discountDescr['VALUE_TYPE'] = Sale\OrderDiscountManager::DESCR_VALUE_TYPE_PERCENT; break; case self::VALUE_TYPE_FIX: default: $discountDescr['VALUE_TYPE'] = Sale\OrderDiscountManager::DESCR_VALUE_TYPE_CURRENCY; if (isset($order['CURRENCY'])) { $discountDescr['VALUE_UNIT'] = $order['CURRENCY']; } break; } unset($allBasket); if ($unit == self::VALUE_TYPE_SUMM) { $dblSumm = 0.0; if (self::$getPercentFromBasePrice) { foreach ($clearBasket as &$arOneRow) { if (!isset($arOneRow['DISCOUNT_PRICE'])) { $arOneRow['DISCOUNT_PRICE'] = 0; } $dblSumm += (double) (isset($arOneRow['BASE_PRICE']) ? $arOneRow['BASE_PRICE'] : $arOneRow['PRICE'] + $arOneRow['DISCOUNT_PRICE']) * (double) $arOneRow['QUANTITY']; } unset($arOneRow); } else { foreach ($clearBasket as &$arOneRow) { $dblSumm += (double) $arOneRow['PRICE'] * (double) $arOneRow['QUANTITY']; } unset($arOneRow); } $value = $dblSumm > 0 ? $value * 100 / $dblSumm : 0.0; $unit = self::VALUE_TYPE_PERCENT; } if ($value != 0) { if (!$manualMode) { $prepareResult = Sale\OrderDiscountManager::prepareDiscountDescription($type, $discountDescr); if ($prepareResult->isSuccess()) { if (!isset($order['DISCOUNT_DESCR'])) { $order['DISCOUNT_DESCR'] = array(); } if (!isset($order['DISCOUNT_DESCR']['BASKET'])) { $order['DISCOUNT_DESCR']['BASKET'] = array(); } $order['DISCOUNT_DESCR']['BASKET'][] = $prepareResult->getData(); } unset($prepareResult); } $applyResultList = array(); foreach ($clearBasket as $basketCode => $arOneRow) { $calculateValue = $value; if ($unit == self::VALUE_TYPE_PERCENT) { if (self::$getPercentFromBasePrice) { if (!isset($arOneRow['DISCOUNT_PRICE'])) { $arOneRow['DISCOUNT_PRICE'] = 0; } $calculateValue = (isset($arOneRow['BASE_PRICE']) ? $arOneRow['BASE_PRICE'] : $arOneRow['PRICE'] + $arOneRow['DISCOUNT_PRICE']) * $value / 100; } else { $calculateValue = $arOneRow['PRICE'] * $value / 100; } $calculateValue = roundEx($calculateValue, SALE_VALUE_PRECISION); } $dblResult = $arOneRow['PRICE'] + $calculateValue; if (abs($dblResult) < self::EPS) { $dblResult = 0; } if ($dblResult >= 0 && (!$manualMode || isset($arOneRow[self::BASKET_APPLIED_FIELD]))) { $arOneRow['PRICE'] = $dblResult; if (isset($arOneRow['PRICE_DEFAULT'])) { $arOneRow['PRICE_DEFAULT'] = $dblResult; } if (isset($arOneRow['DISCOUNT_PRICE'])) { $arOneRow['DISCOUNT_PRICE'] = (double) $arOneRow['DISCOUNT_PRICE']; $arOneRow['DISCOUNT_PRICE'] -= $calculateValue; } else { $arOneRow['DISCOUNT_PRICE'] = -$calculateValue; } if ($arOneRow['DISCOUNT_PRICE'] < 0) { $arOneRow['DISCOUNT_PRICE'] = 0; } if (isset($arOneRow['VAT_RATE'])) { $dblVatRate = (double) $arOneRow['VAT_RATE']; if ($dblVatRate > 0) { $arOneRow['VAT_VALUE'] = $arOneRow['PRICE'] / ($dblVatRate + 1) * $dblVatRate; } } foreach (self::$resetFields as &$fieldName) { if (isset($arOneRow[$fieldName]) && !is_array($arOneRow[$fieldName])) { $arOneRow['~' . $fieldName] = $arOneRow[$fieldName]; } } unset($fieldName); $order['BASKET_ITEMS'][$basketCode] = $arOneRow; $applyResultList[$basketCode] = $discountDescr; $applyResultList[$basketCode]['RESULT_VALUE'] = abs($calculateValue); if (isset($arOneRow['CURRENCY'])) { $applyResultList[$basketCode]['RESULT_UNIT'] = $arOneRow['CURRENCY']; } } } unset($basketCode); if (!isset($order['DISCOUNT_RESULT'])) { $order['DISCOUNT_RESULT'] = array(); } if (!isset($order['DISCOUNT_RESULT']['BASKET'])) { $order['DISCOUNT_RESULT']['BASKET'] = array(); } foreach ($applyResultList as $basketCode => $applyResult) { $prepareResult = Sale\OrderDiscountManager::prepareDiscountDescription($type, $applyResult); if ($prepareResult->isSuccess()) { if (!isset($order['DISCOUNT_RESULT']['BASKET'][$basketCode])) { $order['DISCOUNT_RESULT']['BASKET'][$basketCode] = array(); } $order['DISCOUNT_RESULT']['BASKET'][$basketCode][] = $prepareResult->getData(); } unset($prepareResult); } unset($basketCode, $applyResult, $applyResultList); } }