Была поставлена задача сделать персональные скидки пользователя, которые должны были автоматически рассчитываться сайтом по некоторым правилам от 5 до 90% с шагом в 1%.
Выгодные предложения являются стимулом для потенциальных клиентов. Многие новые посетители казино Пин Ап остаются именно здесь из-за приветственного бонуса в 100% и 250 фриспинов.
Группировка по уровню скидки, мягко говоря, была бы не удобной, т.к. было бы 85 групп, которыми пришлось бы оперировать.Тогда для каждого пользователя будет создано правило с привязкой к пользователю через CSaleDiscount.
Однако, в документации к методам https://dev.1c-bitrix.ru/api_help/sale/classes/csalediscount/csalediscount__add.php информация, как всегда, в полном объеме, особенно скудно описана часть CONDITIONS и ACTIONS.
Более подробное описание есть в https://dev.1c-bitrix.ru/api_help/catalog/classes/ccatalogdiscount/ccatalogdiscount_add.php , но нет структуры и логики процесса.
Как и другие разработчики системы рекомендовали, для понимания логики правил корзины лучше всего создать типовое правило и изучить его:
Так, к примеру,
<?
CModule::IncludeModule('sale');
echo '<pre>';
print_r(unserialize(CSaleDiscount::GetByID(1)['CONDITIONS']));
echo '</pre>';
?>
выведет всю начинку CONDITIONS:
Array ( [CLASS_ID] => CondGroup [DATA] => Array ( [All] => AND [True] => True ) [CHILDREN] => Array ( [0] => Array ( [CLASS_ID] => CondMainUserId [DATA] => Array ( [Type] => CondIBIBlock [Value] => Equal [Unit] => 1 ) ) ) )
А [‘ACTIONS’]
<?
CModule::IncludeModule('sale');
echo '<pre>';
print_r(unserialize(CSaleDiscount::GetByID(1)['ACTIONS']));
echo '</pre>';
?>
покажет ACTIONS для правила с кодом 1 (GetByID(1)):
Array ( [CLASS_ID] => CondGroup [DATA] => Array ( [All] => AND ) [CHILDREN] => Array ( [0] => Array ( [CLASS_ID] => ActSaleBsktGrp [DATA] => Array ( [Type] => Discount [Value] => 5 [Unit] => Perc [All] => OR [True] => True ) [CHILDREN] => Array ( [0] => Array ( [CLASS_ID] => CondIBIBlock [DATA] => Array ( [logic] => Equal [value] => 2 ) ) ) ) ) )
Тогда совместив полученные знания мы получаем явную картину, как это все работает. Остается только выставить в нужном месте нужные операты и значения. Код получился такой:
CModule::IncludeModule("sale");
global $USER;
$discountValue = calcDisc(); //Функция для определения значения скидки
$Actions["CLASS_ID"] = "CondGroup";
$Actions["DATA"]["All"] = "AND";
$Actions["CHILDREN"][0]["CLASS_ID"] = "ActSaleBsktGrp";
$Actions["CHILDREN"][0]["DATA"]["Type"] = "Discount";
$Actions["CHILDREN"][0]["DATA"]["Value"] = $discountValue;
$Actions["CHILDREN"][0]["DATA"]["Unit"] = "Perc";
$Actions["CHILDREN"][0]["DATA"]["All"] = "OR";
$Actions["CHILDREN"][0]["DATA"]["True"] = "True";
$Actions["CHILDREN"][0]["CHILDREN"][0]["CLASS_ID"]="CondIBIBlock";
$Actions["CHILDREN"][0]["CHILDREN"][0]["DATA"]["logic"]="Equal";
$Actions["CHILDREN"][0]["CHILDREN"][0]["DATA"]["value"]="2";//на все, что лежит в ИБ=2
$Conditions["CLASS_ID"] = "CondGroup";
$Conditions["DATA"]["All"] = "AND";
$Conditions["DATA"]["True"] = "True";
$Conditions["CHILDREN"][0]["CLASS_ID"] = "CondMainUserId";
$Conditions["CHILDREN"][0]["DATA"]["Type"] = "CondIBIBlock";
$Conditions["CHILDREN"][0]["DATA"]["Value"] = "Equal";
$Conditions["CHILDREN"][0]["DATA"]["Unit"] =$USER->GetID();//привязка к текущему юзеру
$arFields = array(
"LID"=>"s1",
"NAME"=>$discountValue."% персональная скидка от ".date("d.m.y"),
"CURRENCY"=>"RUB",
"ACTIVE"=>"Y",
"USER_GROUPS"=>array(2),
"ACTIVE_FROM"=>ConvertTimeStamp(time(), "FULL"),
"CONDITIONS"=>$Conditions,
'ACTIONS' => $Actions,
"DISCOUNT_TYPE" => "P",
"LAST_LEVEL_DISCOUNT" => "Y",
"LAST_DISCOUNT" => "Y",
);
$rsUser = CUser::GetByID($USER->GetID());
$arUser = $rsUser->Fetch();
if (intval($arUser["UF_BASKETRULE"])){
CSaleDiscount::Update($arUser["UF_BASKETRULE"],$arFields);
}else{
$ID = CSaleDiscount::Add($arFields);
if(IntVal($ID) > 0) {
\Bitrix\Sale\Internals\DiscountGroupTable::updateByDiscount($ID, [2], "Y", true);
$user = new CUser;
$arFields = array(
"UF_BASKETRULE" => $ID
);
$ID = $user->Update($USER->GetID(),$arFields);
}
}
Дальше хотелось бы отдельно остановится на последней части кода. Поскольку скидка будет обновляться, то каждый раз методом add ее добавлять не стоит, но нужно обновлять правило, а обновить мы можем только по ID правила, а как получить правила, где участвует пользователь, я не знаю. Есть GetList, но его использование с выборкой CONDITIONS так и осталось черным ящиком (и не старался понять, если честно). Было принято решение в пользовательском поле просто хранить ID правила для текущего пользователя, тогда если $arUser[«UF_BASKETRULE»], то обновляем, иначе создаем и запоминаем ID правила для пользователя.
Профит. Все работает )