Your IP : 216.73.216.86


Current Path : /var/www/homesaver/www/bitrix/modules/sale/handlers/delivery/yandextaxi/
Upload File :
Current File : /var/www/homesaver/www/bitrix/modules/sale/handlers/delivery/yandextaxi/ratecalculator.php

<?php

namespace Sale\Handlers\Delivery\YandexTaxi;

use Bitrix\Main\Error;
use Bitrix\Main\Localization\Loc;
use Bitrix\Sale\Delivery\CalculationResult;
use Bitrix\Sale\Shipment;
use Sale\Handlers\Delivery\YandexTaxi\Api\Api;
use Sale\Handlers\Delivery\YandexTaxi\Api\RequestEntity\Address;
use Sale\Handlers\Delivery\YandexTaxi\Api\RequestEntity\ClientRequirements;
use Sale\Handlers\Delivery\YandexTaxi\Api\RequestEntity\Estimation;
use Sale\Handlers\Delivery\YandexTaxi\Api\RequestEntity\OfferEstimation;
use Sale\Handlers\Delivery\YandexTaxi\Api\RequestEntity\TransportClassification;
use Sale\Handlers\Delivery\YandexTaxi\ClaimBuilder\ClaimBuilder;

/**
 * Class RateCalculator
 * @package Sale\Handlers\Delivery\YandexTaxi
 * @internal
 */
final class RateCalculator
{
	private const ERROR_CODE = 'DELIVERY_CALCULATION';

	/** @var Api */
	protected $api;

	/** @var ClaimBuilder */
	protected $claimBuilder;

	/** @var TariffsChecker */
	protected $tariffsChecker;

	/**
	 * RateCalculator constructor.
	 * @param Api $api
	 * @param ClaimBuilder $claimBuilder
	 * @param TariffsChecker $tariffsChecker
	 */
	public function __construct(Api $api, ClaimBuilder $claimBuilder, TariffsChecker $tariffsChecker)
	{
		$this->api = $api;
		$this->claimBuilder = $claimBuilder;
		$this->tariffsChecker = $tariffsChecker;
	}

	/**
	 * @param Shipment $shipment
	 * @return CalculationResult
	 * @throws \Bitrix\Main\ArgumentException
	 * @throws \Bitrix\Main\ArgumentNullException
	 * @throws \Bitrix\Main\ArgumentOutOfRangeException
	 * @throws \Bitrix\Main\ObjectNotFoundException
	 */
	public function calculateRate(Shipment $shipment): CalculationResult
	{
		$result = new CalculationResult();

		$addressFromResult = $this->claimBuilder->buildAddressFrom($shipment);
		if (!$addressFromResult->isSuccess())
		{
			return $result->addErrors(
				$this->getFormattedErrors($addressFromResult->getErrors())
			);
		}
		/** @var Address $addressFrom */
		$addressFrom = $addressFromResult->getData()['ADDRESS'];

		$addressToResult = $this->claimBuilder->buildAddressTo($shipment);
		if (!$addressToResult->isSuccess())
		{
			return $result->addErrors(
				$this->getFormattedErrors($addressToResult->getErrors())
			);
		}
		/** @var Address $addressTo */
		$addressTo = $addressToResult->getData()['ADDRESS'];

		$tariffResult = $this->claimBuilder->getTaxiClass($shipment);

		if (!$tariffResult->isSuccess())
		{
			return $result->addErrors(
				$this->getFormattedErrors($tariffResult->getErrors())
			);
		}

		$taxiClass = $tariffResult->getData()['tariff']['name'];

		if (ClaimBuilder::isOffersCalculateMethod($taxiClass))
		{
			$buildClientReqResult = $this->claimBuilder->buildClientRequirements($shipment);
		}
		else
		{
			$buildClientReqResult = $this->claimBuilder->buildTransportClassification($shipment);
		}

		if (!$buildClientReqResult->isSuccess())
		{
			return $result->addErrors($buildClientReqResult->getErrors());
		}
		/** @var ClientRequirements|TransportClassification $clientRequirements */
		$clientRequirements = $buildClientReqResult->getData()['REQUIREMENTS'];

		$isTariffAvailable = $this->tariffsChecker->isTariffAvailableByShipment(
			$taxiClass,
			$shipment
		);

		if (is_null($isTariffAvailable))
		{
			return $result->addError(
				new Error(Loc::getMessage('SALE_YANDEX_TAXI_INVALID_TOKEN'), static::ERROR_CODE)
			);
		}

		if ($isTariffAvailable === false)
		{
			return $result->addError(
				new Error(Loc::getMessage('SALE_YANDEX_TAXI_TARIFF_NOT_SUPPORTED'), static::ERROR_CODE)
			);
		}

		$shippingItemCollection = $this->claimBuilder->getShippingItemCollection($shipment);
		$validationResult = $shippingItemCollection->isValid();
		if (!$validationResult->isSuccess())
		{
			return $result->addErrors(
				$this->getFormattedErrors($validationResult->getErrors())
			);
		}

		if ($clientRequirements instanceof ClientRequirements)
		{
			$estimationRequest = new OfferEstimation();
		}
		else
		{
			$estimationRequest = new Estimation();
		}

		$estimationRequest
			->addRoutePoint($addressFrom->setId(ClaimBuilder::SOURCE_ROUTE_POINT_ID))
			->addRoutePoint($addressTo->setId(ClaimBuilder::DESTINATION_ROUTE_POINT_ID))
		;

		foreach ($shippingItemCollection as $shippingItem)
		{
			$estimationRequest->addItem($shippingItem);
		}

		if ($clientRequirements instanceof ClientRequirements)
		{
			$estimationRequest->setRequirements($clientRequirements);
			$priceResult = $this->api->offersCalculate($estimationRequest);
		}
		else
		{
			$estimationRequest->setSkipDoorToDoor(!$this->claimBuilder->isDoorDeliveryRequired($shipment));
			$estimationRequest->setRequirements($clientRequirements);
			$priceResult = $this->api->checkPrice($estimationRequest);
		}

		if (!$priceResult->isSuccess())
		{
			return $result->addError(
				new Error(Loc::getMessage('SALE_YANDEX_TAXI_RATE_CALCULATE_ERROR'), static::ERROR_CODE)
			);
		}

		if ($priceResult->getCurrency() !== $shipment->getCollection()->getOrder()->getCurrency())
		{
			return $result->addError(
				new Error(
					Loc::getMessage('SALE_YANDEX_TAXI_RATE_CALCULATE_CURRENCY_MISMATCH_ERROR'),
					static::ERROR_CODE
				)
			);
		}

		$result->setDeliveryPrice($priceResult->getPrice());
		$resultData = $priceResult->getData();
		if (isset($resultData))
		{
			$result->setData($resultData);
		}

		return $result;
	}

	/**
	 * @param array $errors
	 * @return array
	 */
	private function getFormattedErrors(array $errors)
	{
		$result = [];

		foreach ($errors as $error)
		{
			$result[] = new Error($error->getMessage(), static::ERROR_CODE);
		}

		return $result;
	}
}