В данной статье рассмотрены ряд важных тем:
Внимание! Рассмотрены такие действия, как скидка в процентах (%) и фиксированные скидки; подарки НЕ взяты в расчёт.
В статье приведены фрагменты кода, описывающие принцип реализации. Для внедрение описанного подхода потребуется помощь программистов.
Мы также можем в этом помощь, но за отдельное вознаграждение. Обратиться за помощью можно в наш чат в правом нижнем углу нашего сайта (в рабочее время отвечаем достаточно оперативно). Но оставляем за собой право отказать в доработке без объяснения причин.
Для реализации наиболее или наименее выгодной скидки с помощью правил потребуется в помочь наш модуль - Произвольное PHP условие правил работы с корзиной. Свои (кастомные) условия в скидках.
Шаги следующие:
Ниже рассмотрен код, который необходимо разместить в init.php. В коде есть множество коммитов, которые отражает техническую сторону реализации и будет очень полезно для ознакомления разработчикам.
AddEventHandler("main", "OnBeforeProlog", Array("CDev", "OnBeforePrologHandler"));
class CDev
{
//вспомогательная функция: определяет правило с масимальной выгодой
public static function __sc_discounts_calculation()
{
if (!CModule::IncludeModule('sale') && !CModule::IncludeModule('catalog'))
return false;
$max_cond_id = $max_price = 0;
//возвращаем текущую корзину покупателя
$basket = \Bitrix\Sale\Basket::loadItemsForFUser(
\Bitrix\Sale\Fuser::getId(),
\Bitrix\Main\Context::getCurrent()->getSite()
);
//узнаем примененные правила работы с корзиной в корзине
$discounts = \Bitrix\Sale\Discount::loadByBasket($basket);
$res = $discounts->calculate();
$result = $discounts->getApplyResult(true);
//если есть применные правила
if (!empty($result["DISCOUNT_LIST"]) && is_array($result["DISCOUNT_LIST"]))
{
foreach ($result["DISCOUNT_LIST"] as $id => $item)
{
//по очереди исключаем правило и рассчитываем окончательную сумму в корзине
$discounts->setApplyResult([
'DISCOUNT_LIST' => [
$id => 'N'
]
]);
$res = $discounts->calculate();
$sub_result = $discounts->getApplyResult(true);
if (!empty($sub_result["PRICES"]["BASKET"]) && is_array($sub_result["PRICES"]["BASKET"]))
{
foreach ($sub_result["PRICES"]["BASKET"] as $basket_price)
{
//определяем правило с максимальной скидкой
if ($basket_price["PRICE"] > $max_price)
{
$max_price = $basket_price["PRICE"];
//реальный ИД правила работы с корзиной с максимальной скидкой
$max_cond_id = $item["REAL_DISCOUNT_ID"];
}
}
}
}
//если нашли реальный ИД правила работы с корзиной с максимальной скидкой
if ($max_cond_id > 0)
{
//пишем в глобальную переменную для использования во внутренних обработчиках событий
$GLOBALS["SCODER_MAXCOND_ID"] = $max_cond_id;
}
}
}
//Событие "OnBeforeProlog" вызывается в выполняемой части пролога сайта
public static function OnBeforePrologHandler()
{
global $APPLICATION;
if (CModule::IncludeModule('sale') && CModule::IncludeModule('catalog'))
{
///personal/cart/ - если у вас корзина находится по другому пути, то нужно указать его
if (strpos($APPLICATION->GetCurPage(false),"/personal/cart/") === 0)
{
CDev::__sc_discounts_calculation();
}
}
//вспомогательная функция: определяет какое правило можно применять. ФУНКЦИЯ СПЕЦИАЛЬНЫМ ОБРАЗОМ УКАЗЫВАЕТСЯ В ДОПОЛНИТЕЛЬНЫХ НАСТРОЙКАХ ПРАВИЛ РАБОТЫ С КОРЗИНОЙ
public static function __check_best_offer($arOrder = array(), $cond_id = 0)
{
if ($cond_id > 0
&& !empty($GLOBALS["SCODER_MAXCOND_ID"]))
{
//если реальный ИД правила работы с корзиной с максимальной скидкой "НЕ равно" нашему правилу, то отменяем правило
if ($GLOBALS["SCODER_MAXCOND_ID"] != $cond_id)
return false;
}
return true;
}
}
Немного о функции CDev::__check_best_offer($arOrder,732), которая вызывается в дополнительных условиях каждого правила работы с корзиной. Выглядит это следующим образом:
Разумеется, когда правил уже достаточно много создано, то дописывать подобное условие не очень удобно. Но это тоже можно пройтись с помощью скрипта и дописать. С этим может относительно легко справиться любой программист, специализирующийся на ЦМС 1С-Битрикс, или вы можете обратиться к нам (см. выше).