54 protected static bool $init =
false;
77 'DISCOUNT_ACTIVE_FROM',
109 public static function initUseMode($mode = self::MODE_CLIENT, $params = [])
112 if (!is_array($params))
116 self::$checkActivity =
true;
117 self::$userId =
null;
118 self::$orderId =
null;
119 self::$allowedSave =
false;
120 self::$useOrderCoupons =
true;
126 if (!isset($params[
'userId']) || (int)$params[
'userId'] < 0)
130 if (isset($params[
'orderId']))
134 if (empty(self::$errors))
136 self::$userId = (int)$params[
'userId'];
137 self::$orderId =
null;
138 self::$allowedSave =
true;
140 if (isset($params[
'oldUserId']))
147 if (!isset($params[
'userId']) || (
int)$params[
'userId'] < 0)
151 if (!isset($params[
'orderId']) || (
int)$params[
'orderId'] <= 0)
155 if (empty(self::$errors))
157 self::$userId = (int)$params[
'userId'];
158 self::$orderId = (int)$params[
'orderId'];
159 self::$allowedSave =
true;
161 if (isset($params[
'oldUserId']))
170 if (isset($params[
'userId']) && (
int)$params[
'userId'] >= 0)
172 self::$userId = (int)$params[
'userId'];
178 if (self::isSuccess())
180 self::$allowedSave =
true;
186 isset($params[
'userId']) && (int)$params[
'userId'] >= 0
187 ? (
int)$params[
'userId']
188 : \CSaleUser::GetAnonymousUserID()
216 return (self::$useMode === self::MODE_CLIENT);
226 return (self::$useMode === self::MODE_MANAGER || self::$useMode === self::MODE_ORDER);
236 return (self::$useMode === self::MODE_EXTERNAL);
246 if ((self::$userId ===
null || self::$userId === 0) && self::usedByClient())
248 self::$userId =
null;
272 protected static function getSession(): ?
Session
276 if (!$session->isAccessible())
278 self::$errors[] =
Loc::getMessage(
'BX_SALE_DCM_ERR_SESSION_NOT_ACCESSIBLE');
293 return empty(self::$errors);
324 $extendedMode = ($extendedMode ===
true);
328 self::STATUS_NOT_FOUND =>
Loc::getMessage(
'BX_SALE_DCM_STATUS_NOT_FOUND'),
330 self::STATUS_NOT_APPLYED =>
Loc::getMessage(
'BX_SALE_DCM_STATUS_NOT_APPLYED'),
353 $extendedMode = ($extendedMode ===
true);
357 self::COUPON_CHECK_OK =>
Loc::getMessage(
'BX_SALE_DCM_COUPON_CHECK_OK'),
358 self::COUPON_CHECK_NOT_FOUND =>
Loc::getMessage(
'BX_SALE_DCM_COUPON_CHECK_NOT_FOUND'),
359 self::COUPON_CHECK_NO_ACTIVE =>
Loc::getMessage(
'BX_SALE_DCM_COUPON_CHECK_NO_ACTIVE'),
360 self::COUPON_CHECK_RANGE_ACTIVE_FROM =>
Loc::getMessage(
'BX_SALE_DCM_COUPON_CHECK_RANGE_ACTIVE_FROM'),
361 self::COUPON_CHECK_RANGE_ACTIVE_TO =>
Loc::getMessage(
'BX_SALE_DCM_COUPON_CHECK_RANGE_ACTIVE_TO'),
362 self::COUPON_CHECK_NO_ACTIVE_DISCOUNT =>
Loc::getMessage(
'BX_SALE_DCM_COUPON_CHECK_NO_ACTIVE_DISCOUNT'),
363 self::COUPON_CHECK_RANGE_ACTIVE_FROM_DISCOUNT =>
Loc::getMessage(
'BX_SALE_DCM_COUPON_CHECK_RANGE_ACTIVE_FROM_DISCOUNT'),
364 self::COUPON_CHECK_RANGE_ACTIVE_TO_DISCOUNT =>
Loc::getMessage(
'BX_SALE_DCM_COUPON_CHECK_RANGE_ACTIVE_TO_DISCOUNT'),
365 self::COUPON_CHECK_BAD_USER_ID =>
Loc::getMessage(
'BX_SALE_DCM_COUPON_CHECK_BAD_USER_ID'),
366 self::COUPON_CHECK_ALREADY_MAX_USED =>
Loc::getMessage(
'BX_SALE_DCM_COUPON_CHECK_ALREADY_MAX_USED'),
367 self::COUPON_CHECK_UNKNOWN_TYPE =>
Loc::getMessage(
'BX_SALE_DCM_COUPON_CHECK_UNKNOWN_TYPE'),
368 self::COUPON_CHECK_CORRUPT_DATA =>
Loc::getMessage(
'BX_SALE_DCM_COUPON_CHECK_CORRUPT_DATA'),
369 self::COUPON_CHECK_NOT_APPLIED =>
Loc::getMessage(
'BX_SALE_DCM_COUPON_CHECK_NOT_APPLIED'),
399 if (isset($codes[$code]))
401 return $codes[$code];
415 if ($state !==
true && $state !==
false)
419 self::$useOrderCoupons = $state;
439 self::$allowCouponStorage++;
449 self::$allowCouponStorage--;
459 return (self::$allowCouponStorage < 0);
476 public static function init($mode = self::MODE_CLIENT, $params = [], $clearStorage =
false)
482 self::$onlySaleDiscount =
null;
483 self::$couponTypes = Internals\DiscountCouponTable::getCouponTypes(
true);
484 self::$couponIndex = 0;
485 self::$lockedCoupons = [];
489 if (!self::isSuccess())
493 if (self::$useMode !== self::MODE_SYSTEM)
495 $session = self::getSession();
503 switch (self::$useMode)
508 !empty($session[self::STORAGE_CLIENT_COUPONS])
509 && is_array($session[self::STORAGE_CLIENT_COUPONS])
517 !empty($session[self::STORAGE_MANAGER_COUPONS])
518 && !empty($session[self::STORAGE_MANAGER_COUPONS][self::$userId])
519 && is_array($session[self::STORAGE_MANAGER_COUPONS][self::$userId])
528 !empty($session[self::STORAGE_MANAGER_COUPONS])
529 && !empty($session[self::STORAGE_MANAGER_COUPONS][self::$userId])
530 && is_array($session[self::STORAGE_MANAGER_COUPONS][self::$userId])
537 if (!empty($couponsList))
542 if (self::$useMode === self::MODE_ORDER)
564 public static function reInit($mode = self::MODE_CLIENT, $params = [], $clearStorage =
false)
566 if (self::isFrozenCouponStorage())
581 return !empty(self::$coupons);
590 public static function add($coupon)
596 if (self::$useMode === self::MODE_SYSTEM || !self::isSuccess())
601 $coupon = trim((
string)$coupon);
606 if (!isset(self::$coupons[$coupon]))
609 if (!isset(self::$coupons[$couponData[
'COUPON']]))
613 self::$coupons[$couponData[
'COUPON']] = $couponData;
614 self::$couponIndex++;
616 $event =
new Main\Event(
'sale', self::EVENT_ON_COUPON_ADD, $couponData);
619 if (self::$coupons[$couponData[
'COUPON']][
'MODE'] === self::COUPON_MODE_FULL)
621 return (self::$coupons[$couponData[
'COUPON']][
'STATUS'] != self::STATUS_NOT_FOUND);
626 self::$coupons[$couponData[
'COUPON']][
'STATUS'] != self::STATUS_NOT_FOUND
627 && self::$coupons[$couponData[
'COUPON']][
'STATUS'] != self::STATUS_FREEZE
633 if (self::$coupons[$coupon][
'MODE'] === self::COUPON_MODE_FULL)
635 return (self::$coupons[$coupon][
'STATUS'] != self::STATUS_NOT_FOUND);
640 self::$coupons[$coupon][
'STATUS'] != self::STATUS_NOT_FOUND
641 && self::$coupons[$coupon][
'STATUS'] != self::STATUS_FREEZE
653 public static function delete($coupon)
659 if (self::$useMode === self::MODE_SYSTEM || !self::isSuccess())
664 $coupon = trim((
string)$coupon);
670 if (isset(self::$coupons[$coupon]))
672 $couponData = self::$coupons[$coupon];
673 unset(self::$coupons[$coupon]);
679 if (isset(self::$coupons[$couponData[
'COUPON']]))
681 unset(self::$coupons[$couponData[
'COUPON']]);
688 $event =
new Main\Event(
'sale', self::EVENT_ON_COUPON_DELETE, $couponData);
703 public static function clear($clearStorage =
false)
705 if (self::$useMode === self::MODE_SYSTEM || !self::isSuccess())
710 $clearStorage = ($clearStorage ===
true);
726 public static function clearByOrder($order)
728 if (!self::isSuccess())
732 $order = (int)$order;
742 $orderClassName = $registry->getOrderClassName();
744 $orderIterator = $orderClassName::getList([
745 'select' => [
'ID',
'USER_ID'],
746 'filter' => [
'=ID' => $order],
748 if ($orderData = $orderIterator->fetch())
750 $userId = (int)$orderData[
'USER_ID'];
752 unset($orderData, $orderIterator);
764 if (!self::isSuccess())
782 if (self::$useMode !== self::MODE_MANAGER && self::$useMode !== self::MODE_ORDER || self::$userId ===
null)
787 $oldUser = (int)$oldUser;
793 $session = self::getSession();
799 if (empty($session[self::STORAGE_MANAGER_COUPONS]))
805 empty($session[self::STORAGE_MANAGER_COUPONS][self::$userId])
806 || !is_array($session[self::STORAGE_MANAGER_COUPONS][self::$userId])
812 if (!empty($session[self::STORAGE_MANAGER_COUPONS][$oldUser]))
814 if (is_array($session[self::STORAGE_MANAGER_COUPONS][$oldUser]))
818 unset($session[self::STORAGE_MANAGER_COUPONS][$oldUser]);
827 public static function load()
829 if (self::$useMode !== self::MODE_ORDER)
834 self::$checkActivity =
false;
840 $storageClassName = $registry->getOrderDiscountClassName();
842 $couponIterator = $storageClassName::getOrderCouponIterator([
845 'MODULE_ID' =>
'ORDER_DISCOUNT.MODULE_ID',
846 'DISCOUNT_ID' =>
'ORDER_DISCOUNT.DISCOUNT_ID',
847 'DISCOUNT_NAME' =>
'ORDER_DISCOUNT.NAME',
849 'filter' => [
'=ORDER_ID' => self::$orderId],
850 'order' => [
'ID' =>
'ASC'],
852 while ($coupon = $couponIterator->fetch())
854 $couponData = $coupon[
'DATA'];
855 $couponData[
'COUPON'] = $coupon[
'COUPON'];
858 $couponData[
'MODULE'] = $coupon[
'MODULE_ID'];
859 $couponData[
'MODULE_ID'] = $coupon[
'MODULE_ID'];
860 $couponData[
'ID'] = $coupon[
'COUPON_ID'];
861 $couponData[
'DISCOUNT_ID'] = $coupon[
'DISCOUNT_ID'];
862 $couponData[
'DISCOUNT_NAME'] = (string)$coupon[
'DISCOUNT_NAME'];
863 $couponData[
'DISCOUNT_ACTIVE'] =
'Y';
864 $couponData[
'TYPE'] = $coupon[
'TYPE'];
865 $couponData[
'ACTIVE'] =
'Y';
866 $couponData[
'SAVED'] =
'Y';
867 foreach (self::$timeFields as $fieldName)
869 if (isset($couponData[$fieldName]))
871 $couponData[$fieldName] = Main\Type\DateTime::createFromTimestamp($couponData[$fieldName]);
875 if (empty($couponData[
'USER_INFO']) && $couponData[
'MODE'] === self::COUPON_MODE_FULL)
877 $couponData[
'USER_INFO'] = [
881 'ACTIVE_FROM' =>
null,
885 if (!empty($couponData[
'USER_INFO']))
887 foreach (self::$timeFields as $fieldName)
889 if (isset($couponData[
'USER_INFO'][$fieldName]))
891 $couponData[
'USER_INFO'][$fieldName] = Main\Type\DateTime::createFromTimestamp($couponData[
'USER_INFO'][$fieldName]);
895 foreach ($couponData[
'USER_INFO'] as $fieldName => $fieldValue)
897 $couponData[$fieldName] = $fieldValue;
900 $couponsList[$couponData[
'COUPON']] = $couponData;
902 unset($coupon, $couponIterator);
904 if (!empty($couponsList))
909 self::$checkActivity =
true;
921 public static function get($extMode =
true, $filter = [], $show =
false, $final =
false)
923 if (self::$useMode === self::MODE_SYSTEM)
927 $extMode = ($extMode ===
true);
928 if (!is_array($filter))
932 static::convertOldFilterFields($filter);
933 $show = ($show ===
true);
938 if (!self::isSuccess())
943 if (self::isFrozenCouponStorage() || !self::isEntered())
948 $final = ($final ===
true);
956 : array_filter(self::$coupons,
'\Bitrix\Sale\DiscountCouponsManager::filterFreezeCoupons')
958 if (empty($validCoupons))
966 if (!empty($validCoupons))
970 if ($show && !empty($validCoupons))
975 return ($extMode ? $validCoupons : array_keys($validCoupons));
986 public static function getForApply($filter, $product = [], $uniqueDiscount =
false)
988 if (self::$useMode === self::MODE_SYSTEM)
992 if (self::$useMode === self::MODE_ORDER && static::isUsedOrderCouponsForApply())
994 $filter[
'SAVED'] = [
'Y',
'N'];
998 $filter[
'SAVED'] =
'N';
1001 $couponsList =
self::get(
true, $filter,
false);
1002 if ($couponsList ===
false)
1006 if (!empty($couponsList))
1008 $uniqueDiscount = ($uniqueDiscount ===
true);
1009 if ($uniqueDiscount)
1013 if (!empty($product))
1018 $productCoupons = [];
1019 foreach ($couponsList as $id => $data)
1021 if (self::filterOneRowCoupons($data, $hash))
1023 $productCoupons[$id] = $data;
1026 $couponsList = $productCoupons;
1027 unset($productCoupons);
1036 static::filterLockedCoupons($couponsList);
1038 return $couponsList;
1050 $extMode = ($extMode ===
true);
1052 if (self::$useMode !== self::MODE_ORDER)
1056 if (!self::isSuccess())
1061 if (!self::isEntered())
1066 $result = array_filter(self::$coupons,
'\Bitrix\Sale\DiscountCouponsManager::filterFreezeCoupons');
1071 $result = array_filter($result,
'\Bitrix\Sale\DiscountCouponsManager::filterFreezeOrderedCoupons');
1077 $filter[
'SAVED'] =
'Y';
1078 static::filterArrayCoupons($result, $filter);
1079 if (!empty($result))
1081 static::clearSystemData($result);
1084 return ($extMode ? $result : array_keys($result));
1097 self::$useMode === self::MODE_SYSTEM
1098 || !self::isEntered()
1104 $appliedCoupons =
self::filterCoupons([
'STATUS' => self::STATUS_APPLYED,
'SAVED' =>
'N'],
true);
1105 if (!empty($appliedCoupons))
1108 $appliedCoupons = array_keys($appliedCoupons);
1109 foreach ($appliedCoupons as $coupon)
1112 if ($row[
'STATUS'] == self::STATUS_NOT_FOUND || $row[
'STATUS'] == self::STATUS_FREEZE)
1114 $badCoupons[$coupon] = $row;
1117 unset($row, $coupon);
1118 if (!empty($badCoupons))
1122 foreach ($badCoupons as $row)
1124 $errorData[$row[
'COUPON']] = implode(
', ', $row[
'CHECK_CODE_TEXT']);
1127 $result->addError(
new Main\
Error(
1136 unset($appliedCoupons);
1150 self::$useMode === self::MODE_SYSTEM
1151 || !self::isEntered()
1152 || !self::$allowedSave
1155 return $commonResult;
1164 'STATUS' => self::STATUS_APPLYED,
1165 'MODULE_ID' =>
'sale',
1171 if (!empty($appliedCoupons))
1174 'COUPONS' => $appliedCoupons,
1176 $saveResult = Internals\DiscountCouponTable::saveApplied($appliedCoupons,
$userId, $currentTime);
1178 if ($saveResult ===
false)
1180 $result[
'sale'][
'ERROR'] =
true;
1184 if ($saveResult[
'STATUS'])
1186 $result[
'sale'][
'DEACTIVATE'] = $saveResult[
'DEACTIVATE'];
1187 $result[
'sale'][
'LIMITED'] = $saveResult[
'LIMITED'];
1188 $result[
'sale'][
'INCREMENT'] = $saveResult[
'INCREMENT'];
1193 $commonResult->addError(
new Main\
Error(
1196 $saveResult[
'ERROR']
1199 return $commonResult;
1203 if (!self::$onlySaleDiscount && !empty(self::$couponProviders))
1205 foreach (self::$couponProviders as $provider)
1209 'STATUS' => self::STATUS_APPLYED,
1210 'MODULE_ID' => $provider[
'module'],
1215 if (empty($appliedCoupons))
1219 $result[$provider[
'module']] = [
1220 'COUPONS' => $appliedCoupons,
1222 $saveResult = call_user_func_array(
1223 $provider[
'saveApplied'],
1230 if (empty($saveResult) || !is_array($saveResult))
1232 $result[$provider[
'module']][
'ERROR'] =
true;
1236 if (!isset($saveResult[
'STATUS']) || $saveResult[
'STATUS'])
1238 $result[$provider[
'module']][
'DEACTIVATE'] = ($saveResult[
'DEACTIVATE'] ?? []);
1239 $result[$provider[
'module']][
'LIMITED'] = ($saveResult[
'LIMITED'] ?? []);
1240 $result[$provider[
'module']][
'INCREMENT'] = ($saveResult[
'INCREMENT'] ?? []);
1245 $commonResult->addError(
new Main\
Error(
1247 $provider[
'module'],
1248 $saveResult[
'ERROR']
1251 return $commonResult;
1257 self::$allowedSave =
false;
1258 $event =
new Main\Event(
'sale', self::EVENT_ON_SAVE_APPLIED_COUPONS, $result);
1261 return $commonResult;
1274 static $count =
null;
1275 if ($count ===
null)
1279 if (self::$useMode === self::MODE_SYSTEM)
1283 if (empty($couponsList) || empty($product))
1287 $oldMode = ($oldMode ===
true);
1290 if (!isset($product[
'BASKET_ID']))
1292 $product[
'BASKET_ID'] =
'c'.$count;
1304 foreach ($couponsList as $coupon)
1306 $coupon = trim((
string)$coupon);
1307 if ($coupon ===
'' || !isset(self::$coupons[$coupon]))
1312 self::$coupons[$coupon][
'STATUS'] == self::STATUS_NOT_FOUND
1313 || self::$coupons[$coupon][
'STATUS'] == self::STATUS_FREEZE
1320 && !empty(self::$coupons[$coupon][
'BASKET'])
1325 self::$coupons[$coupon][
'BASKET'][$hash] =
true;
1328 $applyList[$coupon] = self::$coupons[$coupon];
1335 self::EVENT_ON_COUPON_APPLY_PRODUCT,
1337 'PRODUCT' => $product,
1338 'COUPONS' => $applyList,
1357 if (self::$useMode === self::MODE_SYSTEM)
1361 $coupon = trim((
string)$coupon);
1362 if ($coupon ===
'' || empty($data) || !is_array($data))
1366 if (!isset(self::$coupons[$coupon]))
1371 self::$coupons[$coupon][
'STATUS'] == self::STATUS_NOT_FOUND
1372 || self::$coupons[$coupon][
'STATUS'] == self::STATUS_FREEZE
1378 if ((!empty($data[
'BASKET']) && is_array($data[
'BASKET'])) || !empty($data[
'DELIVERY']))
1380 if (!empty($data[
'BASKET']) && is_array($data[
'BASKET']))
1386 foreach ($data[
'BASKET'] as $product)
1388 if (empty($product))
1399 && !empty(self::$coupons[$coupon][
'BASKET'])
1404 self::$coupons[$coupon][
'BASKET'][$hash] =
true;
1406 $result[
'COUPON'] = self::$coupons[$coupon];
1407 if (!isset($result[
'BASKET']))
1409 $result[
'BASKET'] = [];
1411 $result[
'BASKET'][] = $product;
1415 if (!empty($data[
'DELIVERY']))
1417 self::$coupons[$coupon][
'DELIVERY'] = $data[
'DELIVERY'];
1419 $result[
'COUPON'] = self::$coupons[$coupon];
1420 $result[
'DELIVERY'] = self::$coupons[$coupon][
'DELIVERY'];
1422 $event =
new Main\Event(
'sale', self::EVENT_ON_COUPON_APPLY, $result);
1440 if (self::$useMode === self::MODE_SYSTEM || empty($product))
1450 foreach (self::$coupons as &$oneCoupon)
1452 if ($oneCoupon[
'STATUS'] == self::STATUS_NOT_FOUND || $oneCoupon[
'STATUS'] == self::STATUS_FREEZE)
1456 if ($oneCoupon[
'SAVED'] ===
'Y')
1460 if (isset($oneCoupon[
'BASKET'][$hash]))
1462 unset($oneCoupon[
'BASKET'][$hash]);
1463 if (empty($oneCoupon[
'BASKET']) && empty($oneCoupon[
'DELIVERY']))
1482 if (self::$useMode === self::MODE_SYSTEM || !self::isSuccess() || empty(self::$coupons))
1487 foreach (self::$coupons as &$oneCoupon)
1489 if ($oneCoupon[
'STATUS'] == self::STATUS_ENTERED)
1492 if ($oneCoupon[
'CHECK_CODE'] == self::COUPON_CHECK_OK)
1509 if (self::$useMode === self::MODE_SYSTEM || !self::isSuccess())
1513 if (empty(self::$coupons))
1517 $coupon = trim((
string)$coupon);
1522 if (!isset(self::$coupons[$coupon]))
1527 self::$coupons[$coupon][
'STATUS'] == self::STATUS_NOT_FOUND
1528 || self::$coupons[$coupon][
'STATUS'] == self::STATUS_FREEZE
1547 if (self::$useMode === self::MODE_SYSTEM || !self::isSuccess())
1551 if (self::isFrozenCouponStorage())
1555 if (empty(self::$coupons))
1559 $all = ($all !==
false);
1560 foreach (self::$coupons as &$coupon)
1563 $coupon[
'STATUS'] == self::STATUS_NOT_FOUND
1564 || $coupon[
'STATUS'] == self::STATUS_FREEZE
1569 if (!$all && $coupon[
'SAVED'] ===
'Y')
1588 public static function getData($coupon, $checkCoupon =
true)
1591 $currentTimestamp = $currentTime->getTimestamp();
1593 $coupon = trim((
string)$coupon);
1598 $checkCoupon = ($checkCoupon ===
true);
1600 $result = static::getEmptyCouponFields($coupon);
1610 'DISCOUNT_ACTIVE_FROM',
1611 'DISCOUNT_ACTIVE_TO',
1614 $couponIterator = Internals\DiscountCouponTable::getList([
1626 'DISCOUNT_NAME' =>
'DISCOUNT.NAME',
1627 'DISCOUNT_ACTIVE' =>
'DISCOUNT.ACTIVE',
1628 'DISCOUNT_ACTIVE_FROM' =>
'DISCOUNT.ACTIVE_FROM',
1629 'DISCOUNT_ACTIVE_TO' =>
'DISCOUNT.ACTIVE_TO',
1632 '=COUPON' => $coupon,
1635 if ($existCoupon = $couponIterator->fetch())
1638 $result[
'MODULE'] =
'sale';
1639 $result[
'MODULE_ID'] =
'sale';
1641 foreach ($resultKeyList as $resultKey)
1643 $result[$resultKey] = $existCoupon[$resultKey];
1649 $checkCode =
self::checkFullData($existCoupon, $result[
'MODE'], $checkCode, $currentTimestamp);
1653 $result[
'CHECK_CODE'] = $checkCode;
1656 elseif (!self::$onlySaleDiscount && !empty(self::$couponProviders))
1658 foreach (self::$couponProviders as $provider)
1660 $existCoupon = call_user_func_array(
1661 $provider[
'getData'],
1666 if (!empty($existCoupon) && is_array($existCoupon))
1668 $result[
'MODE'] = (int)$provider[
'mode'];
1669 $result[
'MODULE'] = $provider[
'module'];
1670 $result[
'MODULE_ID'] = $provider[
'module'];
1672 foreach ($resultKeyList as $resultKey)
1674 $result[$resultKey] = $existCoupon[$resultKey];
1680 $checkCode =
self::checkFullData($existCoupon, $result[
'MODE'], $checkCode, $currentTimestamp);
1684 $result[
'CHECK_CODE'] = $checkCode;
1703 $coupon = trim((
string)$coupon);
1710 $couponIterator = Internals\DiscountCouponTable::getList([
1716 '=COUPON' => $coupon,
1719 if ($existCoupon = $couponIterator->fetch())
1722 'ID' => $existCoupon[
'ID'],
1723 'COUPON' => $existCoupon[
'COUPON'],
1725 'MODULE_ID' =>
'sale',
1730 if (!self::$onlySaleDiscount && !empty(self::$couponProviders))
1732 foreach (self::$couponProviders as $provider)
1734 $existCoupon = call_user_func_array(
1735 $provider[
'isExist'],
1740 if (!empty($existCoupon) && is_array($existCoupon))
1742 if (!isset($existCoupon[
'ID']) || !isset($existCoupon[
'COUPON']))
1747 'ID' => $existCoupon[
'ID'],
1748 'COUPON' => $existCoupon[
'COUPON'],
1749 'MODULE' => $provider[
'module'],
1750 'MODULE_ID' => $provider[
'module'],
1775 if (self::$useMode === self::MODE_SYSTEM || !self::isSuccess())
1780 $clearData = ($clearData ===
true);
1781 $coupon = trim((
string)$coupon);
1786 if (!isset(self::$coupons[$coupon]))
1789 if (isset(self::$coupons[$couponData[
'COUPON']]))
1791 $result = self::$coupons[$couponData[
'COUPON']];
1796 $result = self::$coupons[$coupon];
1798 if (!empty($result))
1800 if ($result[
'MODE'] === self::COUPON_MODE_FULL)
1802 $result[
'USER_INFO'] = $result[
'SYSTEM_DATA'];
1803 unset($result[
'SYSTEM_DATA']);
1807 foreach (self::$clearFields as $fieldName)
1809 unset($result[$fieldName]);
1812 foreach (self::$timeFields as $fieldName)
1814 if (isset($result[$fieldName]) && $result[$fieldName] instanceof Main\
Type\
DateTime)
1816 $result[$fieldName] = $result[$fieldName]->getTimestamp();
1821 if (!empty($result[
'USER_INFO']))
1823 foreach (self::$timeFields as $fieldName)
1825 if (isset($result[
'USER_INFO'][$fieldName]) && $result[
'USER_INFO'][$fieldName] instanceof Main\
Type\
DateTime)
1827 $result[
'USER_INFO'][$fieldName] = $result[
'USER_INFO'][$fieldName]->getTimestamp();
1849 if (self::$useMode !== self::MODE_CLIENT)
1853 if (self::isSuccess())
1867 return (isset($coupon[
'SAVED']) && $coupon[
'SAVED'] ===
'Y');
1879 if (!is_bool($mode))
1883 if (self::getUseMode() != self::MODE_ORDER)
1887 self::$onlySaleDiscount = $mode;
1888 self::loadCouponProviders();
1898 protected static function checkBaseData(&$data, $checkCode = self::COUPON_CHECK_OK)
1900 if (empty(self::$couponTypes))
1902 self::$couponTypes = Internals\DiscountCouponTable::getCouponTypes(
true);
1905 if (!isset($data[
'ID']))
1912 $data[
'ID'] = (int)$data[
'ID'];
1913 if ($data[
'ID'] <= 0 && self::$checkActivity)
1918 if (!isset($data[
'DISCOUNT_ID']))
1920 $data[
'DISCOUNT_ID'] = 0;
1925 $data[
'DISCOUNT_ID'] = (int)$data[
'DISCOUNT_ID'];
1926 if ($data[
'DISCOUNT_ID'] <= 0 && self::$checkActivity)
1931 if (!isset($data[
'TYPE']))
1933 $data[
'TYPE'] = Internals\DiscountCouponTable::TYPE_UNKNOWN;
1938 $data[
'TYPE'] = (int)$data[
'TYPE'];
1939 if (!isset(self::$couponTypes[$data[
'TYPE']]) && $data[
'TYPE'] != Internals\DiscountCouponTable::TYPE_ARCHIVED)
1941 $data[
'TYPE'] = Internals\DiscountCouponTable::TYPE_UNKNOWN;
1945 if (!isset($data[
'ACTIVE']))
1947 $data[
'ACTIVE'] =
'';
1952 $data[
'ACTIVE'] = (string)$data[
'ACTIVE'];
1953 if ($data[
'ACTIVE'] !==
'Y' && $data[
'ACTIVE'] !==
'N')
1958 if (isset($data[
'ACTIVE_FROM']) && !($data[
'ACTIVE_FROM'] instanceof
Main\Type\DateTime))
1960 $data[
'ACTIVE_FROM'] =
null;
1963 if (isset($data[
'ACTIVE_TO']) && !($data[
'ACTIVE_TO'] instanceof
Main\Type\DateTime))
1965 $data[
'ACTIVE_TO'] =
null;
1968 $data[
'DISCOUNT_NAME'] = (isset($data[
'DISCOUNT_NAME']) ? (string)$data[
'DISCOUNT_NAME'] :
'');
1969 if (!isset($data[
'DISCOUNT_ACTIVE']))
1971 $data[
'DISCOUNT_ACTIVE'] =
'';
1976 $data[
'DISCOUNT_ACTIVE'] = (string)$data[
'DISCOUNT_ACTIVE'];
1977 if ($data[
'DISCOUNT_ACTIVE'] !==
'Y' && $data[
'DISCOUNT_ACTIVE'] !==
'N')
1982 if (isset($data[
'DISCOUNT_ACTIVE_FROM']) && !($data[
'DISCOUNT_ACTIVE_FROM'] instanceof
Main\Type\DateTime))
1984 $data[
'DISCOUNT_ACTIVE_FROM'] =
null;
1987 if (isset($data[
'DISCOUNT_ACTIVE_TO']) && !($data[
'DISCOUNT_ACTIVE_TO'] instanceof
Main\Type\DateTime))
1989 $data[
'DISCOUNT_ACTIVE_TO'] =
null;
2005 protected static function checkFullData(&$data, $mode, $checkCode, $currentTimestamp)
2009 if (self::$checkActivity)
2011 if ($data[
'ACTIVE'] !==
'Y')
2015 if ($data[
'DISCOUNT_ACTIVE'] !==
'Y')
2019 if ($data[
'DISCOUNT_ACTIVE_FROM'] instanceof Main\
Type\
DateTime && $data[
'DISCOUNT_ACTIVE_FROM']->getTimestamp() > $currentTimestamp)
2023 if ($data[
'DISCOUNT_ACTIVE_TO'] instanceof Main\
Type\
DateTime && $data[
'DISCOUNT_ACTIVE_TO']->getTimestamp() < $currentTimestamp)
2029 if ($mode === self::COUPON_MODE_FULL)
2031 if (self::$checkActivity)
2033 if ($data[
'ACTIVE_FROM'] instanceof Main\
Type\
DateTime && $data[
'ACTIVE_FROM']->getTimestamp() > $currentTimestamp)
2037 if ($data[
'ACTIVE_TO'] instanceof Main\
Type\
DateTime && $data[
'ACTIVE_TO']->getTimestamp() < $currentTimestamp)
2042 if (!isset($data[
'USER_ID']))
2044 $data[
'USER_ID'] = 0;
2049 $data[
'USER_ID'] = (int)$data[
'USER_ID'];
2050 if ($data[
'USER_ID'] > 0 && $data[
'USER_ID'] != self::$userId)
2055 if (!isset($data[
'MAX_USE']))
2057 $data[
'MAX_USE'] = 0;
2062 $data[
'MAX_USE'] = (int)$data[
'MAX_USE'];
2064 if (!isset($data[
'USE_COUNT']))
2066 $data[
'USE_COUNT'] = 0;
2071 if (self::$checkActivity)
2073 $data[
'USE_COUNT'] = (int)$data[
'USE_COUNT'];
2074 if ($data[
'MAX_USE'] > 0 && $data[
'USE_COUNT'] >= $data[
'MAX_USE'])
2095 if ($checkCode == self::COUPON_CHECK_OK && $result[
'MODE'] === self::COUPON_MODE_FULL)
2097 $result[
'SYSTEM_DATA'] = [
2098 'USER_ID' => $existCoupon[
'USER_ID'],
2099 'MAX_USE' => $existCoupon[
'MAX_USE'],
2100 'USE_COUNT' => $existCoupon[
'USE_COUNT'],
2101 'ACTIVE_FROM' => $existCoupon[
'ACTIVE_FROM'],
2102 'ACTIVE_TO' => $existCoupon[
'ACTIVE_TO'],
2104 if (self::usedByManager() || ($existCoupon[
'USER_ID'] > 0 && $existCoupon[
'USER_ID'] == self::$userId))
2106 $result[
'USER_INFO'] = $result[
'SYSTEM_DATA'];
2120 && self::$useMode === self::MODE_CLIENT
2121 && self::$userId ===
null
2124 $currentUserId = self::getCurrentUserId();
2125 if ($currentUserId ===
null)
2128 if ($fuserId !==
null)
2131 $row = Internals\FuserTable::getRow([
2145 $currentUserId = (int)$row[
'USER_ID'];
2151 if ($currentUserId ===
null)
2157 self::$userId = $currentUserId;
2159 unset($currentUserId);
2170 if (self::isSuccess())
2172 $session = self::getSession();
2179 if (!empty(self::$coupons))
2181 $couponsList = array_filter(self::$coupons,
'\Bitrix\Sale\DiscountCouponsManager::clearSavedCoupons');
2182 if (!empty($couponsList))
2184 $couponsList = array_keys($couponsList);
2188 if (self::usedByManager())
2190 if (!isset($session[self::STORAGE_MANAGER_COUPONS]) || !is_array($session[self::STORAGE_MANAGER_COUPONS]))
2200 unset($couponsList);
2212 if (!empty($result[
'DEACTIVATE']) || !empty($result[
'LIMITED']))
2214 $clear = array_keys(array_merge($result[
'DEACTIVATE'], $result[
'LIMITED']));
2215 foreach ($clear as $coupon)
2217 if (isset(self::$coupons[$coupon]))
2219 unset(self::$coupons[$coupon]);
2221 if (isset(self::$lockedCoupons[$coupon]))
2223 unset(self::$lockedCoupons[$coupon]);
2226 unset($coupon, $clear);
2238 $couponData[
'BASKET'] = [];
2239 $couponData[
'DELIVERY'] = [];
2247 protected static function loadCouponProviders()
2249 self::$couponProviders = [];
2250 if (!self::$onlySaleDiscount)
2253 'COUPON_UNKNOWN' => Internals\DiscountCouponTable::TYPE_UNKNOWN,
2254 'COUPON_TYPES' => Internals\DiscountCouponTable::getCouponTypes(
false),
2256 $event =
new Main\Event(
'sale', self::EVENT_ON_BUILD_COUPON_PROVIDES, $eventData);
2258 $resultList = $event->getResults();
2259 if (empty($resultList) || !is_array($resultList))
2262 foreach ($resultList as $eventResult)
2264 if ($eventResult->getType() != Main\EventResult::SUCCESS)
2268 $module = (string)$eventResult->getModuleId();
2269 $provider = $eventResult->getParameters();
2270 if (empty($provider) || !is_array($provider))
2274 if (empty($provider[
'getData']) || empty($provider[
'isExist']) || empty($provider[
'saveApplied']))
2278 self::$couponProviders[] = [
2279 'module' => $module,
2280 'getData' => $provider[
'getData'],
2281 'isExist' => $provider[
'isExist'],
2282 'saveApplied' => $provider[
'saveApplied'],
2284 (int)($provider[
'mode'] ?? self::COUPON_MODE_SIMPLE) === self::COUPON_MODE_FULL
2290 unset($provider, $module, $eventResult, $resultList, $event, $eventData);
2301 if (self::$onlySaleDiscount !==
null)
2306 self::$onlySaleDiscount = Option::get(
'sale',
'use_sale_discount_only') ===
'Y';
2307 self::loadCouponProviders();
2318 if (empty(self::$couponTypes))
2320 self::$couponTypes = Internals\DiscountCouponTable::getCouponTypes(
true);
2323 return (isset($coupon[
'TYPE']) && isset(self::$couponTypes[$coupon[
'TYPE']]));
2334 if (empty(self::$couponTypes))
2336 self::$couponTypes = Internals\DiscountCouponTable::getCouponTypes(
true);
2340 isset($coupon[
'TYPE'])
2341 && isset(self::$couponTypes[$coupon[
'TYPE']])
2342 && $coupon[
'STATUS'] != self::STATUS_FREEZE
2354 static $currentTimeStamp =
null;
2355 if ($currentTimeStamp ===
null)
2357 $currentTimeStamp = time();
2359 if (!isset($coupon[
'SAVED']) || $coupon[
'SAVED'] !==
'Y')
2363 if (isset($coupon[
'MODE']) && $coupon[
'MODE'] === self::COUPON_MODE_FULL)
2366 isset($coupon[
'ACTIVE_FROM']) && $coupon[
'ACTIVE_FROM'] instanceof Main\
Type\
DateTime
2367 && $coupon[
'ACTIVE_FROM']->getTimestamp() > $currentTimeStamp
2373 isset($coupon[
'ACTIVE_TO']) && $coupon[
'ACTIVE_TO'] instanceof Main\
Type\
DateTime
2374 && $coupon[
'ACTIVE_TO']->getTimestamp() < $currentTimeStamp
2395 || empty($coupon[
'BASKET'])
2396 || (count($coupon[
'BASKET']) === 1 && isset($coupon[
'BASKET'][$hash]))
2408 $existDiscount = [];
2410 foreach (
$coupons as $key => $oneCoupon)
2412 $hash = $oneCoupon[
'MODULE_ID'].
':'.$oneCoupon[
'DISCOUNT_ID'];
2414 isset($existDiscount[$hash])
2425 $existDiscount[$hash] =
true;
2428 unset($hash, $existDiscount);
2433 if (empty($couponList) || !static::usedByClient())
2438 $locker = Sale\Discount\CouponLocker::getInstance();
2439 foreach (array_keys($couponList) as $coupon)
2441 if (!static::needLockCoupon($coupon))
2445 if (isset(self::$lockedCoupons[$coupon]))
2449 $locker->lock($coupon);
2450 if ($locker->isLocked($coupon))
2452 self::$lockedCoupons[$coupon] =
true;
2456 unset($couponList[$coupon]);
2471 $getId = ($getId ===
true);
2473 if (empty(self::$coupons) || empty($filter) || !is_array($filter))
2478 foreach (self::$coupons as $id => $data)
2481 foreach ($filter as $filterKey => $filterValue)
2483 if (is_array($filterValue) && isset($filterValue[
'LOGIC']))
2485 $logic = mb_strtolower($filterValue[
'LOGIC']);
2486 if ($logic !==
'and' && $logic !==
'or')
2490 unset($filterValue[
'LOGIC']);
2491 if (empty($filterValue))
2496 foreach ($filterValue as $subfilterKey => $subfilterValue)
2498 $invert = strncmp($subfilterKey,
'!', 1) === 0;
2499 $fieldName = ($invert? mb_substr($subfilterKey, 1) : $subfilterKey);
2500 if (!isset($data[$fieldName]))
2507 is_array($subfilterValue)
2508 ? in_array($data[$fieldName], $subfilterValue)
2509 : $data[$fieldName] == $subfilterValue
2513 $compare = !$compare;
2515 $subresult[] = $compare;
2520 ? !in_array(
false, $subresult,
true)
2521 : in_array(
true, $subresult,
true)
2531 $invert = strncmp($filterKey,
'!', 1) === 0;
2532 $fieldName = ($invert? mb_substr($filterKey, 1) : $filterKey);
2533 if (!isset($data[$fieldName]))
2540 is_array($filterValue)
2541 ? in_array($data[$fieldName], $filterValue)
2542 : $data[$fieldName] == $filterValue
2546 $compare = !$compare;
2558 $result[$id] = ($getId ? $data[
'ID'] : $data);
2574 if (empty(
$coupons) || !is_array(
$coupons) || empty($filter) || !is_array($filter))
2582 foreach ($filter as $filterKey => $filterValue)
2584 if (is_array($filterValue) && isset($filterValue[
'LOGIC']))
2586 $logic = mb_strtolower($filterValue[
'LOGIC']);
2587 if ($logic !==
'and' && $logic !==
'or')
2591 unset($filterValue[
'LOGIC']);
2592 if (empty($filterValue))
2597 foreach ($filterValue as $subfilterKey => $subfilterValue)
2599 $invert = strncmp($subfilterKey,
'!', 1) === 0;
2600 $fieldName = ($invert? mb_substr($subfilterKey, 1) : $subfilterKey);
2601 if (!isset($data[$fieldName]))
2608 is_array($subfilterValue)
2609 ? in_array($data[$fieldName], $subfilterValue)
2610 : $data[$fieldName] == $subfilterValue
2614 $compare = !$compare;
2616 $subresult[] = $compare;
2621 ? !in_array(
false, $subresult,
true)
2622 : in_array(
true, $subresult,
true)
2632 $invert = strncmp($filterKey,
'!', 1) === 0;
2633 $fieldName = ($invert? mb_substr($filterKey, 1) : $filterKey);
2634 if (!isset($data[$fieldName]))
2641 is_array($filterValue)
2642 ? in_array($data[$fieldName], $filterValue)
2643 : $data[$fieldName] == $filterValue
2647 $compare = !$compare;
2659 $result[$id] = $data;
2675 if (!empty($product) && is_array($product))
2678 if (isset($product[
'MODULE_ID']))
2680 $module = trim((
string)$product[
'MODULE_ID']);
2682 elseif (isset($product[
'MODULE']))
2684 $module = trim((
string)$product[
'MODULE']);
2686 $productId = (isset($product[
'PRODUCT_ID']) ? (int)$product[
'PRODUCT_ID'] : 0);
2687 $basketId = (isset($product[
'BASKET_ID']) ? trim((
string)$product[
'BASKET_ID']) :
'0');
2688 if ($productId > 0 && $basketId !==
'')
2690 $hash = $module.
':'.$productId.
':'.$basketId;
2706 $module =
'catalog';
2709 if (!empty($product) && is_array($product))
2711 if (isset($product[
'MODULE_ID']))
2713 $module = trim((
string)$product[
'MODULE_ID']);
2715 elseif (isset($product[
'MODULE']))
2717 $module = trim((
string)$product[
'MODULE']);
2719 if (isset($product[
'PRODUCT_ID']))
2721 $productId = (int)$product[
'PRODUCT_ID'];
2723 $basketId = (isset($product[
'BASKET_ID']) ? trim((
string)$product[
'BASKET_ID']) :
'0');
2725 if ($productId >= 0 && $basketId !==
'')
2727 $hash = $module.
':'.$productId.
':'.$basketId;
2744 $oneCoupon[
'STATUS_TEXT'] = $statusList[$oneCoupon[
'STATUS']];
2745 if ($oneCoupon[
'CHECK_CODE'] == self::COUPON_CHECK_OK || $oneCoupon[
'CHECK_CODE'] == self::COUPON_CHECK_NOT_APPLIED)
2747 if ($oneCoupon[
'CHECK_CODE'] == self::COUPON_CHECK_OK)
2749 $oneCoupon[
'CHECK_CODE_TEXT'] = (
2750 $oneCoupon[
'STATUS'] == self::STATUS_APPLYED
2751 ? [$statusList[$oneCoupon[
'STATUS']]]
2762 $oneCoupon[
'CHECK_CODE_TEXT'] = [];
2763 foreach ($checkCode as $code => $text)
2765 if ($code == self::COUPON_CHECK_OK)
2769 if (($oneCoupon[
'CHECK_CODE'] & $code) == $code)
2771 $oneCoupon[
'CHECK_CODE_TEXT'][] = $checkCode[$code];
2786 protected static function setCoupons($couponsList, $checkCoupons =
true)
2788 if (empty($couponsList) || !is_array($couponsList))
2793 $checkCoupons = ($checkCoupons !==
false);
2796 foreach ($couponsList as $coupon)
2798 $coupon = trim((
string)$coupon);
2804 if (!isset(self::$coupons[$couponData[
'COUPON']]))
2808 self::$coupons[$couponData[
'COUPON']] = $couponData;
2809 self::$couponIndex++;
2812 unset($couponData, $coupon);
2817 $currentTimestamp = $currentTime->getTimestamp();
2818 unset($currentTime);
2819 foreach ($couponsList as $coupon)
2821 if (empty($coupon) || !is_array($coupon))
2826 $checkCode =
self::checkFullData($coupon, $coupon[
'MODE'], $checkCode, $currentTimestamp);
2828 $coupon[
'CHECK_CODE'] = $checkCode;
2830 if (!isset(self::$coupons[$coupon[
'COUPON']]))
2834 self::$coupons[$coupon[
'COUPON']] = $coupon;
2835 self::$couponIndex++;
2838 unset($coupon, $currentTimestamp);
2851 return (!isset($coupon[
'SAVED']) || $coupon[
'SAVED'] !==
'Y');
2866 if (array_key_exists(
'SYSTEM_DATA', $couponData))
2868 unset($couponData[
'SYSTEM_DATA']);
2885 if (array_key_exists(
'MODULE', $filter))
2887 if (!isset($filter[
'MODULE_ID']))
2889 $filter[
'MODULE_ID'] = $filter[
'MODULE'];
2891 unset($filter[
'MODULE']);
2893 if (array_key_exists(
'!MODULE', $filter))
2895 if (!isset($filter[
'!MODULE_ID']))
2897 $filter[
'!MODULE_ID'] = $filter[
'!MODULE'];
2899 unset($filter[
'!MODULE']);
2914 'COUPON' => $coupon,
2922 'DISCOUNT_NAME' =>
'',
2923 'TYPE' => Internals\DiscountCouponTable::TYPE_UNKNOWN,
2930 private static function getCurrentUserId(): ?int
2936 && $USER instanceof \CUser
2942 $userId = (int)$USER->GetID();
2949 $type = self::$coupons[$coupon][
'TYPE'] ?? Internals\DiscountCouponTable::TYPE_UNKNOWN;
static getMessage($code, $replace=null, $language=null)
static filterUniqueDiscount(&$coupons)
const COUPON_CHECK_CORRUPT_DATA
static needLockCoupon(string $coupon)
static setCoupons($couponsList, $checkCoupons=true)
static fillCouponHints(&$coupons)
static array $couponTypes
const COUPON_CHECK_RANGE_ACTIVE_TO_DISCOUNT
static filterLockedCoupons(array &$couponList)
static filterFreezeOrderedCoupons($coupon)
static array $lockedCoupons
const COUPON_CHECK_NO_ACTIVE_DISCOUNT
const COUPON_CHECK_NOT_APPLIED
static filterOneRowCoupons($coupon, $hash)
static convertOldFilterFields(array &$filter)
static filterArrayCoupons(&$coupons, $filter)
const EVENT_ON_COUPON_DELETE
static deleteApplyByProduct($product)
static fillUserInfo(&$result, $existCoupon, $checkCode)
const COUPON_CHECK_ALREADY_MAX_USED
static int $allowCouponStorage
static getCatalogProductHash($product)
static checkBaseData(&$data, $checkCode=self::COUPON_CHECK_OK)
static bool $useOrderCoupons
const EVENT_ON_BUILD_COUPON_PROVIDES
static getStatusList($extendedMode=false)
static freezeCouponStorage()
static getForApply($filter, $product=[], $uniqueDiscount=false)
const EVENT_ON_COUPON_APPLY_PRODUCT
static getData($coupon, $checkCoupon=true)
static isUsedOrderCouponsForApply()
static getEnteredCoupon($coupon, $clearData=false)
const EVENT_ON_COUPON_APPLY
const STORAGE_MANAGER_COUPONS
static clearSavedCoupons($coupon)
const EVENT_ON_COUPON_ADD
const COUPON_CHECK_UNKNOWN_TYPE
static getEmptyCouponFields($coupon)
static filterUnknownCoupons($coupon)
const COUPON_CHECK_RANGE_ACTIVE_FROM
const COUPON_CHECK_RANGE_ACTIVE_FROM_DISCOUNT
static getCheckCodeMessage($code)
static checkFullData(&$data, $mode, $checkCode, $currentTimestamp)
static filterFreezeCoupons($coupon)
static clear($clearStorage=false)
static unFreezeCouponStorage()
static filterCoupons($filter, $getId=false)
static setUseOnlySaleDiscounts($mode)
const STORAGE_CLIENT_COUPONS
static get($extMode=true, $filter=[], $show=false, $final=false)
static clearSystemData(&$coupons)
static bool $onlySaleDiscount
const EVENT_ON_SAVE_APPLIED_COUPONS
static filterOrderCoupons($coupon)
static init($mode=self::MODE_CLIENT, $params=[], $clearStorage=false)
static array $clearFields
static migrateStorage($oldUser)
static reInit($mode=self::MODE_CLIENT, $params=[], $clearStorage=false)
static array $couponProviders
static clearApply($all=true)
const COUPON_CHECK_NO_ACTIVE
static setApplyByProduct($product, $couponsList, $oldMode=false)
static eraseAppliedCoupons($result)
static getOrderedCoupons($extMode=true, $filter=[])
static isFrozenCouponStorage()
static useSavedCouponsForApply($state)
static clearApplyCoupon($coupon)
static getProductHash($product)
const COUPON_CHECK_BAD_USER_ID
static createApplyFields(&$couponData)
static bool $checkActivity
static initUseMode($mode=self::MODE_CLIENT, $params=[])
static getCheckCodeList($extendedMode=false)
const COUPON_CHECK_RANGE_ACTIVE_TO
static setApply($coupon, $data)
const COUPON_CHECK_NOT_FOUND
static getId($skipCreate=false)
static getInstance($type)