/** * Calculate basket discounts for save. * * @param array &$basket Basket items. * @return bool */ public static function calculateBasketDiscounts(&$basket) { if (!self::$init) { return false; } if (!self::isSuccess() || self::$useMode == self::MODE_SYSTEM || self::$useMode == self::MODE_DISABLED) { return false; } if (empty($basket) || !is_array($basket)) { return false; } Sale\DiscountCouponsManager::clearApply(); if (self::$config['SALE_DISCOUNT_ONLY'] == 'Y' || empty(self::$basketDiscountList)) { return true; } $publicMode = self::usedByClient(); foreach ($basket as $basketCode => $basketItem) { if (\CSaleBasketHelper::isSetItem($basketItem)) { continue; } $code = $publicMode ? $basketItem['ID'] : $basketCode; if (empty(self::$basketDiscountList[$code])) { continue; } $itemData = array('MODULE' => $basketItem['MODULE'], 'PRODUCT_ID' => $basketItem['PRODUCT_ID'], 'BASKET_ID' => $code); foreach (self::$basketDiscountList[$code] as $index => $discount) { $discountResult = self::convertDiscount($discount); if (!$discountResult->isSuccess()) { return false; } $orderDiscountId = $discountResult->getId(); $discountData = $discountResult->getData(); $orderCouponId = ''; self::$basketDiscountList[$code][$index]['ORDER_DISCOUNT_ID'] = $orderDiscountId; if ($discountData['USE_COUPONS'] == 'Y') { if (empty($discount['COUPON'])) { return false; } $couponResult = self::convertCoupon($discount['COUPON'], $orderDiscountId); if (!$couponResult->isSuccess()) { return false; } $orderCouponId = $couponResult->getId(); Sale\DiscountCouponsManager::setApplyByProduct($itemData, array($orderCouponId)); unset($couponResult); } unset($discountData, $discountResult); if (!isset(self::$discountResult['BASKET'][$code])) { self::$discountResult['BASKET'][$code] = array(); } self::$discountResult['BASKET'][$code][$index] = array('DISCOUNT_ID' => $orderDiscountId, 'COUPON_ID' => $orderCouponId, 'RESULT' => array('APPLY' => 'Y', 'DESCR' => false, 'DESCR_DATA' => false)); $orderApplication = !empty(self::$discountsCache[$orderDiscountId]['APPLICATION']) ? self::$discountsCache[$orderDiscountId]['APPLICATION'] : null; if (!empty($orderApplication)) { $basketItem['DISCOUNT_RESULT'] = !empty(self::$discountsCache[$orderDiscountId]['ACTIONS_DESCR_DATA']) ? self::$discountsCache[$orderDiscountId]['ACTIONS_DESCR_DATA'] : false; $applyProduct = null; eval('$applyProduct=' . $orderApplication . ';'); if (is_callable($applyProduct)) { $applyProduct($basketItem); } unset($applyProduct); if (!empty($basketItem['DISCOUNT_RESULT'])) { self::$discountResult['BASKET'][$code][$index]['RESULT']['DESCR_DATA'] = $basketItem['DISCOUNT_RESULT']['BASKET']; self::$discountResult['BASKET'][$code][$index]['RESULT']['DESCR'] = self::formatDescription($basketItem['DISCOUNT_RESULT']); } unset($basketItem['DISCOUNT_RESULT']); } unset($orderApplication); } unset($discount, $index); } unset($basketCode, $basketItem); return true; }
function UpdateBasketPrices($fuserID, $siteID) { $fuserID = (int) $fuserID; if ($fuserID <= 0) { return false; } $siteID = (string) $siteID; if ($siteID == '') { $siteID = SITE_ID; } $isOrderConverted = \Bitrix\Main\Config\Option::get("main", "~sale_converted_15", 'N'); DiscountCouponsManager::clearApply(false); $basketItems = array(); /* if (!empty($arBasketItems) && is_array($arBasketItems)) { foreach ($arBasketItems as &$basketItemData) { if (array_key_exists('MEASURE_RATIO', $basketItemData)) { $basketItemQuantity = floatval($basketItemData['QUANTITY']); $basketItemRatio = floatval($basketItemData['MEASURE_RATIO']); $mod = roundEx(($basketItemQuantity / $basketItemRatio - intval($basketItemQuantity / $basketItemRatio)), 6); if ($mod !== 0) { $basketItemData['QUANTITY'] = ceil(ceil($basketItemQuantity) / $basketItemRatio)* $basketItemRatio; CSaleBasket::Update($basketItemData['ID'], array('QUANTITY' => $basketItemData['QUANTITY'])); } } } unset($basketItemData); } */ $dbBasketItems = CSaleBasket::GetList(array("ALL_PRICE" => "DESC"), array("FUSER_ID" => $fuserID, "LID" => $siteID, "ORDER_ID" => "NULL", "SUBSCRIBE" => "N"), false, false, array("ID", "MODULE", "PRODUCT_ID", "QUANTITY", "CALLBACK_FUNC", "PRODUCT_PROVIDER_CLASS", "CAN_BUY", "DELAY", "NOTES", "TYPE", "SET_PARENT_ID")); while ($arItem = $dbBasketItems->Fetch()) { $basketItems[] = $arItem; } if (!empty($basketItems) && is_array($basketItems)) { $basketItems = getRatio($basketItems); foreach ($basketItems as $basketItem) { $fields = array(); $basketItem['CALLBACK_FUNC'] = (string) $basketItem['CALLBACK_FUNC']; $basketItem['PRODUCT_PROVIDER_CLASS'] = (string) $basketItem['PRODUCT_PROVIDER_CLASS']; if (strval(trim($basketItem['PRODUCT_PROVIDER_CLASS'])) !== '' || strval(trim($basketItem['CALLBACK_FUNC'])) !== '') { $basketItem['MODULE'] = (string) $basketItem['MODULE']; $basketItem['PRODUCT_ID'] = (int) $basketItem['PRODUCT_ID']; $basketItem['QUANTITY'] = (double) $basketItem['QUANTITY']; if ($productProvider = CSaleBasket::GetProductProvider($basketItem)) { $fields = $productProvider::GetProductData(array("PRODUCT_ID" => $basketItem["PRODUCT_ID"], "QUANTITY" => $basketItem["QUANTITY"], "RENEWAL" => "N", "CHECK_COUPONS" => 'Y' == $basketItem['CAN_BUY'] && 'N' == $basketItem['DELAY'] ? 'Y' : 'N', "CHECK_DISCOUNT" => CSaleBasketHelper::isSetItem($basketItem) ? 'N' : 'Y', "BASKET_ID" => $basketItem["ID"], "NOTES" => $basketItem["NOTES"])); } else { $fields = CSaleBasket::ExecuteCallbackFunction($basketItem["CALLBACK_FUNC"], $basketItem["MODULE"], $basketItem["PRODUCT_ID"], $basketItem["QUANTITY"], "N"); } if (!empty($fields) && is_array($fields)) { if ($isOrderConverted == 'Y' && $basketItem['DELAY'] == 'N') { if (!Sale\Compatible\DiscountCompatibility::isInited()) { Sale\Compatible\DiscountCompatibility::init(); } if (Sale\Compatible\DiscountCompatibility::usedByClient()) { Sale\Compatible\DiscountCompatibility::setBasketItemData($basketItem['ID'], $fields); } } $fields['CAN_BUY'] = 'Y'; $fields['TYPE'] = (int) $basketItem['TYPE']; $fields['SET_PARENT_ID'] = (int) $basketItem['SET_PARENT_ID']; } else { $fields = array('CAN_BUY' => 'N'); } } if (array_key_exists('MEASURE_RATIO', $basketItem)) { $basketItemQuantity = floatval($basketItem['QUANTITY']); $basketItemRatio = floatval($basketItem['MEASURE_RATIO']); $mod = roundEx($basketItemQuantity / $basketItemRatio - intval($basketItemQuantity / $basketItemRatio), 6); if ($mod != 0) { $fields['QUANTITY'] = floor(ceil($basketItemQuantity) / $basketItemRatio) * $basketItemRatio; } } if (!empty($fields) && is_array($fields)) { CSaleBasket::Update($basketItem['ID'], $fields); } } } return true; }
/** * Calculate discount by new order. * * @return Result */ protected function calculateFull() { $result = new Result(); $this->discountIds = array(); if (!$this->isMixedBasket()) { $this->fillEmptyDiscountResult(); } else { $this->discountResult['ORDER'] = array(); } $order = $this->getOrder(); $basket = $order->getBasket(); /** @var BasketItem $basketItem */ foreach ($basket as $basketItem) { $code = $basketItem->getBasketCode(); if ($this->isCustomPriceByCode($code)) { if (array_key_exists($code, $this->basketDiscountList)) { unset($this->basketDiscountList[$code]); } } else { if (!isset($this->basketDiscountList[$code])) { $this->basketDiscountList[$code] = $basketItem->getField('DISCOUNT_LIST'); if ($this->basketDiscountList[$code] === null) { unset($this->basketDiscountList[$code]); } } } } unset($code, $basketItem, $basket); $this->resetBasketPrices(); if ($this->isMixedBasket()) { DiscountCouponsManager::clearApply(false); $basketDiscountResult = $this->calculateMixedBasketDiscount(); } else { DiscountCouponsManager::clearApply(); $basketDiscountResult = $this->calculateFullBasketDiscount(); } if (!$basketDiscountResult->isSuccess()) { $result->addErrors($basketDiscountResult->getErrors()); unset($basketDiscountResult); return $result; } unset($basketDiscountResult); $this->roundBasketPrices(); $codeList = array_keys($this->orderData['BASKET_ITEMS']); switch (self::getApplyMode()) { case self::APPLY_MODE_DISABLE: foreach ($codeList as &$code) { if (isset($this->basketDiscountList[$code]) && !empty($this->basketDiscountList[$code])) { $this->orderData['BASKET_ITEMS'][$code]['LAST_DISCOUNT'] = 'Y'; } } unset($code); break; case self::APPLY_MODE_LAST: foreach ($codeList as &$code) { if (!isset($this->basketDiscountList[$code]) || empty($this->basketDiscountList[$code])) { continue; } $lastDiscount = end($this->basketDiscountList[$code]); if (!empty($lastDiscount['LAST_DISCOUNT']) && $lastDiscount['LAST_DISCOUNT'] == 'Y') { $this->orderData['BASKET_ITEMS'][$code]['LAST_DISCOUNT'] = 'Y'; } } unset($code); break; case self::APPLY_MODE_ADD: break; } unset($codeList); $userGroups = \CUser::getUserGroup($this->orderData['USER_ID']); Main\Type\Collection::normalizeArrayValuesByInt($userGroups); $cacheKey = md5('U' . implode('_', $userGroups)); if (!isset($this->discountByUserCache[$cacheKey])) { $discountCache = array(); $groupDiscountIterator = Internals\DiscountGroupTable::getList(array('select' => array('DISCOUNT_ID'), 'filter' => array('@GROUP_ID' => $userGroups, '=ACTIVE' => 'Y'))); while ($groupDiscount = $groupDiscountIterator->fetch()) { $groupDiscount['DISCOUNT_ID'] = (int) $groupDiscount['DISCOUNT_ID']; if ($groupDiscount['DISCOUNT_ID'] > 0) { $discountCache[$groupDiscount['DISCOUNT_ID']] = $groupDiscount['DISCOUNT_ID']; } } unset($groupDiscount, $groupDiscountIterator); if (!empty($discountCache)) { Main\Type\Collection::normalizeArrayValuesByInt($discountCache); $this->discountByUserCache[$cacheKey] = $discountCache; } unset($discountCache); } if (!empty($this->discountByUserCache[$cacheKey])) { $this->discountIds = $this->discountByUserCache[$cacheKey]; } if (empty($this->discountIds)) { $this->discountIds = null; } else { $this->getDiscountModules(); $couponList = DiscountCouponsManager::getForApply(array('MODULE' => 'sale', 'DISCOUNT_ID' => $this->discountIds), array(), true); $cacheKey = md5('D' . implode('_', $this->discountIds)); if (!empty($couponList)) { $cacheKey .= '-C' . implode('_', array_keys($couponList)); } $currentList = array(); if (!isset($this->saleDiscountCache[$cacheKey])) { $discountApply = array(); $currentDatetime = new Main\Type\DateTime(); $discountSelect = array('ID', 'PRIORITY', 'SORT', 'LAST_DISCOUNT', 'UNPACK', 'APPLICATION', 'USE_COUPONS', 'EXECUTE_MODULE', 'NAME', 'CONDITIONS_LIST', 'ACTIONS_LIST'); $discountOrder = array('PRIORITY' => 'DESC', 'SORT' => 'ASC', 'ID' => 'ASC'); $discountFilter = array('@ID' => $this->discountIds, '=LID' => $this->orderData['SITE_ID'], '@EXECUTE_MODULE' => array('sale', 'all'), array('LOGIC' => 'OR', 'ACTIVE_FROM' => '', '<=ACTIVE_FROM' => $currentDatetime), array('LOGIC' => 'OR', 'ACTIVE_TO' => '', '>=ACTIVE_TO' => $currentDatetime)); unset($currentDatetime); if (empty($couponList)) { $discountFilter['=USE_COUPONS'] = 'N'; } else { $discountFilter[] = array('LOGIC' => 'OR', '=USE_COUPONS' => 'N', array('=USE_COUPONS' => 'Y', '@COUPON.COUPON' => array_keys($couponList))); $discountSelect['DISCOUNT_COUPON'] = 'COUPON.COUPON'; } $discountIterator = Internals\DiscountTable::getList(array('select' => $discountSelect, 'filter' => $discountFilter, 'order' => $discountOrder)); while ($discount = $discountIterator->fetch()) { $discount['ID'] = (int) $discount['ID']; if (isset($discountApply[$discount['ID']])) { continue; } $discountApply[$discount['ID']] = true; if (!$this->loadDiscountModules('sale' . $discount['ID'])) { continue; } if ($discount['USE_COUPONS'] == 'Y') { $discount['COUPON'] = $couponList[$discount['DISCOUNT_COUPON']]; } $discount['CONDITIONS'] = $discount['CONDITIONS_LIST']; $discount['ACTIONS'] = $discount['ACTIONS_LIST']; $discount['MODULE_ID'] = 'sale'; if (isset($this->cacheDiscountModules['sale' . $discount['ID']])) { $discount['MODULES'] = $this->cacheDiscountModules['sale' . $discount['ID']]; } unset($discount['ACTIONS_LIST'], $discount['CONDITIONS_LIST']); $currentList[] = $discount; } unset($discount, $discountIterator, $discountApply); $this->saleDiscountCache[$cacheKey] = $currentList; } else { $currentList = $this->saleDiscountCache[$cacheKey]; } unset($couponList); $this->discountIds = array(); if (!empty($currentList)) { foreach ($currentList as &$discount) { $this->discountIds[] = $discount['ID']; } unset($discount); $this->extendOrderData(); foreach ($currentList as $indexDiscount => $discount) { $this->fillCurrentStep(array('discount' => $discount)); if (!self::checkDiscountConditions()) { continue; } $actionsResult = $this->applySaleDiscount(); if (!$actionsResult->isSuccess()) { $result->addErrors($actionsResult->getErrors()); unset($actionsResult); return $result; } if ($this->currentStep['stop']) { break; } } unset($discount, $indexDiscount, $currentList); } $this->fillEmptyCurrentStep(); } return $result; }
/** * Calculate discount by exist order with new items. * * @return Result */ protected function calculateMixed() { $result = new Result(); $this->orderData['USE_BASE_PRICE'] = $this->saleOptions['USE_BASE_PRICE']; DiscountCouponsManager::clearApply(false); $basketDiscountResult = $this->calculateMixedBasketDiscount(); if (!$basketDiscountResult->isSuccess()) { $result->addErrors($basketDiscountResult->getErrors()); unset($basketDiscountResult); return $result; } unset($basketDiscountResult); $this->fillBasketLastDiscount(); return $result; }
$isRefreshDataAndSaveOperation = $_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST["refresh_data_and_save"]) && $_POST["refresh_data_and_save"] == "Y"; $isNeedFieldsRestore = $_SERVER["REQUEST_METHOD"] == "POST" && !$isSavingOperation && !$isRefreshDataAndSaveOperation; //save order params if (($isSavingOperation || $isNeedFieldsRestore || $isRefreshDataAndSaveOperation) && $saleModulePermissions >= "U" && check_bitrix_sessid() && $result->isSuccess()) { if ($isSavingOperation || $isRefreshDataAndSaveOperation) { $order = OrderEdit::editOrderByFormData($_POST, $order, $USER->GetID(), true, $_FILES, $result); } if (($isSavingOperation || $isRefreshDataAndSaveOperation) && $result->isSuccess()) { if ($order) { $res = OrderEdit::saveCoupons($order->getUserId(), $_POST); if (!$res) { $result->addError(new \Bitrix\Main\Entity\EntityError("Can't save coupons!")); } $discount = $order->getDiscount(); if ($isRefreshDataAndSaveOperation) { \Bitrix\Sale\DiscountCouponsManager::clearApply(true); \Bitrix\Sale\DiscountCouponsManager::useSavedCouponsForApply(true); $discount->setOrderRefresh(true); $discount->setApplyResult(array()); /** @var \Bitrix\Sale\Basket $basket */ if (!($basket = $order->getBasket())) { throw new \Bitrix\Main\ObjectNotFoundException('Entity "Basket" not found'); } $res = $basket->refreshData(array('PRICE', 'QUANTITY', 'COUPONS')); if (!$res->isSuccess()) { $result->addErrors($res->getErrors()); } } $res = $discount->calculate(); if (!$res->isSuccess()) { $result->addErrors($res->getErrors());