Выбрать курс
6  /  8

Как применить наиболее или наименее выгодную скидку в корзине в интернет-магазине на ЦМС 1С-Битрикс

В данной статье рассмотрены ряд важных тем:

  • Как вернуть примененные правила работы в текущей корзине покупателя с помощью АПИ.
  • Как рассчитать итоговую сумму корзины покупателя по отдельности по каждому правилу с помощью АПИ.
  • Как применить только одну наиболее выгодную скидку из актуальных правил работы с корзиной.
Внимание! Рассмотрены такие действия, как скидка в процентах (%) и фиксированные скидки; подарки НЕ взяты в расчёт.

В статье приведены фрагменты кода, описывающие принцип реализации. Для внедрение описанного подхода потребуется помощь программистов.

Мы также можем в этом помощь, но за отдельное вознаграждение. Обратиться за помощью можно в наш чат в правом нижнем углу нашего сайта (в рабочее время отвечаем достаточно оперативно). Но оставляем за собой право отказать в доработке без объяснения причин.

Для реализации наиболее или наименее выгодной скидки с помощью правил потребуется в помочь наш модуль - Произвольное PHP условие правил работы с корзиной. Свои (кастомные) условия в скидках.

Шаги следующие:

  1. С помощью АПИ 1С-Битрикс до вывода корзины (подключения компонента bitrix:sale.basket.basket) определяем какие правила работы применились для текущего покупателя.
  2. Проходим по найденным правилам работы с корзиной и применяем каждое по отдельности. Таким образом определяем сумму корзины на случай, если бы каждое правило применилось по отдельности.
  3. Находим правило с наибольшей (с максимальной выгодой для покупателя) сумме или наименьшей (менее всего выгодной для покупателя), в зависимости от требуемого. Записываем ИД найденного правила в глобальную переменную для дальнейшего использования в модуле. В нашем примере ниже рассмотрен случай с максимальной выгодой.
  4. С помощью модуля Произвольное 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С-Битрикс, или вы можете обратиться к нам (см. выше).