3namespace Bitrix\Sale\Discount\Preset;
5use Bitrix\Crm\Order\BuyerGroup;
7use Bitrix\Main\Config\Option;
8use Bitrix\Main\Context;
10use Bitrix\Main\ErrorCollection;
11use Bitrix\Main\Loader;
12use Bitrix\Main\Localization\Loc;
13use Bitrix\Main\SiteTable;
14use Bitrix\Main\SystemException;
15use Bitrix\Main\Web\Json;
16use Bitrix\Sale\Helpers\Admin\Blocks\OrderBasket;
17use Bitrix\Sale\Internals\DiscountGroupTable;
49 private $stepResultState;
51 private array $discount;
53 private bool $restrictedGroupsMode =
false;
63 return get_called_class();
72 return (
new \ReflectionClass($classObject))->getShortName();
78 $this->request = Context::getCurrent()->getRequest();
79 $this->bitrix24Included = Loader::includeModule(
'bitrix24');
86 $this->restrictedGroupsMode = $state ===
true;
91 return $this->restrictedGroupsMode;
99 return !$this->errorCollection->isEmpty();
107 return $this->errorCollection->toArray();
112 if ($this->stepResultState)
114 return $this->stepResultState->getStepNumber();
133 . $this->
endForm($this->stepResultState)
139 return (
bool)$this->request->getPost(static::RUN_PREV_STEP_NAME_VAR);
144 $methodName =
'processAjaxAction' . $actionName;
145 if (!method_exists($this, $methodName))
150 $result = call_user_func_array([$this, $methodName], []);
152 header(
'Content-Type:application/json; charset=UTF-8');
153 \CMain::FinalActions(Json::encode(
$result));
158 $productId = !empty(
$params[
'productId']) ?
$params[
'productId'] : $this->request->get(
'productId');
159 if (is_array($productId))
161 $productId = array_pop($productId);
164 $quantity = !empty(
$params[
'quantity']) ?
$params[
'quantity'] : $this->request->get(
'quantity');
165 $quantity = (float)$quantity;
173 if (empty($productId))
177 if (empty($quantity))
182 $productDetails = OrderBasket::getProductDetails($productId, $quantity,
$userId,
$siteId);
183 if (!$productDetails || empty($productDetails[
'PRODUCT_ID']))
185 return $this->getProductInfo($productId);
188 return $productDetails;
191 private function getProductInfo($elementId):
array
193 $elementId = (int)$elementId;
199 $dbProduct = \CIBlockElement::getList(
201 [
'ID' => $elementId],
214 $product = $dbProduct->fetch();
222 if ($product[
"IBLOCK_ID"] > 0)
224 $product[
"EDIT_PAGE_URL"] = \CIBlock::getAdminElementEditLink(
225 $product[
"IBLOCK_ID"],
227 [
"find_section_section" => $product[
"IBLOCK_SECTION_ID"]]
231 if ($product[
"DETAIL_PICTURE"] > 0)
233 $imgCode = $product[
"DETAIL_PICTURE"];
235 elseif ($product[
"PREVIEW_PICTURE"] > 0)
237 $imgCode = $product[
"PREVIEW_PICTURE"];
242 $imgProduct = \CFile::resizeImageGet(
243 \CFile::getFileArray($imgCode),
252 $product[
"PICTURE_URL"] = $imgProduct[
'src'];
254 $product[
'PRODUCT_ID'] = $product[
'ID'];
259 public function exec()
261 $isPost = $this->request->isPost();
263 $stepName = $this->getStepName();
274 $stepName = $state->getPrevStep();
280 list($state,
$nextStep) = $this->runStep($stepName, $state, self::MODE_SAVE);
284 $state->addStepChain($stepName);
303 $step = $state->popStepChain();
317 $step = $state->popStepChain();
322 $this->stepResult = $this->runStep($stepName, $state, self::MODE_SHOW);
323 $this->stepResultState = $state;
328 private function runStep($actionName, State $state, $mode = self::MODE_SHOW)
331 if ($mode === self::MODE_SHOW)
333 $methodName =
'processShow' . $actionName;
335 elseif ($mode === self::MODE_SAVE)
337 $methodName =
'processSave' . $actionName;
342 throw new SystemException(
"Unknown mode {$mode}");
345 if (!method_exists($this, $methodName))
347 throw new SystemException(
"Method {$methodName} is not exist");
350 return call_user_func_array(
array($this, $methodName),
array($state));
353 private function getStepName()
355 return $this->request->getPost(static::STEP_NAME_VAR) ?: static::getFirstStepName();
364 $this->discount ?? []
370 return !empty($this->discount);
379 if (!is_array($discount))
458 return self::AVAILABLE_STATE_ALLOW;
474 'DISCOUNT_TYPE' =>
'',
475 'DISCOUNT_VALUE' =>
'',
476 'DISCOUNT_CONDITION' =>
'',
503 $prevStep = $this->stepResultState->getPrevStep();
528 .
' enctype="multipart/form-data" method="post" name="__preset_form" id="__preset_form">'
530 .
'<input type="hidden" name="' . static::STEP_NAME_VAR .
'" id="' . static::STEP_NAME_VAR .
'" value="' .
htmlspecialcharsbx($this->
getNextStep()) .
'">
531 <input type="hidden" name="' . static::RUN_PREV_STEP_NAME_VAR .
'" id="' . static::RUN_PREV_STEP_NAME_VAR .
'" value="">
533 <input type="hidden" name="lang" value="' . LANGUAGE_ID .
'">
546 if (
Main\Loader::includeModule(
'crm'))
548 $existingGroups = [];
555 $discountGroups = BuyerGroup::prepareGroupIds($existingGroups, $discountGroups);
559 return $discountGroups;
568 $siteId = $state->get(
'discount_lid');
570 $discountGroups = $state->get(
'discount_groups') ?: [];
575 'NAME' => $state->get(
'discount_name'),
577 'ACTIVE_FROM' => $state->get(
'discount_active_from'),
578 'ACTIVE_TO' => $state->get(
'discount_active_to'),
580 'SORT' => $state->get(
'discount_sort'),
581 'PRIORITY' => $state->get(
'discount_priority'),
582 'LAST_DISCOUNT' => $state->get(
'discount_last_discount'),
583 'LAST_LEVEL_DISCOUNT' => $state->get(
'discount_last_level_discount'),
584 'USER_GROUPS' => $userGroups,
595 'discount_id' => $discountFields[
'ID'],
596 'discount_lid' => $discountFields[
'LID'],
597 'discount_name' => $discountFields[
'NAME'],
598 'discount_active_from' => $discountFields[
'ACTIVE_FROM'],
599 'discount_active_to' => $discountFields[
'ACTIVE_TO'],
600 'discount_last_discount' => $discountFields[
'LAST_DISCOUNT'],
601 'discount_last_level_discount' => $discountFields[
'LAST_LEVEL_DISCOUNT'],
602 'discount_priority' => $discountFields[
'PRIORITY'],
603 'discount_sort' => $discountFields[
'SORT'],
610 if (isset($discountFields[
'CONDITIONS']) && is_array($discountFields[
'CONDITIONS']))
612 $discountFields[
'CONDITIONS_LIST'] = $discountFields[
'CONDITIONS'];
615 if (isset($discountFields[
'CONDITIONS_LIST']) && is_string($discountFields[
'CONDITIONS_LIST']))
617 $discountFields[
'CONDITIONS_LIST'] = unserialize($discountFields[
'CONDITIONS_LIST'], [
'allowed_classes' =>
false]);
620 if (isset($discountFields[
'CONDITIONS_LIST']) && is_array($discountFields[
'CONDITIONS_LIST']))
622 $discountFields[
'CONDITIONS'] = $discountFields[
'CONDITIONS_LIST'];
625 if (isset($discountFields[
'ACTIONS']) && is_array($discountFields[
'ACTIONS']))
627 $discountFields[
'ACTIONS_LIST'] = $discountFields[
'ACTIONS'];
630 if (isset($discountFields[
'ACTIONS_LIST']) && is_string($discountFields[
'ACTIONS_LIST']))
632 $discountFields[
'ACTIONS_LIST'] = unserialize($discountFields[
'ACTIONS_LIST'], [
'allowed_classes' =>
false]);
635 if (isset($discountFields[
'ACTIONS_LIST']) && is_array($discountFields[
'ACTIONS_LIST']))
637 $discountFields[
'ACTIONS'] = $discountFields[
'ACTIONS_LIST'];
640 if (isset($discountFields[
'PREDICTIONS_LIST']) && is_string($discountFields[
'PREDICTIONS_LIST']))
642 $discountFields[
'PREDICTIONS_LIST'] = unserialize($discountFields[
'PREDICTIONS_LIST'], [
'allowed_classes' =>
false]);
645 if (isset($discountFields[
'PREDICTIONS_LIST']) && is_array($discountFields[
'PREDICTIONS_LIST']))
647 $discountFields[
'PREDICTIONS'] = $discountFields[
'PREDICTIONS_LIST'];
650 return $discountFields;
655 $discountFields[
'PRESET_ID'] = $this->
className();
657 if (!\CSaleDiscount::update($id, $discountFields))
663 $this->errorCollection[] =
new Error($ex->getString());
667 $this->errorCollection[] =
new Error(Loc::getMessage(
'SALE_BASE_PRESET_DISCOUNT_EDIT_ERR_UPDATE'));
674 $discountFields[
'PRESET_ID'] = $this->
className();
676 $discountId = \CSaleDiscount::add($discountFields);
678 if ($discountId <= 0)
684 $this->errorCollection[] =
new Error($ex->getString());
688 $this->errorCollection[] =
new Error(Loc::getMessage(
'SALE_BASE_PRESET_DISCOUNT_EDIT_ERR_ADD'));
695 return Loc::getMessage(
696 'SALE_BASE_PRESET_FINAL_OK',
706 $groupDiscountIterator = DiscountGroupTable::getList([
711 'DISCOUNT_ID' => $discountId,
715 while ($groupDiscount = $groupDiscountIterator->fetch())
717 $groups[] = (int)$groupDiscount[
'GROUP_ID'];
721 $groupDiscountIterator,
729 return $this->getSaleSiteList() ?: $this->getFullSiteList();
732 private function getSaleSiteList():
array
750 $saleSite = Option::get(
'sale',
'SHOP_SITE_' .
$site[
'LID']);
751 if (
$site[
'LID'] == $saleSite)
764 private function getFullSiteList():
array
792 <table width="100%" border="0" cellspacing="7" cellpadding="0">
795 <td class="adm-detail-content-cell-l" style="width:40%;"><strong>' . Loc::getMessage(
'SALE_BASE_PRESET_ORDERAMOUNT_FIELD_NAME') .
':</strong></td>
796 <td class="adm-detail-content-cell-r" style="width:60%;">
797 <input type="text" name="discount_name" value="' .
htmlspecialcharsbx($state->get(
'discount_name')) .
'" size="39" maxlength="100" style="width: 300px;">
801 <td class="adm-detail-content-cell-l"><strong>' . Loc::getMessage(
'SALE_BASE_PRESET_ORDERAMOUNT_LID') .
':</strong></td>
802 <td class="adm-detail-content-cell-r">
813 if (!trim($state->get(
'discount_name')))
815 $this->errorCollection[] =
new Error(Loc::getMessage(
'SALE_BASE_PRESET_ERROR_EMPTY_NAME'));
818 if (!trim($state->get(
'discount_lid')))
820 $this->errorCollection[] =
new Error(Loc::getMessage(
'SALE_BASE_PRESET_ERROR_EMPTY_LID'));
823 if (!$this->errorCollection->isEmpty())
825 return array($state,
'InputName');
833 $this->errorCollection[] =
new Error(Loc::getMessage(
'SALE_HANDLERS_DISCOUNTPRESET_ERROR_EMPTY_VALUE_MSGVER_1'));
845 $hintLastDiscountImageName =
'hint_last_discount_' . LANGUAGE_ID .
'.png';
853 if ($state->get(
'discount_active_from') || $state->get(
'discount_active_to'))
859 <table width="100%" border="0" cellspacing="7" cellpadding="0">
862 <td class="adm-detail-content-cell-l" style="width:40%;"><strong>' . Loc::getMessage(
'SALE_BASE_PRESET_ORDERAMOUNT_USER_GROUPS') .
':</strong></td>
863 <td class="adm-detail-content-cell-r">
868 <td class="adm-detail-content-cell-l" style="width:40%;"><strong>' . Loc::getMessage(
'SALE_BASE_PRESET_ACTIVE_PERIOD') .
':</strong></td>
869 <td class="adm-detail-content-cell-r">' .
871 'discount_active_from',
872 'discount_active_to',
873 $state->get(
'discount_active_from'),
874 $state->get(
'discount_active_to'),
887 <td class="adm-detail-content-cell-l" style="width:40%;"><strong>' . Loc::getMessage(
'SALE_BASE_PRESET_ORDERAMOUNT_FIELD_PRIORITY') .
':</strong></td>
888 <td class="adm-detail-content-cell-r" style="width:60%;">
889 <input type="text" name="discount_priority" value="' . (int)$state->get(
'discount_priority', 1) .
'" size="39" maxlength="100" style="width: 100px;">
893 <td class="adm-detail-content-cell-l" style="width:40%;"><strong>' . Loc::getMessage(
'SALE_BASE_PRESET_ORDERAMOUNT_FIELD_SORT') .
':</strong></td>
894 <td class="adm-detail-content-cell-r" style="width:60%;">
895 <input type="text" name="discount_sort" value="' . (int)$state->get(
'discount_sort', 100) .
'" size="39" maxlength="100" style="width: 100px;">
899 <td class="adm-detail-content-cell-l" style="width:40%;">
900 <script>BX.ready(function(){BX.hint_replace(BX("tr_HELP_notice"), \'<img style="padding-left: 16px;" width="545" height="353" src="/bitrix/images/sale/discount/' . $hintLastDiscountImageName .
'" alt="">\');})</script>
901 <span id="tr_HELP_notice"></span>
902 <strong>' . Loc::getMessage(
'SALE_BASE_PRESET_LAST_LEVEL_DISCOUNT_LABEL') .
':</strong>
904 <td class="adm-detail-content-cell-r" style="width:60%;">
905 <input type="checkbox" name="discount_last_level_discount" value="Y" ' . ($state->get(
'discount_last_level_discount',
'N') ==
'Y'?
'checked' :
'') .
'>
909 <td class="adm-detail-content-cell-l" style="width:40%;">
910 <script>BX.ready(function(){BX.hint_replace(BX("tr_HELP_notice2"), \'<img style="padding-left: 16px;" width="545" height="353" src="/bitrix/images/sale/discount/' . $hintLastDiscountImageName .
'" alt="">\');})</script>
911 <span id="tr_HELP_notice2"></span>
912 <strong>' . Loc::getMessage(
'SALE_BASE_PRESET_LAST_DISCOUNT_LABEL') .
':</strong>
914 <td class="adm-detail-content-cell-r" style="width:60%;">
915 <input type="checkbox" name="discount_last_discount" value="Y" ' . ($state->get(
'discount_last_discount',
'Y') ==
'Y'?
'checked' :
'') .
'>
925 if (!$state->get(
'discount_groups'))
927 $this->errorCollection[] =
new Error(Loc::getMessage(
'SALE_BASE_PRESET_ERROR_EMPTY_USER_GROUPS'));
930 $priority = (int)$state->get(
'discount_priority');
933 $this->errorCollection[] =
new Error(Loc::getMessage(
'SALE_BASE_PRESET_ERROR_EMPTY_PRIORITY'));
937 $state[
'discount_priority'] = $priority;
940 if ($state[
'discount_last_discount'] !==
'Y' || !$this->request->getPost(
'discount_last_discount'))
942 $state[
'discount_last_discount'] =
'N';
945 if ($state[
'discount_last_level_discount'] !==
'Y' || !$this->request->getPost(
'discount_last_level_discount'))
947 $state[
'discount_last_level_discount'] =
'N';
950 if (!$this->errorCollection->isEmpty())
952 return array($state,
'CommonSettings');
960 return Loc::getMessage(
'SALE_BASE_PRESET_DISCOUNT_VALUE_LABEL');
967 <td class="adm-detail-content-cell-l" style="width:40%;"><strong>' . $this->
getLabelDiscountValue() .
':</strong></td>
968 <td class="adm-detail-content-cell-r" style="width:60%;">
969 <input type="text" name="discount_value" value="' .
htmlspecialcharsbx($state->get(
'discount_value')) .
'" maxlength="100" style="width: 100px;"> '
971 'Perc' => Loc::getMessage(
'SHD_BT_SALE_ACT_GROUP_BASKET_SELECT_PERCENT'),
973 ), $state->get(
'discount_type')) .
'
981 return static::ACTION_TYPE_DISCOUNT;
993 if (
Main\Loader::includeModule(
'crm'))
995 foreach (BuyerGroup::getPublicList() as $group)
997 $groupList[$group[
'ID']] = $group[
'NAME'];
1014 while ($group = $groupIterator->fetch())
1016 $groupList[$group[
'ID']] = $group[
'NAME'];
1034 foreach ($dateFields as $fieldName)
1037 isset($discount[$fieldName])
1041 $discount[$fieldName] = $discount[$fieldName]->toString();
if(!is_object($USER)||! $USER->IsAuthorized()) $userId
static getDefaultLang($lang)
static getList(array $parameters=array())
normalizeDiscountFields(array $discountFields)
generateState(array $discountFields)
isRestrictedGroupsModeEnabled()
processSaveCommonSettingsInternal(State $state, $nextStep=self::FINAL_STEP)
processSaveInputNameInternal(State $state, $nextStep)
processShowInputNameInternal(State $state)
generateDiscount(State $state)
updateDiscount($id, array $discountFields)
filterUserGroups(array $discountGroups)
const AVAILABLE_STATE_DISALLOW
processAjaxActionGetProductDetails(array $params=[])
renderDiscountValue(State $state, $currency)
executeAjaxAction($actionName)
addDiscount(array $discountFields)
setStepDescription($stepDescription)
const AVAILABLE_STATE_ALLOW
static classShortName(BasePreset $classObject)
const AVAILABLE_STATE_TARIFF
enableRestrictedGroupsMode($state)
processShowCommonSettingsInternal(State $state)
const ACTION_TYPE_DISCOUNT
processShowFinalStep(State $state)
const RUN_PREV_STEP_NAME_VAR
addErrorEmptyActionValue()
prepareDiscountFields(array $discount)
getUserGroupsByDiscount($discountId)
static generateMultipleSelect($id, array $selectData, array $values, array $params=[])
static generateSelect($id, array $selectData, $value, array $params=[])
static createFromRequest(HttpRequest $request)
static getSiteCurrency($siteId)
static CalendarPeriodCustom($sFromName, $sToName, $sFromVal="", $sToVal="", $bSelectShow=false, $size=10, $bTime=false, $arPeriod=false, $periodValue='')
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
const BX_RESIZE_IMAGE_PROPORTIONAL
bitrix_sessid_post($varname='sessid', $returnInvocations=false)
htmlspecialcharsbx($string, $flags=ENT_COMPAT, $doubleEncode=true)
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)
if($inWords) echo htmlspecialcharsbx(Number2Word_Rus(roundEx($totalVatSum $params['CURRENCY']