В данной статье рассмотрены ряд важных тем:
Для реализации наиболее или наименее выгодной скидки с помощью правил потребуется в помочь наш модуль - Произвольное 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С-Битрикс, или вы можете обратиться к нам (см. выше).