12Loc::loadMessages(__FILE__);
34 Main\EventResult::SUCCESS,
36 'prepareData' => [__CLASS__,
'prepareData'],
37 'getEditUrl' => [__CLASS__,
'getEditUrl'],
38 'calculateApplyCoupons' => [__CLASS__,
'calculateApplyCoupons'],
39 'roundBasket' => [__CLASS__,
'roundBasket']
60 if (!isset(self::$discountCache[$discountId]))
62 self::$discountCache[$discountId] =
false;
65 if (!empty($loadData))
67 $loadData[
'LAST_LEVEL_DISCOUNT'] =
'N';
68 if ($loadData[
'CURRENCY'] !=
$params[
'CURRENCY'])
72 'ID' => $discountId,
'TYPE' => $loadData[
'TYPE']
74 self::$discountCache[$discountId] = $loadData;
77 $result = self::$discountCache[$discountId];
80 if (
$result[
'USE_COUPONS'] ==
'Y')
97 if (empty(self::$editUrlTemplate))
99 self::$editUrlTemplate = [
115 if (isset(self::$typeCache[$id]))
117 $type = self::$typeCache[$id];
121 $discountIterator = Catalog\DiscountTable::getList([
122 'select' => [
'ID',
'TYPE'],
123 'filter' => [
'=ID' => $id]
125 $data = $discountIterator->fetch();
129 self::$typeCache[$id] =
$type;
131 unset(
$data, $discountIterator);
134 if (isset(self::$editUrlTemplate[
$type]))
153 if (empty($couponsList))
157 $filteredBasket = array_filter($basket,
'\Bitrix\Catalog\Discount\DiscountManager::basketFilter');
158 if (empty($filteredBasket))
160 $filteredBasket = array_filter($filteredBasket,
'\Bitrix\Catalog\Discount\DiscountManager::lastDiscountFilter');
161 if (empty($filteredBasket))
164 $filteredCoupons = [];
165 foreach ($couponsList as $coupon)
167 if (!isset($coupon[
'COUPON']) || $coupon[
'COUPON'] ==
'')
169 if (!isset($coupon[
'DISCOUNT_ID']) || (
int)$coupon[
'DISCOUNT_ID'] <= 0)
171 $filteredCoupons[] = $coupon[
'COUPON'];
174 if (empty($filteredCoupons))
178 $discountCoupons = [];
180 $couponsIterator = Catalog\DiscountCouponTable::getList([
181 'select' => [
'ID',
'COUPON',
'DISCOUNT_ID',
'TYPE'],
182 'filter' => [
'@COUPON' => $filteredCoupons,
'ACTIVE' =>
'Y']
184 while ($coupon = $couponsIterator->fetch())
186 $discountIds[$coupon[
'DISCOUNT_ID']] =
true;
187 $discountCoupons[$coupon[
'COUPON']] = $coupon[
'COUPON'];
189 $oneRowCoupons[$coupon[
'COUPON']] =
true;
191 unset($coupon, $couponsIterator);
192 if (empty($discountCoupons))
202 $product2Iblock = [];
204 foreach ($filteredBasket as $basketItem)
206 $productId = (int)$basketItem[
'PRODUCT_ID'];
207 $itemIds[$productId] = $productId;
212 'select' => [
'ID',
'IBLOCK_ID'],
213 'filter' => [
'@ID' => $itemIds,
'=ACTIVE' =>
'Y']
215 while ($item = $itemIterator->fetch())
217 $id = (int)$item[
'ID'];
225 unset($item, $itemIterator);
234 \CCatalogDiscount::setProductSectionsCache($elements);
236 \CCatalogDiscount::setDiscountProductCache($elements, [
'IBLOCK_ID' =>
$iblockId,
'GET_BY_ID' =>
'Y']);
241 if (isset(
$params[
'USE_BASE_PRICE']))
245 foreach ($filteredBasket as $basketCode => $basketItem)
247 $productId = (int)$basketItem[
'PRODUCT_ID'];
248 if (!isset($product2Iblock[$productId]))
250 if (empty($discountCoupons))
254 $discountList = \CCatalogDiscount::getDiscount(
256 $product2Iblock[$productId],
264 if (empty($discountList))
270 if (!isset($discountIds[
$discount[
'ID']]))
275 if (empty($itemDiscounts))
279 unset($itemDiscounts);
280 if (!empty($itemsDiscountResult[
'DISCOUNT_LIST']))
283 foreach ($itemsDiscountResult[
'DISCOUNT_LIST'] as
$discount)
287 unset($discountCoupons[
$discount[
'COUPON']]);
291 unset($itemsDiscountResult);
293 unset($basketCode, $basketItem, $basketItem);
296 unset($discountPercentMode);
312 if (empty($basketItem))
334 $basket = array_filter($basket,
'\Bitrix\Catalog\Discount\DiscountManager::basketFilter');
339 $loadBasketCodes = [];
340 foreach ($basket as $basketCode => $basketItem)
342 if (!empty($basketRoundData[$basketCode]))
345 if (isset($basketItem[
'PRICE_TYPE_ID']))
346 $priceTypeId = (int)$basketItem[
'PRICE_TYPE_ID'];
347 if ($priceTypeId <= 0 && isset($basketItem[
'CATALOG_GROUP_ID']))
348 $priceTypeId = (int)$basketItem[
'CATALOG_GROUP_ID'];
349 if ($priceTypeId <= 0 && isset($basketItem[
'PRODUCT_PRICE_ID']))
351 $priceId = (int)$basketItem[
'PRODUCT_PRICE_ID'];
354 $cachedPrice = self::getPriceDataByPriceId($priceId);
355 if (!empty($cachedPrice))
356 $priceTypeId = (int)$cachedPrice[
'CATALOG_GROUP_ID'];
357 if ($priceTypeId <= 0)
359 $loadPriceId[] = $priceId;
360 $loadBasketCodes[$priceId] = $basketCode;
365 $basket[$basketCode][
'PRICE_TYPE_ID'] = $priceTypeId;
366 if ($priceTypeId > 0)
367 $priceTypes[$priceTypeId] = $priceTypeId;
370 unset($priceId, $priceTypeId, $basketCode, $basketItem);
372 if (!empty($loadPriceId))
375 foreach (array_chunk($loadPriceId, 500) as $pageIds)
378 'select' => [
'ID',
'CATALOG_GROUP_ID'],
379 'filter' => [
'@ID' => $pageIds]
383 $id = (int)$row[
'ID'];
384 $priceTypeId = (int)$row[
'CATALOG_GROUP_ID'];
385 if (!isset($loadBasketCodes[$id]))
387 $basket[$loadBasketCodes[$id]][
'PRICE_TYPE_ID'] = $priceTypeId;
388 $priceTypes[$priceTypeId] = $priceTypeId;
390 unset($priceTypeId, $id, $row,
$iterator);
393 unset($loadBasketCodes, $loadPriceId);
395 if (!empty($priceTypes))
396 Catalog\Product\Price::loadRoundRules($priceTypes);
399 foreach ($basket as $basketCode => $basketItem)
401 if (!empty($basketRoundData[$basketCode]))
403 $roundData = $basketRoundData[$basketCode];
407 $roundData = Catalog\Product\Price::searchRoundRule(
408 $basketItem[
'PRICE_TYPE_ID'],
409 $basketItem[
'PRICE'],
410 $basketItem[
'CURRENCY']
414 if (empty($roundData))
419 $result[$basketCode] = self::getRoundResult($basketItem, $roundData);
421 unset($roundData, $basketCode, $basketItem, $basketRoundData);
438 if (empty($product) || !is_array($product))
444 if (!isset($product[
'DISCOUNT_PRICE']))
445 $product[
'DISCOUNT_PRICE'] = 0;
446 $getPercentFromBasePrice = (isset(
$discount[
'USE_BASE_PRICE']) &&
$discount[
'USE_BASE_PRICE'] ==
'Y');
447 $basePrice = (float)(
448 isset($product[
'BASE_PRICE'])
449 ? $product[
'BASE_PRICE']
450 : $product[
'PRICE'] + $product[
'DISCOUNT_PRICE']
459 $getPercentFromBasePrice
467 if ($discountValue +
$discount[
'MAX_VALUE'] <= 0)
468 $discountValue = -
$discount[
'MAX_VALUE'];
470 $product[
'PRICE'] += $discountValue;
471 $product[
'DISCOUNT_PRICE'] -= $discountValue;
472 if (!empty($product[
'DISCOUNT_RESULT']))
474 $product[
'DISCOUNT_RESULT'][
'BASKET'][0][
'RESULT_VALUE'] = (string)abs($discountValue);
475 $product[
'DISCOUNT_RESULT'][
'BASKET'][0][
'RESULT_UNIT'] = $product[
'CURRENCY'];
477 unset($discountValue);
482 $product[
'DISCOUNT_PRICE'] +=
$discount[
'VALUE'];
486 $product[
'DISCOUNT_PRICE'] += ($product[
'PRICE'] -
$discount[
'VALUE']);
501 if (!isset(self::$preloadedPriceData[$productId.
'-'.$catalogGroupId]))
503 self::$preloadedPriceData[$productId.
'-'.$catalogGroupId] =
null;
506 return self::$preloadedPriceData[$productId.
'-'.$catalogGroupId];
522 self::$productProperties[$productId] =
$props;
532 self::$productProperties = [];
542 self::$preloadedProductsData = [];
552 self::$preloadedPriceData = [];
564 if (empty($productIds) || empty($catalogGroups))
566 Collection::normalizeArrayValuesByInt($productIds);
567 if (empty($productIds))
569 Collection::normalizeArrayValuesByInt($catalogGroups);
570 if (empty($catalogGroups))
575 foreach($productIds as
$i => $productId)
577 if(isset(self::$preloadedPriceData[$productId]))
579 unset($productIds[
$i]);
583 if(empty($productIds))
590 'filter' => [
'@PRODUCT_ID' => $productIds,
'@CATALOG_GROUP_ID' => $catalogGroups]
592 while($priceRow = $dbPrice->fetch())
594 self::$preloadedPriceData[$priceRow[
'PRODUCT_ID'].
'-'.$priceRow[
'CATALOG_GROUP_ID']] = $priceRow;
598 private static function fillByPreloadedPrices(
array &$productData,
array $priceList)
600 foreach ($productData as $productId => $product)
602 foreach (self::$preloadedPriceData as $priceData)
604 if ($priceData[
'PRODUCT_ID'] != $productId)
609 if(!in_array($priceData[
'ID'], $priceList))
614 $productData[$productId][
'CATALOG_GROUP_ID'] = $priceData[
'CATALOG_GROUP_ID'];
628 if (empty($productIds) || empty($userGroups))
630 Collection::normalizeArrayValuesByInt($productIds,
true);
631 if (empty($productIds))
633 Collection::normalizeArrayValuesByInt($userGroups,
true);
634 if (empty($userGroups))
637 if(self::$saleIncluded ===
null)
638 self::$saleIncluded = Loader::includeModule(
'sale');
640 if(!self::$saleIncluded)
651 Collection::normalizeArrayValuesByInt($discountIds,
true);
654 if(!$entityList || empty($entityList[
'catalog']))
670 $productData = array_fill_keys($productIds, []);
671 if(empty($iblockData[
'iblockElement']))
679 if(!isset(self::$preloadedProductsData[$cacheKeyForEntityList]))
681 self::$preloadedProductsData[$cacheKeyForEntityList] = [];
684 foreach($productData as $productId =>
$data)
686 self::$preloadedProductsData[$cacheKeyForEntityList][$productId] =
$data;
700 $orderData =
$event->getParameter(
'ORDER');
701 $entityList =
$event->getParameter(
'ENTITY');
704 if (empty($orderData) || !is_array($orderData))
710 if (!isset($orderData[
'BASKET_ITEMS']) || !is_array($orderData[
'BASKET_ITEMS']))
718 && !empty($orderData[
'BASKET_ITEMS'])
722 if (empty($entityData))
732 $basket = array_filter($orderData[
'BASKET_ITEMS'],
'\Bitrix\Catalog\Discount\DiscountManager::basketFilter');
735 foreach ($basket as $basketCode => $basketItem)
737 $basketItem[
'PRODUCT_ID'] = (int)$basketItem[
'PRODUCT_ID'];
738 $productList[] = $basketItem[
'PRODUCT_ID'];
739 if (!isset($productMap[$basketItem[
'PRODUCT_ID']]))
741 $productMap[$basketItem[
'PRODUCT_ID']] = [];
743 $productMap[$basketItem[
'PRODUCT_ID']][] = &$basket[$basketCode];
745 if (isset($basketItem[
'PRODUCT_PRICE_ID']))
747 $priceList[] = $basketItem[
'PRODUCT_PRICE_ID'];
750 unset($basketItem, $basketCode);
752 if(isset(self::$preloadedProductsData[$cacheKeyForEntityList]))
754 $preloadedProductIds = array_keys(self::$preloadedProductsData[$cacheKeyForEntityList]);
755 $loadedProductIds = array_intersect($productList, $preloadedProductIds);
757 $productList = array_diff($productList, $preloadedProductIds);
760 $productData = array_fill_keys($productList, []);
770 if (!empty($iblockData[
'iblockElement']))
775 if(!empty($loadedProductIds))
777 foreach($loadedProductIds as $loadedProductId)
779 $productData[$loadedProductId] = self::$preloadedProductsData[$cacheKeyForEntityList][$loadedProductId];
782 if(!empty($entityData[
'priceFields']))
784 self::fillByPreloadedPrices($productData, $priceList);
790 foreach ($productData as $product =>
$data)
792 if (empty($productMap[$product]))
794 foreach ($productMap[$product] as &$basketItem)
795 $basketItem[
'CATALOG'] =
$data;
798 unset($product,
$data);
800 $resultData[
'BASKET_ITEMS'] = $basket;
802 unset($basket, $productData, $productMap, $productList);
809 unset($process, $resultData);
816 return md5(serialize($entityList));
823 Collection::normalizeArrayValuesByInt($productIds);
824 if (empty($productIds))
826 $key = md5(implode(
'|', $productIds));
828 if(!isset($cache[
$key]))
830 $extendedList = array_combine($productIds, $productIds);
831 foreach(\CCatalogSku::getOffersList($productIds) as $mainProduct)
833 foreach(array_keys($mainProduct) as $offerId)
835 if(!isset($extendedList[$offerId]))
837 $extendedList[$offerId] = $offerId;
842 $cache[
$key] = $extendedList;
858 (isset($basketItem[
'MODULE']) && $basketItem[
'MODULE'] ==
'catalog')
859 || (isset($basketItem[
'MODULE_ID']) && $basketItem[
'MODULE_ID'] ==
'catalog')
861 && (isset($basketItem[
'PRODUCT_ID']) && (
int)$basketItem[
'PRODUCT_ID'] > 0)
874 !isset($basketItem[
'LAST_DISCOUNT'])
875 || $basketItem[
'LAST_DISCOUNT'] !=
'Y'
891 $select[
'CONDITIONS_LIST'] =
true;
901 $select[
'LAST_DISCOUNT'] =
true;
912 $select[
'MAX_DISCOUNT'] =
true;
922 $select[
'MAX_DISCOUNT'] =
true;
924 $selectKeys = array_keys(
$select);
928 $discountIterator = Catalog\DiscountTable::getList([
929 'select' => $selectKeys,
930 'filter' => [
'=ID' => $id]
932 $loadData = $discountIterator->fetch();
933 if (empty($loadData))
946 unset($loadData, $discountIterator);
951 if (array_key_exists(
'HANDLERS',
$discount))
962 $helper = $conn->getSqlHelper();
964 $moduleIterator = $conn->query(
965 'select MODULE_ID from '.$helper->quote(
'b_catalog_discount_module').
' where '.$helper->quote(
'DISCOUNT_ID').
' = '.$id
967 while ($module = $moduleIterator->fetch())
968 $discount[
'MODULES'][] = $module[
'MODULE_ID'];
969 unset($module, $moduleIterator, $helper, $conn);
970 if (!in_array(
'catalog',
$discount[
'MODULES']))
973 self::$typeCache[$id] =
$discount[
'TYPE'];
988 'iblockFields' => [],
990 'iblockProperties' => [],
991 'iblockPropertiesMap' => [],
992 'catalogFields' => [],
996 if (!is_array($entityList))
999 if (empty($entityList[
'catalog']))
1002 if (!empty($entityList[
'catalog']))
1004 if (!empty($entityList[
'catalog'][
'ELEMENT']) && is_array($entityList[
'catalog'][
'ELEMENT']))
1006 foreach ($entityList[
'catalog'][
'ELEMENT'] as
$entity)
1008 if (
$entity[
'FIELD_ENTITY'] ==
'SECTION_ID')
1017 if (!empty($entityList[
'catalog'][
'ELEMENT_PROPERTY']) && is_array($entityList[
'catalog'][
'ELEMENT_PROPERTY']))
1019 foreach ($entityList[
'catalog'][
'ELEMENT_PROPERTY'] as
$entity)
1021 $propertyData = explode(
':',
$entity[
'FIELD_TABLE']);
1022 if (!is_array($propertyData) ||
count($propertyData) != 2)
1024 $iblock = (int)$propertyData[0];
1025 $property = (int)$propertyData[1];
1026 unset($propertyData);
1037 if (!empty($entityList[
'catalog'][
'PRODUCT']) && is_array($entityList[
'catalog'][
'PRODUCT']))
1039 foreach ($entityList[
'catalog'][
'PRODUCT'] as
$entity)
1044 if (!empty($entityList[
'catalog'][
'PRICE']) && is_array($entityList[
'catalog'][
'PRICE']))
1046 foreach ($entityList[
'catalog'][
'PRICE'] as
$entity)
1064 'iblockElement' => [],
1066 'skuIblockList' => []
1069 if (empty($productList))
1073 'select' => [
'ID',
'IBLOCK_ID'],
1074 'filter' => [
'@ID' => $productList]
1076 while ($element = $elementIterator->fetch())
1078 $element[
'ID'] = (int)$element[
'ID'];
1079 $element[
'IBLOCK_ID'] = (int)$element[
'IBLOCK_ID'];
1080 if (!isset(
$result[
'iblockElement'][$element[
'IBLOCK_ID']]))
1081 $result[
'iblockElement'][$element[
'IBLOCK_ID']] = [];
1082 $result[
'iblockElement'][$element[
'IBLOCK_ID']][] = $element[
'ID'];
1084 unset($element, $elementIterator);
1085 if (!empty(
$result[
'iblockElement']))
1090 'select' => [
'IBLOCK_ID',
'PRODUCT_IBLOCK_ID',
'SKU_PROPERTY_ID'],
1091 'filter' => [
'@IBLOCK_ID' =>
$result[
'iblockList'],
'!=PRODUCT_IBLOCK_ID' => 0]
1093 while ($sku = $skuIterator->fetch())
1095 $sku[
'IBLOCK_ID'] = (int)$sku[
'IBLOCK_ID'];
1096 $sku[
'PRODUCT_IBLOCK_ID'] = (int)$sku[
'PRODUCT_IBLOCK_ID'];
1097 $sku[
'SKU_PROPERTY_ID'] = (int)$sku[
'SKU_PROPERTY_ID'];
1098 $result[
'skuIblockList'][$sku[
'IBLOCK_ID']] = $sku;
1100 unset($sku, $skuIterator);
1115 $entityData[
'needProperties'] = [];
1116 if (!empty($entityData[
'iblockProperties']) && !empty($iblockData[
'iblockList']))
1118 foreach ($iblockData[
'iblockList'] as
$iblock)
1120 if (!empty($entityData[
'iblockProperties'][
$iblock]))
1121 $entityData[
'needProperties'][
$iblock] = $entityData[
'iblockProperties'][
$iblock];
1125 if (!empty($iblockData[
'skuIblockList']))
1127 foreach ($iblockData[
'skuIblockList'] as $skuData)
1129 if (!isset($entityData[
'needProperties'][$skuData[
'IBLOCK_ID']]))
1130 $entityData[
'needProperties'][$skuData[
'IBLOCK_ID']] = [];
1131 $entityData[
'needProperties'][$skuData[
'IBLOCK_ID']][] = $skuData[
'SKU_PROPERTY_ID'];
1132 $entityData[
'iblockPropertiesMap'][$skuData[
'IBLOCK_ID']][$skuData[
'SKU_PROPERTY_ID']] =
'PARENT_ID';
1133 if (!empty($entityData[
'iblockProperties'][$skuData[
'PRODUCT_IBLOCK_ID']]))
1134 $entityData[
'needProperties'][$skuData[
'PRODUCT_IBLOCK_ID']] = $entityData[
'iblockProperties'][$skuData[
'PRODUCT_IBLOCK_ID']];
1150 protected static function convertProperties(&$productData, $propertyValues, $entityData, $iblockData): void
1152 if (empty($productData) || !is_array($productData))
1154 if (empty($propertyValues) || !is_array($propertyValues))
1156 if (empty($entityData) || !is_array($entityData))
1158 if (empty($iblockData) || !is_array($iblockData))
1161 if (empty($entityData[
'needProperties']) || !is_array($entityData[
'needProperties']))
1163 $propertyIblocks = array_keys($entityData[
'needProperties']);
1164 foreach ($propertyIblocks as
$iblock)
1166 if (empty($iblockData[
'iblockElement'][
$iblock]))
1168 $propertyMap = $entityData[
'iblockPropertiesMap'][
$iblock];
1169 foreach ($iblockData[
'iblockElement'][
$iblock] as $element)
1171 if (empty($propertyValues[$element]))
1173 foreach ($propertyValues[$element] as $property)
1175 if (empty($property) || empty($property[
'ID']))
1179 $property[
'ID'] = (int)$property[
'ID'];
1180 if (empty($propertyMap[$property[
'ID']]))
1182 $propertyKey = $propertyMap[$property[
'ID']];
1186 if ($property[
'MULTIPLE'] ==
'N')
1188 if (!empty($property[
'USER_TYPE']))
1190 switch($property[
'USER_TYPE'])
1194 $property[
'VALUE'] = (string)$property[
'VALUE'];
1195 if ($property[
'VALUE'] !=
'')
1197 $propertyFormat =
false;
1198 if ($property[
'USER_TYPE'] ==
'DateTime')
1200 if (defined(
'FORMAT_DATETIME'))
1205 if (defined(
'FORMAT_DATE'))
1208 $intStackTimestamp = (int)$property[
'VALUE'];
1209 $property[
'VALUE'] = (
1210 $intStackTimestamp.
'!' != $property[
'VALUE'].
'!'
1212 : $intStackTimestamp
1215 $value = $property[
'VALUE'];
1222 switch ($property[
'PROPERTY_TYPE'])
1225 $property[
'VALUE_ENUM_ID'] = (int)$property[
'VALUE_ENUM_ID'];
1226 $value = ($property[
'VALUE_ENUM_ID'] > 0 ? $property[
'VALUE_ENUM_ID'] : -1);
1230 $property[
'VALUE'] = (int)$property[
'VALUE'];
1231 $value = ($property[
'VALUE'] > 0 ? $property[
'VALUE'] : -1);
1234 $value = $property[
'VALUE'];
1242 if (!empty($property[
'USER_TYPE']))
1244 switch($property[
'USER_TYPE'])
1248 if (!empty($property[
'VALUE']) && is_array($property[
'VALUE']))
1250 $propertyFormat =
false;
1251 if ($property[
'USER_TYPE'] ==
'DateTime')
1253 if (defined(
'FORMAT_DATETIME'))
1258 if (defined(
'FORMAT_DATE'))
1261 foreach ($property[
'VALUE'] as &$oneValue)
1263 $oneValue = (string)$oneValue;
1264 if (
'' != $oneValue)
1266 $intStackTimestamp = (int)$oneValue;
1267 if ($intStackTimestamp.
'!' != $oneValue.
'!')
1270 $oneValue = $intStackTimestamp;
1272 $value[] = $oneValue;
1274 unset($oneValue, $propertyFormat);
1282 switch ($property[
'PROPERTY_TYPE'])
1285 if (!empty($property[
'VALUE_ENUM_ID']) && is_array($property[
'VALUE_ENUM_ID']))
1287 foreach ($property[
'VALUE_ENUM_ID'] as &$oneValue)
1289 $oneValue = (int)$oneValue;
1291 $value[] = $oneValue;
1300 if (!empty($property[
'VALUE']) && is_array($property[
'VALUE']))
1302 foreach ($property[
'VALUE'] as &$oneValue)
1304 $oneValue = (int)$oneValue;
1306 $value[] = $oneValue;
1314 $value = $property[
'VALUE'];
1319 $productData[$element][$propertyKey] = (is_array($value) ? $value : [$value]);
1338 if (
$iblockId <= 0 || empty($itemIds) || empty($propertyIds))
1344 'select' => [
'ID',
'PROPERTY_TYPE',
'MULTIPLE',
'USER_TYPE'],
1345 'filter' => [
'=IBLOCK_ID' =>
$iblockId,
'@ID' => $propertyIds]
1349 $id = (int)$row[
'ID'];
1350 $multiple = ($row[
'MULTIPLE'] ==
'Y');
1355 'VALUE_ENUM' =>
null,
1356 'VALUE_XML_ID' =>
null,
1357 'VALUE_SORT' =>
null,
1359 'PROPERTY_VALUE_ID' =>
false,
1360 'DESCRIPTION' =>
false,
1361 '~DESCRIPTION' =>
false,
1369 'VALUE_ENUM' =>
null,
1370 'VALUE_XML_ID' =>
null,
1371 'VALUE_SORT' =>
null,
1373 'PROPERTY_VALUE_ID' =>
null,
1374 'DESCRIPTION' =>
'',
1375 '~DESCRIPTION' =>
'',
1381 $row[
'VALUE_ENUM_ID'] = ($multiple ?
false :
null);
1384 $propertyList[$id] = $row;
1388 foreach ($itemIds as $id)
1390 if (!empty($propertyValues[$id]))
1394 $propertyValues[$id] = $propertyList;
1396 unset($propertyList);
1410 if (empty($iblockData[
'skuIblockList']))
1412 if (empty($productData) || !is_array($productData))
1416 $parentIblockData = [
1417 'iblockElement' => [],
1420 if (!empty($entityData[
'iblockFields']))
1422 foreach ($entityData[
'iblockFields'] as &$value)
1423 $value =
'PARENT_'.$value;
1425 if (array_key_exists(
'catalogFields', $entityData))
1426 unset($entityData[
'catalogFields']);
1427 foreach ($iblockData[
'skuIblockList'] as $skuData)
1429 if (empty($iblockData[
'iblockElement'][$skuData[
'IBLOCK_ID']]))
1431 foreach ($iblockData[
'iblockElement'][$skuData[
'IBLOCK_ID']] as $element)
1433 if (empty($productData[$element][
'PARENT_ID']))
1436 is_array($productData[$element][
'PARENT_ID'])
1437 ? current($productData[$element][
'PARENT_ID'])
1438 : $productData[$element][
'PARENT_ID']
1442 if (!isset($parentMap[$parentId]))
1443 $parentMap[$parentId] = [];
1444 $parentMap[$parentId][] = $element;
1445 $parentData[$parentId] = [];
1446 if (!isset($parentIblockData[
'iblockElement'][$skuData[
'PRODUCT_IBLOCK_ID']]))
1447 $parentIblockData[
'iblockElement'][$skuData[
'PRODUCT_IBLOCK_ID']] = [];
1448 $parentIblockData[
'iblockElement'][$skuData[
'PRODUCT_IBLOCK_ID']][] = $parentId;
1450 unset($parentId, $element);
1453 if (empty($parentIblockData[
'iblockElement']))
1455 $parentIblockData[
'iblockList'] = array_keys($parentIblockData[
'iblockElement']);
1459 foreach ($parentData as $parentId =>
$data)
1461 $parentSections = [];
1462 if ($entityData[
'sections'])
1464 $parentSections =
$data[
'SECTION_ID'];
1465 unset(
$data[
'SECTION_ID']);
1467 if(!isset($parentMap[$parentId]))
1471 foreach ($parentMap[$parentId] as $element)
1473 $productData[$element] = array_merge($productData[$element],
$data);
1474 if ($entityData[
'sections'])
1476 $productData[$element][
'SECTION_ID'] = (
1477 empty($productData[
'SECTION_ID'])
1479 : array_merge($productData[$element][
'SECTION_ID'], $parentSections)
1483 unset($element, $parentSections);
1485 unset($parentId,
$data);
1490 if (isset(
$fields[
'DATE_ACTIVE_FROM']))
1493 unset(
$fields[
'DATE_ACTIVE_FROM']);
1495 if (isset(
$fields[
'DATE_ACTIVE_TO']))
1498 unset(
$fields[
'DATE_ACTIVE_TO']);
1503 \CTimeZone::Disable();
1505 'select' => array_merge([
'ID'], array_keys(
$fields)),
1506 'filter' => [
'@ID' => $productIds]
1508 while ($element = $elementIterator->fetch())
1510 $element[
'ID'] = (int)$element[
'ID'];
1514 $productData[$element[
'ID']][$alias] = $element[
$key]->getTimestamp();
1516 $productData[$element[
'ID']][$alias] = $element[
$key];
1519 \CTimeZone::Enable();
1521 return $productData;
1526 $productSection = array_fill_keys($productIds, []);
1527 $elementSectionIterator = Iblock\SectionElementTable::getList([
1529 'filter' => [
'@IBLOCK_ELEMENT_ID' => $productIds]
1531 while ($elementSection = $elementSectionIterator->fetch())
1533 $elementSection[
'IBLOCK_ELEMENT_ID'] = (int)$elementSection[
'IBLOCK_ELEMENT_ID'];
1534 $elementSection[
'IBLOCK_SECTION_ID'] = (int)$elementSection[
'IBLOCK_SECTION_ID'];
1535 $elementSection[
'ADDITIONAL_PROPERTY_ID'] = (int)$elementSection[
'ADDITIONAL_PROPERTY_ID'];
1536 if ($elementSection[
'ADDITIONAL_PROPERTY_ID'] > 0)
1538 $productSection[$elementSection[
'IBLOCK_ELEMENT_ID']][$elementSection[
'IBLOCK_SECTION_ID']] =
true;
1539 $parentSectionIterator = \CIBlockSection::GetNavChain(0, $elementSection[
'IBLOCK_SECTION_ID'], [
'ID']);
1540 while ($parentSection = $parentSectionIterator->fetch())
1542 $parentSection[
'ID'] = (int)$parentSection[
'ID'];
1543 $productSection[$elementSection[
'IBLOCK_ELEMENT_ID']][$parentSection[
'ID']] =
true;
1545 unset($parentSection, $parentSectionIterator);
1547 unset($elementSection, $elementSectionIterator);
1549 return $productSection;
1557 'select' => array_merge([
'ID'], array_keys(
$fields)),
1558 'filter' => [
'@ID' => $productIds]
1560 while ($product = $productIterator->fetch())
1562 $product[
'ID'] = (int)$product[
'ID'];
1565 $productData[$product[
'ID']][$alias] = $product[
$key];
1569 return $productData;
1574 $propertyValues = array_fill_keys($productIds, []);
1575 foreach ($entityData[
'needProperties'] as
$iblock => $propertyList)
1577 if (empty($iblockData[
'iblockElement'][
$iblock]))
1582 $needToLoad = array_fill_keys($iblockData[
'iblockElement'][
$iblock],
true);
1583 if(self::$productProperties)
1585 foreach ($iblockData[
'iblockElement'][
$iblock] as $productId)
1588 foreach ($propertyList as $prop)
1590 $propData = self::getCachedProductProperty($productId, $prop);
1591 if (!empty($propData))
1593 $propertyValues[$productId][$propData[
'ID']] = $propData;
1605 $propertyValues[$productId] = [];
1609 unset($needToLoad[$productId]);
1615 if(!empty($needToLoad))
1617 $needProductIds = array_keys($needToLoad);
1618 sort($needProductIds);
1619 $iblockPropertyValues = array_fill_keys($needProductIds, []);
1621 \CTimeZone::Disable();
1622 foreach (array_chunk($needProductIds, 500) as $pageIds)
1629 \CIBlockElement::GetPropertyValuesArray(
1630 $iblockPropertyValues,
1633 [
'ID' => $propertyList],
1635 'USE_PROPERTY_ID' =>
'Y',
1636 'PROPERTY_FIELDS' => [
'ID',
'PROPERTY_TYPE',
'MULTIPLE',
'USER_TYPE']
1639 foreach ($iblockPropertyValues as $productId =>
$data)
1643 $propertyValues[$productId] =
$data;
1644 unset($needToLoad[$productId]);
1647 unset($productId,
$data);
1650 \CTimeZone::Enable();
1651 unset($iblockPropertyValues, $needProductIds);
1653 if (!empty($needToLoad))
1672 protected static function getProductData(&$productData, $entityData, $iblockData): void
1674 if (!empty($iblockData[
'iblockElement']))
1676 $productList = array_keys($productData);
1677 if (!empty($entityData[
'iblockFields']))
1679 foreach(self::loadIblockFields($productList, $entityData[
'iblockFields']) as $productId =>
$fields)
1681 $productData[$productId] = (
1682 empty($productData[$productId])
1684 : array_merge($productData[$productId],
$fields)
1689 if ($entityData[
'sections'])
1691 foreach(self::loadSections($productList) as $element => $sections)
1693 $productData[$element][
'SECTION_ID'] = array_keys($sections);
1696 if (!empty($entityData[
'needProperties']))
1700 if (!empty($entityData[
'catalogFields']))
1702 foreach(self::loadCatalogFields($productList, $entityData[
'catalogFields']) as $productId =>
$fields)
1704 $productData[$productId] = (
1705 empty($productData[$productId])
1707 : array_merge($productData[$productId],
$fields)
1712 if (!empty($entityData[
'priceFields']) && !empty($entityData[
'priceData']))
1714 foreach($entityData[
'priceData'] as $productId => $priceId)
1716 $productData[$productId][
'CATALOG_GROUP_ID'] = $priceId;
1718 unset($product, $productIterator);
1721 if (!empty($iblockData[
'skuIblockList']))
1740 'USE_BASE_PRICE' =>
$params[
'USE_BASE_PRICE']
1745 $action =
'\Bitrix\Catalog\Discount\DiscountManager::applyDiscount('.$params[
'BASKET_ITEM'].
', '.var_export(
$data,
true).
');';
1746 $discount[
'APPLICATION'] =
'function (&'.$params[
'BASKET_ITEM'].
'){'.
$action.
'};';
1750 if (self::$saleIncluded ===
null)
1751 self::$saleIncluded = Loader::includeModule(
'sale');
1752 if (!self::$saleIncluded)
1776 $descr[
'LIMIT_UNIT'] =
$discount[
'CURRENCY'];
1777 $descr[
'LIMIT_VALUE'] =
$discount[
'MAX_VALUE'];
1783 $descr[
'VALUE_UNIT'] =
$discount[
'CURRENCY'];
1787 $descr[
'VALUE_UNIT'] =
$discount[
'CURRENCY'];
1791 if ($descrResult !==
null)
1799 unset($descrResult, $descr,
$type);
1804 $entityData[
'priceData'] = [];
1805 if(empty($entityData[
'priceFields']) || empty($priceIds))
1812 'select' => [
'PRODUCT_ID',
'CATALOG_GROUP_ID'],
1813 'filter' => [
'@ID' => $priceIds],
1815 while($price = $priceList->fetch())
1817 if(!isset($priceData[$price[
'PRODUCT_ID']]))
1819 $priceData[$price[
'PRODUCT_ID']] = [];
1821 $priceData[$price[
'PRODUCT_ID']] = $price[
'CATALOG_GROUP_ID'];
1824 $entityData[
'priceData'] = $priceData;
1836 if (self::$saleIncluded ===
null)
1837 self::$saleIncluded = Loader::includeModule(
'sale');
1838 if (self::$saleIncluded)
1852 private static function getRoundResult(
array $basketItem,
array $roundData):
array
1855 'ROUND_RULE' => $roundData
1858 $basketItem[
'PRICE'],
1859 $roundData[
'ROUND_PRECISION'],
1860 $roundData[
'ROUND_TYPE']
1863 if (isset($basketItem[
'BASE_PRICE']))
1865 $result[
'DISCOUNT_PRICE'] = $basketItem[
'BASE_PRICE'] -
$result[
'PRICE'];
1869 if (!isset(
$result[
'DISCOUNT_PRICE']))
1870 $result[
'DISCOUNT_PRICE'] = 0;
1871 $result[
'DISCOUNT_PRICE'] += ($basketItem[
'PRICE'] -
$result[
'PRICE']);
1877 private static function getPriceDataByPriceId($priceId)
1879 foreach(self::$preloadedPriceData as $priceData)
1881 if($priceData[
'ID'] == $priceId)
1890 private static function getCachedProductProperty($productId, $propertyId)
1892 if(!isset(self::$productProperties[$productId]))
1897 foreach(self::$productProperties[$productId] as
$props)
1899 if(
$props[
'ID'] == $propertyId)
const CATALOG_VALUE_PRECISION
if(!is_object($USER)||! $USER->IsAuthorized()) $userId
static catalogDiscountManager(Main\Event $event)
static $productProperties
static prepareData(array $discount, $params=[])
static extendOrderData(Main\Event $event)
static fillProperties(array &$productData, array $productIds, array $iblockData, array $entityData)
static extendProductIdsToOffer(array $productIds)
static loadFromDatabase(int $id, array $discount)
static loadSections(array $productIds)
static lastDiscountFilter(array $basketItem)
static getProductIblocks(array $productList)
static createSaleAction(&$discount, $params)
static prepareEntity($entityList)
static getCacheKeyForEntityList(array $entityList)
static fillProductPropertyList(array &$entityData, array $iblockData)
static clearProductPricesCache()
static roundPrice(array $basketItem, array $roundData=[])
static roundBasket(array $basket, array $basketRoundData=[], array $order=[])
static basketFilter(array $basketItem)
static $preloadedProductsData
static loadCatalogFields(array $productIds, array $fields)
static clearProductPropertiesCache()
static clearProductsCache()
static calculateApplyCoupons(array $couponsList, array $basket, array $params)
static getParentProducts(&$productData, $entityData, $iblockData)
static getProductData(&$productData, $entityData, $iblockData)
static loadIblockFields(array $productIds, array $fields)
static getPriceDataByProductId(int $productId, int $catalogGroupId)
static fillProductPriceList(&$entityData, $priceIds)
static convertProperties(&$productData, $propertyValues, $entityData, $iblockData)
static applyDiscount(&$product, $discount)
static preloadPriceData(array $productIds, array $catalogGroups)
static preloadProductDataToExtendOrder(array $productIds, array $userGroups)
static roundValue($value, string $currency)
static $preloadedPriceData
static getEditUrl(array $discount)
static fillEmptyProperties(array &$propertyValues, int $iblockId, array $itemIds, array $propertyIds)
static setProductPropertiesCache($productId, $props)
static convertCurrency(&$discount, $currency)
static getConnection($name="")
static getList(array $parameters=array())
static sortByColumn(array &$array, $columns, $callbacks='', $defaultValueIfNotSetValue=null, $preserveKeys=false)
static getUserGroupIds($userId)
static roundValue($value, $currency)
static setUseBasePrice($useBasePrice)
static getDiscountDescription(array $discount)
static applyDiscountList($price, $currency, &$discountList)
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
if(! $catalogEdit->isSuccess()) $iblock
MakeTimeStamp($datetime, $format=false)
if(empty($signedUserToken)) $key
</p ></td >< td valign=top style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0cm 2.0pt 0cm 2.0pt;height:9.0pt'>< p class=Normal align=center style='margin:0cm;margin-bottom:.0001pt;text-align:center;line-height:normal'>< a name=ТекстовоеПоле54 ></a ><?=($taxRate > count( $arTaxList) > 0) ? $taxRate."%"
if($inWords) echo htmlspecialcharsbx(Number2Word_Rus(roundEx($totalVatSum $params['CURRENCY']