28 private static $discountProviders = array();
29 private static $managerConfig = array();
31 private static $discountCache = array();
38 public static function init()
43 static::initDiscountProviders();
55 if (empty($config) || empty($config[
'SITE_ID']))
57 if (empty($config[
'CURRENCY']))
58 $config[
'CURRENCY'] = Internals\SiteCurrencyTable::getSiteCurrency($config[
'SITE_ID']);
59 if (!isset($config[
'USE_BASE_PRICE']) || ($config[
'USE_BASE_PRICE'] !=
'Y' && $config[
'USE_BASE_PRICE'] !=
'N'))
60 $config[
'USE_BASE_PRICE'] = ((string)Main\
Config\Option::get(
'sale',
'get_discount_percent_from_base_price') ==
'Y' ?
'Y' :
'N');
61 if (empty($config[
'BASKET_ITEM']))
62 $config[
'BASKET_ITEM'] =
'$basketItem';
63 self::$managerConfig = $config;
74 return self::$managerConfig;
84 public static function saveDiscount(array $discount, $extResult =
false)
89 $extResult = ($extResult ===
true);
94 $discountData =
false;
100 'ORDER_DISCOUNT_ID' => 0,
101 'ORDER_COUPON_ID' => 0,
103 'LAST_DISCOUNT' =>
'',
105 'EDIT_PAGE_URL' =>
'',
106 'ACTIONS_DESCR' => array()
110 $emptyData[
'RAW_DATA'] = array();
111 $emptyData[
'PREPARED_DATA'] = array();
113 $resultData = $emptyData;
115 $config = static::getManagerConfig();
120 $result->addError(
new Main\Entity\EntityError(
126 if (empty($discount) || empty($discount[
'MODULE_ID']))
129 $result->addError(
new Main\Entity\EntityError(
137 if (!static::isNativeModule($discount[
'MODULE_ID']))
139 if (!static::checkDiscountProvider($discount[
'MODULE_ID']))
142 $result->addError(
new Main\Entity\EntityError(
149 $discountData = static::executeDiscountProvider(
150 array(
'MODULE_ID' => $discount[
'MODULE_ID'],
'METHOD' => self::PROVIDER_ACTION_PREPARE_DISCOUNT),
151 array($discount, $config)
157 $discountData = static::prepareData($discount);
159 if (empty($discountData) || !is_array($discountData))
162 $result->addError(
new Main\Entity\EntityError(
171 $fields = static::normalizeDiscountFields($discountData);
172 if (empty($fields) || !is_array($fields))
175 $result->addError(
new Main\Entity\EntityError(
180 elseif ($fields[
'DISCOUNT_HASH'] ===
null)
183 $result->addError(
new Main\Entity\EntityError(
192 $existDiscount = static::searchDiscount($fields[
'DISCOUNT_HASH']);
193 if ($existDiscount ===
null)
196 $internalResult = static::addDiscount($fields, $discountData);
197 if ($internalResult->isSuccess())
199 $existDiscount = static::searchDiscount($fields[
'DISCOUNT_HASH']);
204 $result->addErrors($internalResult->getErrors());
206 unset($internalResult);
208 if ($existDiscount !==
null)
210 $resultData = $existDiscount;
211 $result->setId($resultData[
'ID']);
217 $resultData[
'EDIT_PAGE_URL'] = $discountData[
'EDIT_PAGE_URL'];
220 $resultData[
'RAW_DATA'] = $discount;
221 $resultData[
'PREPARED_DATA'] = $discountData;
223 $result->setData($resultData);
225 unset($resultData, $process);
246 'ORDER_DISCOUNT_ID' => 0,
253 if (empty($coupon) || !is_array($coupon))
263 if (empty($coupon[
'ORDER_DISCOUNT_ID']) || (
int)$coupon[
'ORDER_DISCOUNT_ID'] <= 0)
271 if (empty($coupon[
'COUPON']))
279 if (!isset($coupon[
'TYPE']))
284 'SALE_ORDER_DISCOUNT_ERR_COUPON_TYPE_ABSENT',
285 array(
'#COUPON#' => $coupon[
'COUPON'])
294 $validateResult = static::validateCoupon($coupon);
295 if (!$validateResult->isSuccess())
298 $result->addErrors($validateResult->getErrors());
300 unset($validateResult);
305 $iterator = static::getOrderCouponIterator(array(
306 'select' => array(
'*'),
307 'filter' => array(
'=COUPON' => $coupon[
'COUPON'],
'=ORDER_ID' => $coupon[
'ORDER_ID'])
309 if ($row = $iterator->fetch())
315 $internalResult = static::addCoupon($coupon);
316 if ($internalResult->isSuccess())
318 $resultData = $internalResult->getData();
319 $resultData[
'ID'] = $internalResult->getId();
324 $result->addErrors($internalResult->getErrors());
326 unset($internalResult);
328 unset($row, $iterator);
333 $result->setId($resultData[
'ID']);
334 $result->setData($resultData);
336 unset($process, $resultData);
354 $module = (string)$module;
355 if (static::isNativeModule($module))
358 return static::executeDiscountProvider(
359 array(
'MODULE_ID' => $module,
'METHOD' => self::PROVIDER_ACTION_APPLY_COUPON),
360 array($discount, $basket, $params)
371 public static function roundPrice(array $basketItem, array $roundData = array())
375 if (empty($basketItem))
378 $result = static::executeDiscountProvider(
379 array(
'MODULE_ID' => $basketItem[
'MODULE'],
'METHOD' => self::PROVIDER_ACTION_ROUND_ITEM_PRICE),
380 array($basketItem, $roundData)
385 if (!isset($result[
'PRICE']) || !isset($result[
'DISCOUNT_PRICE']))
388 if (!isset($result[
'ROUND_RULE']))
402 public static function roundBasket(array $basket, array $roundData = array(), array $orderData = array())
410 $basketByModules = array();
411 $roundByModules = array();
412 foreach ($basket as $basketCode => $basketItem)
414 if (!isset($basketItem[
'MODULE']))
416 $module = $basketItem[
'MODULE'];
417 if (!isset($basketByModules[$module]))
419 $basketByModules[$module] = array();
420 $roundByModules[$module] = array();
422 $basketByModules[$module][$basketCode] = $basketItem;
423 $roundByModules[$module][$basketCode] = (isset($roundData[$basketCode]) ? $roundData[$basketCode] : array());
425 unset($basketCode, $basketItem);
427 foreach ($basketByModules as $module => $moduleItems)
429 $moduleResult = static::executeDiscountProvider(
430 array(
'MODULE_ID' => $module,
'METHOD' => self::PROVIDER_ACTION_ROUND_BASKET_PRICES),
431 array($moduleItems, $roundByModules[$module], $orderData)
433 if ($moduleResult ===
false)
435 $moduleResult = array();
436 foreach ($moduleItems as $basketCode => $basketItem)
438 $itemResult = static::roundPrice($basketItem, $roundByModules[$module][$basketCode]);
439 if (!empty($itemResult))
440 $moduleResult[$basketCode] = $itemResult;
443 if (empty($moduleResult))
446 foreach (array_keys($moduleResult) as $basketCode)
447 $result[$basketCode] = $moduleResult[$basketCode];
448 unset($moduleResult);
450 unset($moduleResult, $module, $moduleItems);
464 $module = (string)$module;
465 if (static::isNativeModule($module))
467 return ($module !=
'' && isset(self::$discountProviders[$module]));
479 if (!empty($discount[
'ID']))
480 $result =
'/bitrix/admin/sale_discount_edit.php?lang='.LANGUAGE_ID.
'&ID='.$discount[
'ID'];
491 $entity = get_called_class();
492 if (!isset(self::$discountCache[$entity]))
494 unset(self::$discountCache[$entity]);
505 public static function loadResultFromDb($order, array $basketList = [], array $basketData = [])
511 $discountClassName = static::getDiscountClassName();
512 $emptyApplyBlock = $discountClassName::getEmptyApplyBlock();
514 $order = (int)$order;
524 'APPLY_BLOCKS' => [],
525 'DISCOUNT_LIST' => [],
527 'STORED_ACTION_DATA' => []
532 $orderDiscountIndex = [];
533 $orderDiscountLink = [];
539 $resultData[
'COUPON_LIST'] = static::loadCouponsFromDb($order);
540 if (!empty($resultData[
'COUPON_LIST']))
542 foreach ($resultData[
'COUPON_LIST'] as $coupon)
543 $couponList[$coupon[
'ID']] = $coupon[
'COUPON'];
547 $ruleIterator = static::getResultIterator([
548 'filter' => [
'=ORDER_ID' => $order],
549 'order' => [
'ID' =>
'ASC']
551 while ($rule = $ruleIterator->fetch())
553 $rule[
'ID'] = (int)$rule[
'ID'];
554 $rule[
'ORDER_DISCOUNT_ID'] = (int)$rule[
'ORDER_DISCOUNT_ID'];
555 $rule[
'ORDER_COUPON_ID'] = (int)$rule[
'COUPON_ID'];
556 $rule[
'ENTITY_ID'] = (int)$rule[
'ENTITY_ID'];
558 if ($rule[
'ORDER_COUPON_ID'] > 0)
560 if (!isset($couponList[$rule[
'COUPON_ID']]))
562 $result->addError(
new Main\Entity\EntityError(
564 'SALE_ORDER_DISCOUNT_ERR_RULE_COUPON_NOT_FOUND',
565 array(
'#ID#' => $rule[
'ID'],
'#COUPON_ID#' => $rule[
'COUPON_ID'])
571 $rule[
'COUPON_ID'] = $couponList[$rule[
'ORDER_COUPON_ID']];
574 if (!isset($rule[
'RULE_DESCR_ID']))
575 $rule[
'RULE_DESCR_ID'] = 0;
576 $rule[
'RULE_DESCR_ID'] = (int)$rule[
'RULE_DESCR_ID'];
578 $rule[
'APPLY_BLOCK_COUNTER'] = (int)$rule[
'APPLY_BLOCK_COUNTER'];
579 $blockCounter = $rule[
'APPLY_BLOCK_COUNTER'];
580 if (!isset($applyBlocks[$blockCounter]))
581 $applyBlocks[$blockCounter] = $emptyApplyBlock;
582 if (!isset($orderDiscountIndex[$blockCounter]))
583 $orderDiscountIndex[$blockCounter] = 0;
585 if (!isset($discountList[$rule[
'ORDER_DISCOUNT_ID']]))
587 $discountList[$rule[
'ORDER_DISCOUNT_ID']] = $rule[
'ORDER_DISCOUNT_ID'];
588 $discountSort[] = $rule[
'ORDER_DISCOUNT_ID'];
591 if (static::isNativeModule($rule[
'MODULE_ID']))
593 $discountId = (int)$rule[
'ORDER_DISCOUNT_ID'];
594 if (!isset($orderDiscountLink[$discountId]))
596 $applyBlocks[$blockCounter][
'ORDER'][$orderDiscountIndex[$blockCounter]] = static::formatSaleRuleResult($rule);
597 $orderDiscountLink[$discountId] = &$applyBlocks[$blockCounter][
'ORDER'][$orderDiscountIndex[$blockCounter]];
598 $orderDiscountIndex[$blockCounter]++;
601 $ruleItem = static::formatSaleItemRuleResult($rule);
603 switch (static::getResultEntityFromInternal($rule[
'ENTITY_TYPE']))
605 case $discountClassName::ENTITY_BASKET_ITEM:
606 $index = static::transferEntityCodeFromInternal($rule, $basketList);
610 $ruleItem[
'BASKET_ID'] = static::transferEntityCodeFromInternal($rule, []);
611 static::fillRuleProductFields($ruleItem, $basketData, $index);
612 if (!isset($orderDiscountLink[$discountId][
'RESULT'][
'BASKET']))
613 $orderDiscountLink[$discountId][
'RESULT'][
'BASKET'] = [];
614 $orderDiscountLink[$discountId][
'RESULT'][
'BASKET'][$index] = $ruleItem;
615 if ($ruleItem[
'ACTION_BLOCK_LIST'] ===
null)
616 $orderDiscountLink[$discountId][
'ACTION_BLOCK_LIST'] =
false;
618 case $discountClassName::ENTITY_DELIVERY:
619 if (!isset($orderDiscountLink[$discountId][
'RESULT'][
'DELIVERY']))
620 $orderDiscountLink[$discountId][
'RESULT'][
'DELIVERY'] = [];
621 $ruleItem[
'DELIVERY_ID'] = static::transferEntityCodeFromInternal($rule, []);
622 $orderDiscountLink[$discountId][
'RESULT'][
'DELIVERY'] = $ruleItem;
625 unset($ruleItem, $discountId);
630 $rule[
'ENTITY_ID'] <= 0
631 || static::getResultEntityFromInternal($rule[
'ENTITY_TYPE']) != $discountClassName::ENTITY_BASKET_ITEM
635 $index = static::transferEntityCodeFromInternal($rule, $basketList);
639 $ruleResult = static::formatBasketRuleResult($rule);
640 static::fillRuleProductFields($ruleResult, $basketData, $index);
642 if (!isset($applyBlocks[$blockCounter][
'BASKET'][$index]))
643 $applyBlocks[$blockCounter][
'BASKET'][$index] = [];
644 $applyBlocks[$blockCounter][
'BASKET'][$index][] = $ruleResult;
649 unset($rule, $ruleIterator);
651 unset($orderDiscountLink, $orderDiscountIndex);
653 if (!empty($discountList))
655 $resultData[
'DISCOUNT_LIST'] = static::loadOrderDiscountFromDb($discountList, $discountSort);
656 if ($resultData[
'DISCOUNT_LIST'] ===
null)
657 $resultData[
'DISCOUNT_LIST'] = [];
659 unset($discountSort, $discountList);
661 $actionsData = static::loadOrderStoredDataFromDb(
663 self::STORAGE_TYPE_DISCOUNT_ACTION_DATA
665 if ($actionsData !==
null)
666 $resultData[
'STORED_ACTION_DATA'] = $actionsData;
669 $dataIterator = static::getRoundResultIterator([
672 '=ORDER_ID' => $order,
673 '=ENTITY_TYPE' => static::getRoundEntityInternal($discountClassName::ENTITY_BASKET_ITEM)
676 while ($data = $dataIterator->fetch())
678 $data[
'APPLY_BLOCK_COUNTER'] = (int)$data[
'APPLY_BLOCK_COUNTER'];
679 $blockCounter = $data[
'APPLY_BLOCK_COUNTER'];
680 if (!isset($applyBlocks[$blockCounter]))
681 $applyBlocks[$blockCounter] = $emptyApplyBlock;
682 $basketCode = static::transferEntityCodeFromInternal($data, $basketList);
683 if ($basketCode ==
'')
686 $applyBlocks[$blockCounter][
'BASKET_ROUND'][$basketCode] = array(
687 'RULE_ID' => (
int)$data[
'ID'],
688 'APPLY' => $data[
'APPLY'],
689 'ROUND_RULE' => $data[
'ROUND_RULE']
691 unset($basketCode, $blockCounter);
693 unset($data, $dataIterator);
695 if (!empty($applyBlocks))
698 $resultData[
'APPLY_BLOCKS'] = $applyBlocks;
701 $result->setData($resultData);
704 unset($emptyApplyBlock, $discountClassName);
718 if (empty($discountIds) || empty($discountOrder))
723 $iterator = static::getOrderDiscountIterator([
725 'filter' => [
'@ID' => $discountIds]
727 while ($row = $iterator->fetch())
729 $row[
'ID'] = (int)$row[
'ID'];
730 $row[
'ORDER_DISCOUNT_ID'] = $row[
'ID'];
731 $row[
'MODULES'] = [];
732 $row[
'SIMPLE_ACTION'] =
true;
733 if (static::isNativeModule($row[
'MODULE_ID']))
734 $row[
'SIMPLE_ACTION'] = self::isSimpleAction($row[
'APPLICATION']);
735 $list[$row[
'ID']] = $row;
737 unset($row, $iterator);
741 foreach ($discountOrder as $id)
743 if (!isset($list[$id]))
745 $result[$id] = $list[$id];
753 $resultIds = array_keys($result);
754 $discountModules = static::loadModulesFromDb($resultIds);
755 if ($discountModules !==
null)
757 foreach ($discountModules as $id => $modules)
758 $result[$id][
'MODULES'] = $modules;
759 unset($id, $modules);
761 unset($discountModules);
763 foreach ($resultIds as $id)
765 $discount = $result[$id];
766 if (static::isNativeModule($discount[
'MODULE_ID']))
768 $result[$id][
'EDIT_PAGE_URL'] = static::getEditUrl([
'ID' => $discount[
'DISCOUNT_ID']]);
772 $result[$id][
'EDIT_PAGE_URL'] = (string)static::executeDiscountProvider(
773 [
'MODULE_ID' => $discount[
'MODULE_ID'],
'METHOD' => self::PROVIDER_ACTION_GET_URL],
775 [
'ID' => $discount[
'DISCOUNT_ID'],
'MODULE_ID' => $discount[
'MODULE_ID']]
780 unset($discount, $id);
783 return (!empty($result) ? $result :
null);
799 $order = (int)$order;
803 $storageType = static::getStorageTypeInternal($storageType);
804 if ($storageType ===
null)
807 '=ORDER_ID' => $order,
808 '=ENTITY_TYPE' => $storageType,
810 if (!empty($additionalFilter))
811 $filter = $filter + $additionalFilter;
814 $iterator = static::getStoredDataIterator(array(
818 while ($row = $iterator->fetch())
820 if (empty($row[
'ENTITY_DATA']) || !is_array($row[
'ENTITY_DATA']))
822 $index = static::getEntityIndex($row);
823 $list[$index] = $row[
'ENTITY_DATA'];
825 unset($index, $row, $iterator);
845 $data = static::loadStoredDataFromDb(
848 [
'=ENTITY_ID' => $order]
852 if (count($data) > 1)
854 if (isset($data[$order]))
855 $result = $data[$order];
872 return static::saveStoredDataBlock(
876 'ENTITY_ID' => $order,
877 'ENTITY_VALUE' => $order,
878 'ENTITY_DATA' => $data
898 $order = (int)$order;
901 $result->addError(
new Main\
Error(
908 $storageType = static::getStorageTypeInternal($storageType);
909 if ($storageType ===
null)
911 $result->addError(
new Main\
Error(
918 $allowUpdate = (isset($options[
'ALLOW_UPDATE']) && $options[
'ALLOW_UPDATE'] ===
'Y');
919 $deleteMissing = (isset($options[
'DELETE_MISSING']) && $options[
'DELETE_MISSING'] ===
'Y');
923 $iterator = static::getStoredDataIterator([
926 '=ORDER_ID' => $order,
927 '=ENTITY_TYPE' => $storageType,
930 while ($row = $iterator->fetch())
932 $index = static::getEntityIndex($row);
933 $collection[$index] = $row;
934 $deleteList[$index] = $row[
'ID'];
936 unset($row, $iterator);
939 foreach ($block as $index => $row)
941 if (isset($deleteList[$index]))
942 unset($deleteList[$index]);
943 if (!empty($collection[$index]) && !$allowUpdate)
948 if (empty($collection[$index]))
950 $row[
'ORDER_ID'] = $order;
951 $row[
'ENTITY_TYPE'] = $storageType;
952 $resultInternal = static::addStoredDataInternal($row);
956 $resultInternal = static::updateStoredDataInternal(
957 $collection[$index][
'ID'],
958 [
'ENTITY_DATA' => $row[
'ENTITY_DATA']]
961 if (!$resultInternal->isSuccess())
962 $result->addErrors($resultInternal->getErrors());
964 unset($resultInternal, $index, $row);
968 $result->addError(
new Main\
Error(
969 Loc::getMessage(
'SALE_ORDER_DISCOUNT_ERR_ORDER_STORED_DATA_ALREADY_EXISTS'),
975 if ($result->isSuccess())
977 if ($deleteMissing && !empty($deleteList))
978 static::deleteRowsByIndex(static::getStoredDataTableInternal(),
'ID', $deleteList);
980 unset($deleteList, $deleteMissing);
989 $order = (int)$order;
992 $result->addError(
new Main\
Error(
1002 foreach ($block as $row)
1004 $row[
'ORDER_ID'] = $order;
1005 $row[
'ENTITY_TYPE'] = static::getResultEntityInternal($row[
'ENTITY_TYPE']);
1006 if (!isset($row[
'APPLY_BLOCK_COUNTER']) || $row[
'APPLY_BLOCK_COUNTER'] < 0)
1013 $resultInternal = static::addResultRow($row);
1014 if (!$resultInternal->isSuccess())
1015 $result->addErrors($resultInternal->getErrors());
1017 unset($resultInternal, $row);
1026 $order = (int)$order;
1029 $result->addError(
new Main\
Error(
1036 $deleteList = array();
1037 $iterator = static::getResultIterator(array(
1038 'select' => array(
'ID'),
1039 'filter' => array(
'=ORDER_ID' => $order),
1040 'order' => array(
'ID' =>
'ASC')
1042 while ($row = $iterator->fetch())
1044 $row[
'ID'] = (int)$row[
'ID'];
1045 $deleteList[$row[
'ID']] = $row[
'ID'];
1047 unset($row, $iterator);
1051 foreach ($block as $row)
1054 if (isset($row[
'RULE_ID']) && $row[
'RULE_ID'] > 0)
1055 $id = $row[
'RULE_ID'];
1056 unset($row[
'RULE_ID']);
1059 $result->addError(
new Main\
Error(
1065 if (!isset($deleteList[$id]))
1067 $result->addError(
new Main\
Error(
1073 unset($deleteList[$id]);
1075 $resultInternal = static::updateResultRow($id, $row);
1076 if (!$resultInternal->isSuccess())
1077 $result->addErrors($resultInternal->getErrors());
1079 unset($resultInternal, $row);
1082 if (!$result->isSuccess())
1085 if (!empty($deleteList))
1087 self::deleteRowsByIndex(static::getResultTableNameInternal(),
'ID', $deleteList);
1088 self::deleteRowsByIndex(static::getResultDescriptionTableNameInternal(),
'RULE_ID', $deleteList);
1098 $order = (int)$order;
1101 $result->addError(
new Main\
Error(
1111 foreach ($block as $row)
1113 $row[
'ORDER_ID'] = $order;
1114 $row[
'ENTITY_TYPE'] = static::getRoundEntityInternal($row[
'ENTITY_TYPE']);
1115 $row[
'ORDER_ROUND'] =
'N';
1116 if (!isset($row[
'APPLY_BLOCK_COUNTER']) || $row[
'APPLY_BLOCK_COUNTER'] < 0)
1123 $resultInternal = static::addRoundResultInternal($row);
1124 if (!$resultInternal->isSuccess())
1125 $result->addErrors($resultInternal->getErrors());
1127 unset($resultInternal, $row);
1136 $order = (int)$order;
1139 $result->addError(
new Main\
Error(
1146 $deleteList = array();
1147 $iterator = static::getRoundResultIterator([
1149 'filter' => [
'=ORDER_ID' => $order]
1151 while ($row = $iterator->fetch())
1153 $row[
'ID'] = (int)$row[
'ID'];
1154 $deleteList[$row[
'ID']] = $row[
'ID'];
1156 unset($row, $iterator);
1160 foreach ($block as $row)
1163 if (isset($row[
'RULE_ID']) && $row[
'RULE_ID'] > 0)
1164 $id = $row[
'RULE_ID'];
1167 $result->addError(
new Main\
Error(
1173 if (!isset($deleteList[$id]))
1175 $result->addError(
new Main\
Error(
1181 unset($deleteList[$id]);
1183 unset($row[
'RULE_ID']);
1184 $resultInternal = static::updateRoundResultInternal($id, $row);
1185 if (!$resultInternal->isSuccess())
1186 $result->addErrors($resultInternal->getErrors());
1188 unset($resultInternal, $row);
1191 if (!$result->isSuccess())
1194 if (!empty($deleteList))
1195 self::deleteRowsByIndex(static::getRoundTableNameInternal(),
'ID', $deleteList);
1223 return $registry->getDiscountClassName();
1234 return ($module ===
'sale');
1245 self::PROVIDER_ACTION_PREPARE_DISCOUNT,
1246 self::PROVIDER_ACTION_GET_URL,
1247 self::PROVIDER_ACTION_APPLY_COUPON,
1248 self::PROVIDER_ACTION_ROUND_ITEM_PRICE,
1249 self::PROVIDER_ACTION_ROUND_BASKET_PRICES
1258 protected static function initDiscountProviders()
1260 self::$discountProviders = array();
1261 $event =
new Main\Event(
'sale', self::EVENT_ON_BUILD_DISCOUNT_PROVIDERS, array());
1263 $resultList = $event->getResults();
1264 if (empty($resultList) || !is_array($resultList))
1266 $actionList = static::getDiscountProviderActions();
1268 foreach ($resultList as $eventResult)
1270 if ($eventResult->getType() != Main\EventResult::SUCCESS)
1272 $module = (string)$eventResult->getModuleId();
1273 $provider = $eventResult->getParameters();
1274 if (empty($provider) || !is_array($provider))
1276 if (!isset($provider[self::PROVIDER_ACTION_PREPARE_DISCOUNT]))
1278 self::$discountProviders[$module] = array(
1281 foreach ($actionList as $action)
1283 if (isset($provider[$action]))
1284 self::$discountProviders[$module][$action] = $provider[$action];
1287 unset($provider, $module, $actionList, $eventResult, $resultList, $event);
1304 $module = $provider[
'MODULE_ID'];
1305 $method = $provider[
'METHOD'];
1307 if (!isset(self::$discountProviders[$module]) || !isset(self::$discountProviders[$module][$method]))
1310 return call_user_func_array(
1311 self::$discountProviders[$module][$method],
1324 $fields = static::fillAbsentDiscountFields($discount);
1325 if ($fields ===
null)
1328 $discountId = (int)$fields[
'ID'];
1329 if (!isset($fields[
'NAME']) || (string)$fields[
'NAME'] ==
'')
1330 $fields[
'NAME'] =
Loc::getMessage(
'SALE_ORDER_DISCOUNT_NAME_TEMPLATE', array(
'#ID#' => $fields[
'ID']));
1331 $fields[
'DISCOUNT_ID'] = $discountId;
1332 $fields[
'EDIT_PAGE_URL'] = static::getEditUrl(array(
'ID' => $discountId));
1333 unset($fields[
'ID']);
1346 if (empty($fields) || empty($fields[
'ID']))
1349 $discountId = (int)$fields[
'ID'];
1350 if ($discountId <= 0)
1353 $requiredFields = static::checkRequiredOrderDiscountFields($fields);
1354 if (!empty($requiredFields))
1356 if (in_array(
'ACTIONS_DESCR', $requiredFields))
1358 $requiredFields[] =
'ID';
1359 $iterator = static::getDiscountIterator(array(
1360 'select' => $requiredFields,
1361 'filter' => array(
'=ID' => $discountId)
1363 $row = $iterator->fetch();
1367 foreach ($row as $field => $value)
1369 if (isset($fields[$field]))
1371 $fields[$field] = $value;
1373 unset($field, $value);
1375 unset($requiredFields);
1388 $result = static::normalizeOrderDiscountFieldsInternal($rawFields);
1389 if (!is_array($result))
1391 $result[
'DISCOUNT_HASH'] = static::calculateOrderDiscountHashInternal($result);
1403 $hash = (string)$hash;
1406 $entity = get_called_class();
1407 if (!isset(self::$discountCache[$entity]))
1408 self::$discountCache[$entity] = array();
1409 if (!isset(self::$discountCache[$entity][$hash]))
1411 $iterator = static::getOrderDiscountIterator(array(
1412 'select' => array(
'*'),
1413 'filter' => array(
'=DISCOUNT_HASH' => $hash)
1415 $row = $iterator->fetch();
1417 self::setCacheItem($entity, $row);
1418 unset($row, $iterator);
1421 return (isset(self::$discountCache[$entity][$hash]) ? self::$discountCache[$entity][$hash] :
null);
1431 private static function setCacheItem($entity, array $fields)
1433 $fields[
'ID'] = (int)$fields[
'ID'];
1434 $fields[
'NAME'] = (string)$fields[
'NAME'];
1435 $fields[
'ORDER_DISCOUNT_ID'] = $fields[
'ID'];
1436 self::$discountCache[$entity][$fields[
'DISCOUNT_HASH']] = $fields;
1450 !static::isValidCouponTypeInternal($fields[
'TYPE'])
1455 'SALE_ORDER_DISCOUNT_ERR_COUPON_TYPE_BAD',
1456 array(
'#COUPON#' => $fields[
'COUPON'])
1462 if (empty($fields[
'COUPON_ID']) || (
int)$fields[
'COUPON_ID'] <= 0)
1466 'SALE_ORDER_DISCOUNT_ERR_COUPON_ID_BAD',
1467 array(
'#COUPON#' => $fields[
'COUPON'])
1486 if (array_key_exists(
'ID', $fields))
1487 unset($fields[
'ID']);
1488 $tabletResult = static::addOrderCouponInternal($fields);
1489 if ($tabletResult->isSuccess())
1491 $fields[
'ID'] = $tabletResult->getId();
1492 $result->setId($fields[
'ID']);
1493 $result->setData($fields);
1497 $result->addErrors($tabletResult->getErrors());
1499 unset($tabletResult);
1511 protected static function addDiscount(array $fields, array $rawFields)
1516 $orderDiscountId =
null;
1518 $tabletResult = static::addOrderDiscountInternal($fields);
1519 if ($tabletResult->isSuccess())
1521 $orderDiscountId = (int)$tabletResult->getId();
1526 $result->addErrors($tabletResult->getErrors());
1528 unset($tabletResult);
1532 $moduleList = static::prepareDiscountModules($rawFields);
1533 if (!empty($moduleList))
1535 $resultModule = static::saveOrderDiscountModulesInternal(
1547 unset($resultModule);
1553 $result->setId($orderDiscountId);
1566 if (empty($discountIds))
1569 Main\Type\Collection::normalizeArrayValuesByInt($discountIds,
true);
1570 if (empty($discountIds))
1574 $iterator = static::getOrderDiscountModuleIterator(array(
1575 'select' => array(
'MODULE_ID',
'ORDER_DISCOUNT_ID'),
1576 'filter' => array(
'@ORDER_DISCOUNT_ID' => $discountIds)
1578 while ($row = $iterator->fetch())
1580 $orderDiscountId = (int)$row[
'ORDER_DISCOUNT_ID'];
1581 if (!isset($result[$orderDiscountId]))
1582 $result[$orderDiscountId] = array();
1583 $result[$orderDiscountId][] = $row[
'MODULE_ID'];
1585 unset($row, $iterator);
1587 return (!empty($result) ? $result :
null);
1593 $needDiscountModules = array();
1594 if (!empty($discount[
'MODULES']))
1596 $needDiscountModules = (
1597 !is_array($discount[
'MODULES'])
1598 ? array($discount[
'MODULES'])
1599 : $discount[
'MODULES']
1602 elseif (!empty($discount[
'HANDLERS']))
1604 if (!empty($discount[
'HANDLERS'][
'MODULES']))
1606 $needDiscountModules = (
1607 !is_array($discount[
'HANDLERS'][
'MODULES'])
1608 ? array($discount[
'HANDLERS'][
'MODULES'])
1609 : $discount[
'HANDLERS'][
'MODULES']
1613 if (!empty($needDiscountModules))
1615 foreach ($needDiscountModules as &$module)
1617 $module = trim((
string)$module);
1618 if (!empty($module))
1619 $result[$module] = $module;
1622 $result = array_values($result);
1639 $row[
'ENTITY_VALUE'] = (string)$row[
'ENTITY_VALUE'];
1640 if (!empty($transferList))
1642 if ($row[
'ENTITY_ID'] > 0 && isset($transferList[$row[
'ENTITY_ID']]))
1643 $code = $transferList[$row[
'ENTITY_ID']];
1644 elseif ($row[
'ENTITY_VALUE'] !==
'' && isset($transferList[$row[
'ENTITY_VALUE']]))
1645 $code = $transferList[$row[
'ENTITY_VALUE']];
1649 $code = ($row[
'ENTITY_ID'] > 0 ? $row[
'ENTITY_ID'] : $row[
'ENTITY_VALUE']);
1663 'BASKET_ID' => $rule[
'ENTITY_ID'],
1664 'RULE_ID' => $rule[
'ID'],
1665 'ORDER_ID' => $rule[
'ORDER_ID'],
1666 'DISCOUNT_ID' => $rule[
'ORDER_DISCOUNT_ID'],
1667 'ORDER_COUPON_ID' => $rule[
'ORDER_COUPON_ID'],
1668 'COUPON_ID' => ($rule[
'ORDER_COUPON_ID'] > 0 ? $rule[
'COUPON_ID'] :
''),
1669 'RESULT' => [
'APPLY' => $rule[
'APPLY']],
1670 'RULE_DESCR_ID' => $rule[
'RULE_DESCR_ID'],
1671 'ACTION_BLOCK_LIST' => (isset($rule[
'ACTION_BLOCK_LIST']) ? $rule[
'ACTION_BLOCK_LIST'] :
null)
1674 if (!empty($rule[
'RULE_DESCR']) && is_array($rule[
'RULE_DESCR']))
1676 $ruleResult[
'RESULT'][
'DESCR_DATA'] = $rule[
'RULE_DESCR'];
1677 $ruleResult[
'RESULT'][
'DESCR'] = Discount\Formatter::formatList($rule[
'RULE_DESCR']);
1678 $ruleResult[
'DESCR_ID'] = $rule[
'RULE_DESCR_ID'];
1693 'ORDER_ID' => $rule[
'ORDER_ID'],
1694 'DISCOUNT_ID' => $rule[
'ORDER_DISCOUNT_ID'],
1695 'ORDER_COUPON_ID' => $rule[
'ORDER_COUPON_ID'],
1696 'COUPON_ID' => ($rule[
'ORDER_COUPON_ID'] > 0 ? $rule[
'COUPON_ID'] :
''),
1698 'ACTION_BLOCK_LIST' =>
true
1711 'RULE_ID' => $rule[
'ID'],
1712 'APPLY' => $rule[
'APPLY'],
1713 'RULE_DESCR_ID' => $rule[
'RULE_DESCR_ID'],
1714 'ACTION_BLOCK_LIST' => (
1715 !empty($rule[
'ACTION_BLOCK_LIST']) && is_array($rule[
'ACTION_BLOCK_LIST'])
1716 ? $rule[
'ACTION_BLOCK_LIST']
1720 if (!empty($rule[
'RULE_DESCR']) && is_array($rule[
'RULE_DESCR']))
1722 $ruleItem[
'DESCR_DATA'] = $rule[
'RULE_DESCR'];
1723 $ruleItem[
'DESCR'] = Discount\Formatter::formatList($rule[
'RULE_DESCR']);
1724 $ruleItem[
'DESCR_ID'] = $rule[
'RULE_DESCR_ID'];
1740 if (!empty($basketData[$index]))
1742 $result[
'MODULE'] = $basketData[$index][
'MODULE'];
1743 $result[
'PRODUCT_ID'] = $basketData[$index][
'PRODUCT_ID'];
1869 $couponIterator = static::getOrderCouponIterator(array(
1870 'select' => array(
'*'),
1871 'filter' => array(
'=ORDER_ID' => $order),
1872 'order' => array(
'ID' =>
'ASC')
1874 while ($coupon = $couponIterator->fetch())
1876 $coupon[
'ID'] = (int)$coupon[
'ID'];
1877 $coupon[
'ORDER_ID'] = (int)$coupon[
'ORDER_ID'];
1878 $coupon[
'ORDER_DISCOUNT_ID'] = (int)$coupon[
'ORDER_DISCOUNT_ID'];
1879 $result[$coupon[
'COUPON']] = $coupon;
1881 unset($coupon, $couponIterator);
1963 if (array_key_exists(
'ID', $fields))
1964 unset($fields[
'ID']);
1965 $resultFields = static::checkResultTableWhiteList($fields);
1966 if (empty($resultFields))
1968 $result =
new Main\Entity\AddResult();
1974 $result = static::addResultInternal($resultFields);
1975 unset($resultFields);
1976 if (!$result->isSuccess())
1979 $fields[
'RULE_ID'] = (int)$result->getId();
1980 $descriptionFields = static::checkResultDescriptionTableWhiteList($fields);
1981 if (empty($descriptionFields))
1984 Loc::getMessage(
'SALE_ORDER_DISCOUNT_ERR_RESULT_ROW_DESCRIPTION_IS_EMPTY')
1988 $descriptionResult = static::addResultDescriptionInternal($descriptionFields);
1989 unset($descriptionFields);
1990 if (!$descriptionResult->isSuccess())
1991 $result->addErrors($descriptionResult->getErrors());
1992 unset($descriptionResult);
2006 $rowUpdate = [
'APPLY' => $fields[
'APPLY']];
2007 if (isset($fields[
'ACTION_BLOCK_LIST']))
2008 $rowUpdate[
'ACTION_BLOCK_LIST'] = $fields[
'ACTION_BLOCK_LIST'];
2009 $result = static::updateResultInternal($id, $rowUpdate);
2011 if (!$result->isSuccess())
2015 if (isset($fields[
'DESCR_ID']) && $fields[
'DESCR_ID'] > 0)
2016 $descrId = $fields[
'DESCR_ID'];
2017 if ($descrId ===
null)
2019 $iterator = static::getResultDescriptionIterator([
2021 'filter' => [
'=RULE_ID' => $id]
2023 $row = $iterator->fetch();
2024 if (!empty($row[
'ID']))
2025 $descrId = (int)$row[
'ID'];
2026 unset($row, $iterator);
2028 if ($descrId ===
null)
2030 $iterator = static::getResultIterator([
2031 'select' => [
'MODULE_ID',
'ORDER_DISCOUNT_ID',
'ORDER_ID'],
2032 'filter' => [
'=ID' => $id],
2035 $row = $iterator->fetch();
2037 $row[
'RULE_ID'] = $id;
2038 $row[
'DESCR'] = $fields[
'DESCR'];
2039 $resultDescr = static::addResultDescriptionInternal($row);
2044 $resultDescr = static::updateResultDescriptionInternal(
2045 $fields[
'DESCR_ID'],
2046 array(
'DESCR' => $fields[
'DESCR'])
2050 if (!$resultDescr->isSuccess())
2051 $result->addErrors($resultDescr->getErrors());
2052 unset($resultDescr);
2279 private static function isSimpleAction($action)
2283 $action = (string)$action;
2287 $action = trim(mb_substr($action, 8));
2288 $action = mb_substr($action, 2);
2289 $key = mb_strpos($action,
')');
2292 $orderName =
'\\'.mb_substr($action, 0, $key);
2294 preg_match_all(
"/".$orderName.
"(?:,|\))/".BX_UTF_PCRE_MODIFIER, $action, $list);
2295 if (isset($list[0]) && is_array($list[0]))
2296 $result = count($list[0]) <= 2;
2309 private static function deleteRowsByIndex($tableName, $indexField, array $ids)
2311 $tableName = (string)$tableName;
2312 if ($tableName ===
'')
2314 $indexField = (string)$indexField;
2315 if ($indexField ===
'')
2320 Main\Type\Collection::normalizeArrayValuesByInt($ids,
true);
2324 $conn = Main\Application::getConnection();
2325 $helper = $conn->getSqlHelper();
2327 $query =
'delete from '.$helper->quote($tableName).
' where '.$helper->quote($indexField);
2328 foreach (array_chunk($ids, 500) as $page)
2330 $conn->queryExecute($query.
' in ('.implode(
', ', $page).
')');
2332 unset($page, $query);
2334 unset($helper, $conn);
2337 private static function getEntityIndex(array $row)
2339 return (isset($row[
'ENTITY_ID']) ? $row[
'ENTITY_ID'] : $row[
'ENTITY_VALUE']);