/**
  * 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;
 }
Esempio n. 2
0
 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;
 }
Esempio n. 3
0
 /**
  * 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;
 }
Esempio n. 4
0
 /**
  * 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;
 }
Esempio n. 5
0
$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());