Рассчет стоимости доставки в карточке товара

Рассчет стоимости доставки в карточке товара

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

Начнем с того, что в ядре D7, для расчета доставки, нужно создать копию заказа, а уже затем выудить из нее данные по доставке. В нашем случае мы создаем заказ на 1 позицию и рассчитываем для нее стоимость доставки. Собственно, мы это без труда реализовали, но через некоторое время мы осознали весь масштаб проблемы. Мы получили десятки тысяч брошенных корзин. Т.е. битрикс посчитал, что все это брошенные корзины, каждый заход в карточку товара, генерировал брошенную корзину. Как же быть, подумали мы и углубились в изучение кода, ведь с документацией по D7 до сих пор беда(

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

\Bitrix\Main\Loader::includeModule('sale');   
$order = \Bitrix\Sale\Order::create("s1", 1);
$basket = \Bitrix\Sale\Basket::create("s1"); 
$item = $basket->createItem('catalog', $PRODUCT_ID); //$PRODUCT_ID – ИД товара
$item->setFields(array(
	'QUANTITY' => 1,
	'CURRENCY' => \Bitrix\Currency\CurrencyManager::getBaseCurrency(),
	'LID' => "s1", //Указываем ИД Вашего сайта
	'PRODUCT_PROVIDER_CLASS' => 'CCatalogProductProvider',
));
$order->setBasket($basket); // привязываем корзину к заказу
$order->setPersonTypeId(1);  //ставим тип плательщика, чтобы пройти ограничения доставки по типу плательщика корректно

Далее нужно создать объект отгрузки заказа и наполнить его необходимыми данными из корзины.

$shipmentCollection = $order->getShipmentCollection(); 
$shipment = $shipmentCollection->createItem();
$shipment->setFields(array(
	'CURRENCY' => $order->getCurrency()
));
$shipmentItemCollection = $shipment->getShipmentItemCollection(); 

foreach ($order->getBasket() as $item)
{
	$shipmentItem = $shipmentItemCollection->createItem($item);
	$shipmentItem->setQuantity($item->getQuantity());
}

Расчет стоимости доставки осуществляется в определенный город. Вот тут, конечно, необходимо его определить по IP, например, или еще как-то. Мы используем один из модулей, который и определяет местоположение пользователя. Чтобы система приняла нужный город, прописываем код города доставки куда хотим показать расчет в свойства фейкового заказа.

$propertyCollection = $order->getPropertyCollection();//получаем коллекцию свойств заказа
$property = $propertyCollection->getDeliveryLocation();//выбираем ту что отвечает за местоположение
$property->setValue($locationCode);//передаем местоположение
Далее получаем список доступных для данного местоположения доставок.
$deliveries = \Bitrix\Sale\Delivery\Services\Manager::getRestrictedObjectsList($shipment);
Обрабатываем в цикле все доступные доставки и запускаем расчет стоимости каждой из них. Для расчета каждый раз клонируем заказ и рассчитываем для него доставку. 
$arDeliveries = array();
foreach ($deliveries as $key => $deliveryObj)
{
			
	$clonedOrder = $order->createClone();//клонируем заказ
	$clonedShipment = SmgroupShop::getCurrentShipment($clonedOrder);//проверяем, системная это отгрузка или нет. Если нет – то возвращаем отгрузку.
	$clonedShipment->setField('CUSTOM_PRICE_DELIVERY', 'N');
			
			
	$calcResult = false;
	$calcOrder = false;
	$arDelivery = array();

Достаем отгрузку, и получаем данные о стоимости ее доставки.

$clonedShipment->setField('DELIVERY_ID', $deliveryObj->getId());
$clonedOrder->getShipmentCollection()->calculateDelivery();
$calcResult = $deliveryObj->calculate($clonedShipment);
$calcOrder = $clonedOrder;

На последнем шаге мы проверяем, удалось ли получить расчет стоимости доставки и если все прошло успешно, разберем все полученные данные, сформируем необходимый массив с необходимыми параметрами расчета.

if ($calcResult->isSuccess())
{
	if($deliveryObj->getId()!="1"){
		$arDelivery['id'] = $deliveryObj->getId();//получаем ИД доставки
		$arDelivery['logo_path'] = $deliveryObj->getLogotipPath();//получаем логотип
		$arDelivery['price'] = \Bitrix\Sale\PriceMaths::roundByFormatCurrency($calcResult->getPrice(), $calcOrder->getCurrency());//получаем стоимость доставки
		$arDelivery['price_formated'] = \SaleFormatCurrency($arDelivery['price'], $calcOrder->getCurrency());//форматируем стоимость в формат сайта
					
		$currentCalcDeliveryPrice = \Bitrix\Sale\PriceMaths::roundByFormatCurrency($calcOrder->getDeliveryPrice(), $calcOrder->getCurrency());
		if ($currentCalcDeliveryPrice >= 0 && $arDelivery['price'] != $currentCalcDeliveryPrice)
			{
			$arDelivery['discount_price'] = $currentCalcDeliveryPrice; //стоимость со скидкой
			$arDelivery['discount_price_formated'] = \SaleFormatCurrency($arDelivery['DELIVERY_DISCOUNT_PRICE'], $calcOrder->getCurrency());//стоимость со скидкой в нужной валюте
			}
					
			if (strlen($calcResult->getPeriodDescription()) > 0)
			{
				$arDelivery['period_text'] = $calcResult->getPeriodDescription();//время доставки
			}else{
				$arDelivery['period_text'] = "0";
			}
					
			$arDelivery["name"] = $deliveryObj->getNameWithParent();	//Название доставки
			$arDeliveries[] = $arDelivery;//итоговый массив
		}
}

В результате Вы получите на своем сайте актуальный список доставок для данного товара со стоимостью и сроками доставки. Сроки доставки можно отформатировать в нужном вам формате, чтобы клиент точнее понимал, когда ему стоит ждать заказ.


Комментировать