Your IP : 3.133.7.179


Current Path : /home/bitrix/ext_www/klimatlend.ua/bitrix/modules/sale/lib/exchange/
Upload File :
Current File : /home/bitrix/ext_www/klimatlend.ua/bitrix/modules/sale/lib/exchange/exportonecpackage.php

<?php
namespace Bitrix\Sale\Exchange;


use Bitrix\Main\ArgumentException;
use Bitrix\Sale\BasketItem;
use Bitrix\Sale\Exchange\Entity\EntityImport;
use Bitrix\Sale\Exchange\Entity\OrderImport;
use Bitrix\Sale\Exchange\Entity\PaymentImport;
use Bitrix\Sale\Exchange\Entity\ShipmentImport;
use Bitrix\Sale\Exchange\Entity\UserImportBase;
use Bitrix\Sale\Exchange\OneC\Converter;
use Bitrix\Sale\Exchange\OneC\ConverterFactory;
use Bitrix\Sale\Exchange\OneC\DocumentBase;
use Bitrix\Sale\Exchange\OneC\UserProfileDocument;
use Bitrix\Sale\IBusinessValueProvider;
use Bitrix\Sale\Internals\CollectionBase;
use Bitrix\Sale\Internals\Entity;
use Bitrix\Sale\Order;
use Bitrix\Sale\Payment;
use Bitrix\Sale\Result;
use Bitrix\Sale\Shipment;

abstract class ExportOneCPackage extends ExportOneCBase
{
	use PackageTrait
	{
		PackageTrait::load as protected load_AliasTrait;
	}
	use LoggerTrait;
	use BaseTrait;

	private static $instance = null;

	/**
	 * @return static
	 */
	public static function getInstance()
	{
		if(self::$instance === null)
		{
			self::$instance = new static();
		}
		return self::$instance;
	}

	private function __clone() {}
	private function __construct() {}

	/**
	 * @param array $fields
	 * @return Result
	 */
	protected function getItems(array $fields)
	{
		$result = new Result();

		$orderId = $fields['ORDER_ID'];

		$orderImport = ManagerExport::create(EntityType::ORDER);
		self::load($orderImport, array('ID'=>$orderId));

		/** @var \Bitrix\Sale\Order $order */
		$order = $orderImport->getEntity();

		$profileImport = ManagerExport::create(EntityType::USER_PROFILE);
		self::load($profileImport, array('ID'=>$order->getUserId()));

		$list = array_merge(
			$this->loadItemsByCollection($order->getPaymentCollection(), $order),
			$this->loadItemsByCollection($order->getShipmentCollection(), $order));

		$list[] = $orderImport;
		$list[] = $profileImport;

		$this->initLogger($list);

		$result->setData($list);
		return $result;
	}

	/**
	 * @param CollectionBase $collection
	 * @param Order $order
	 * @return array
	 */
	protected function loadItemsByCollection(CollectionBase $collection, Order $order)
	{
		$list = array();

		if(count($collection)>0)
		{
			foreach ($collection as $entity)
			{
				if($entity instanceof Shipment)
				{
					if($entity->isSystem())
						continue;
				}

				$typeId = $this->resolveEntityTypeId($entity);

				/** @var EntityImport $entityExport */
				$entityExport = ManagerExport::create($typeId);
				self::load($entityExport, array('ID'=>$entity->getId()), $order);
				$list[] = $entityExport;
			}
		}

		return $list;
	}

	/**
	 * @param Entity $entity
	 * @return int
	 */
	protected function resolveEntityTypeId(Entity $entity)
	{
		$typeId = EntityType::UNDEFINED;

		if($entity instanceof Order)
			$typeId = OrderImport::resolveEntityTypeId($entity);
		elseif($entity instanceof Payment)
			$typeId = PaymentImport::resolveEntityTypeId($entity);
		elseif($entity instanceof Shipment)
			$typeId = ShipmentImport::resolveEntityTypeId($entity);

		return $typeId;
	}

	/**
	 * @param ImportBase[] $items
	 * @return Result
	 */
	protected function convert(array $items)
	{
		$result = new Result();
		$list = array();

		$this->convertEntityFields($items);

		foreach ($items as $item)
		{
			$list[] = $this->convertEntity($item);
		}

		$this->convertDocumentFields($list);

		$list = $this->modifyDocumentsCollection($list);

		if($result->isSuccess())
		{
			$result->setData($list);
		}
		return $result;
	}

	/**
	 * @param DocumentBase[] $documents
	 */
	protected function convertDocumentFields(array $documents)
	{
		$documentOrder = $this->getDocumentByTypeId(EntityType::ORDER, $documents);
		$orderFields = $documentOrder->getFieldValues();

		/** @var UserProfileDocument $documentProfile */
		$documentProfile = $this->getDocumentByTypeId(EntityType::USER_PROFILE, $documents);
		$orderFields['AGENT'] = $documentProfile->getFieldValues();

		$documentOrder->setFields($orderFields);
	}

	/**
	 * @param ImportBase[] $items
	 * @return Result;
	 */
	protected function convertEntityFields(array $items)
	{
		$result = new Result();

		$orderImport = $this->getEntityByTypeId(EntityType::ORDER, $items);
		/** @var ProfileImport $profileImport */
		$profileImport = $this->getEntityByTypeId(EntityType::USER_PROFILE, $items);

		//region business value order profile shipment payment
		$this->prepareEntityFieldsBusinessValue($orderImport);
		$this->prepareEntityFieldsBusinessValue($profileImport, $orderImport);

		foreach ($items as $item)
		{
			if($item instanceof ShipmentImport || $item instanceof PaymentImport)
			{
				$this->prepareEntityFieldsBusinessValue($item);
			}
		}
		//endregion

		//region payment.lid && payment.vesion
		$orderFields = $orderImport->getFieldValues();
		foreach ($items as $item)
		{
			if($item instanceof PaymentImport)
			{
				$paymentFields = $item->getFieldValues();
				$paymentFields['TRAITS']['LID'] = $orderFields['TRAITS']['LID'];
				$paymentFields['TRAITS']['VERSION'] = $orderFields['TRAITS']['VERSION'];
				$item->setFields($paymentFields);
			}
		}
		//endregion

		//region shipment.lid && shipment.version
		$orderFields = $orderImport->getFieldValues();
		foreach ($items as $item)
		{
			if($item instanceof ShipmentImport)
			{
				$shipmentFields = $item->getFieldValues();
				$shipmentFields['TRAITS']['LID'] = $orderFields['TRAITS']['LID'];
				$shipmentFields['TRAITS']['VERSION'] = $orderFields['TRAITS']['VERSION'];
				$item->setFields($shipmentFields);
			}
		}
		//endregion

		$this->addItemOrderDelivery($items);

		return $result;
	}

	/**
	 * @param ImportBase[] $items
	 */
	protected function addItemOrderDelivery(array $items)
	{
		$orderImport = $this->getEntityByTypeId(EntityType::ORDER, $items);

		//region shipment.items ORDER_DELIVERY
		$orderFields = $orderImport->getFieldValues();
		foreach ($items as $item)
		{
			if($item instanceof ShipmentImport)
			{
				$shipmentFields = $item->getFieldValues();
				/** @var Shipment $shipmemt */
				$shipmemt = $item->getEntity();
				if($shipmemt->getPrice()>0)
				{

					$shipmentFields['ITEMS'][] = array_merge(
						array(
							'PRODUCT_XML_ID'=>ImportOneCBase::DELIVERY_SERVICE_XMLID,
							'NAME'=>DocumentBase::getLangByCodeField(ImportOneCBase::DELIVERY_SERVICE_XMLID),
							'MEASURE_CODE'=>Converter::MEASURE_CODE_DEFAULT,
							'KOEF'=>Converter::KOEF_DEFAULT,
							'PRICE'=>$shipmemt->getPrice(),
							'QUANTITY'=>1
						),
						$this->getVatRateByShipment($item, $this->getSummOrderTaxes($orderFields['TAXES']))
					);
				}
				$item->setFields($shipmentFields);
			}
		}
		//endregion

		//region order.items ORDER_DELIVERY
		$orderFields = $orderImport->getFieldValues();
		foreach ($items as $item)
		{
			if($item instanceof ShipmentImport)
			{
				$shipmentItems = $this->getProductsItems($item->getFieldValues());
				if($this->deliveryServiceExists($shipmentItems))
				{
					$orderFields['ITEMS'][] = $this->getDeliveryServiceItem($shipmentItems);
				}
			}
		}
		$orderImport->setFields($orderFields);
		//endregion
	}

	/**
	 * @param array $list
	 * @return mixed|null
	 */
	protected function getDeliveryServiceItem(array $list)
	{
		foreach ($list as $k=>$items)
		{
			if($items['PRODUCT_XML_ID'] == ImportOneCBase::DELIVERY_SERVICE_XMLID)
			{
				return $items;
			}
		}

		return null;
	}

	/**
	 * @param $taxes
	 * @return int
	 */
	protected function getSummOrderTaxes($taxes)
	{
		$orderTax = 0;
		foreach ($taxes as $tax)
		{
			$tax["VALUE_MONEY"] = roundEx($tax["VALUE_MONEY"], 2);
			$orderTax += $tax["VALUE_MONEY"];
		}
		return $orderTax;
	}

	/**
	 * @param ShipmentImport $item
	 * @param $orderTax
	 * @return array
	 */
	protected function getVatRateByShipment(ShipmentImport $item, $orderTax)
	{
		$result = array();

		$shipmentFields = $item->getFieldValues();
		/** @var Shipment $shipmemt */
		$shipmemt = $item->getEntity();
		if($shipmemt->getPrice()>0)
		{
			$vatRate = 0;
			$vatSum = 0;
			$order = $shipmemt->getParentOrder();
			/** @var BasketItem $basket */
			foreach ($order->getBasket() as $basket)
			{
				$vatRate = $basket->getVatRate();
				$basketVatSum = $basket->getPrice()/($vatRate+1) * $vatRate;
				$vatSum += roundEx($basketVatSum * $basket->getQuantity(), 2);
			}

			$tax = roundEx((($shipmemt->getPrice() / ($vatRate+1)) * $vatRate), 2);

			if($orderTax > $vatSum && $orderTax == roundEx($vatSum + $tax, 2))
			{
				$result = array('VAT_RATE'=>$vatRate*100);
			}
		}
		return $result;
	}

	/**
	 * @param DocumentBase $document
	 * @param UserProfileDocument $documentProfile
	 */
	protected function prepareDocumentFieldsDeliveryAddress(DocumentBase $document, UserProfileDocument $documentProfile)
	{
		$fields = $document->getFieldValues();
		$profileFields = $documentProfile->getFieldValues();

		$fields['REK_VALUES'] = is_array($fields['REK_VALUES'])? $fields['REK_VALUES']:array();
		$profileFields['REK_VALUES'] = is_array($profileFields['REK_VALUES'])? $profileFields['REK_VALUES']:array();

		$fields['REK_VALUES'] = array_merge($fields['REK_VALUES'], $profileFields['REK_VALUES']);

		$document->setFields($fields);
	}

	/**
	 * @param ImportBase $item
	 * @param OrderImport $orderImport
	 * @throws ArgumentException
	 */
	protected function prepareEntityFieldsBusinessValue(ImportBase $item, OrderImport $orderImport=null)
	{
		if(!($item instanceof OrderImport || $item instanceof ShipmentImport || $item instanceof PaymentImport || $item instanceof UserImportBase))
			throw new ArgumentException("Entity must be instanceof OrderImport or ShipmentImport or PaymentImport or ProfileImport");

		$fields = $item->getFieldValues();

		/** @var IBusinessValueProvider $provider */
		$provider = ($item instanceof UserImportBase ? $orderImport->getEntity():$item->getEntity());
		$fields['BUSINESS_VALUE'] = $item::getBusinessValue($provider);

		$item->setFields($fields);
	}

	/**
	 * @param DocumentBase[] $documents
	 * @param int $level
	 * @return Result
	 */
	protected function outputXmlDocuments(array $documents, $level=0)
	{
		$result = new Result();
		$list = array();

		foreach ($documents as $document)
		{
			$list[] = $this->outputXmlDocument($document, $level);
		}
		$result->setData($list);

		return $result;
	}

	/**
	 * @param DocumentBase $document
	 * @param int $level
	 * @return string
	 */
	protected function outputXmlDocument(DocumentBase $document, $level)
	{
		$xml = $document->openNodeDirectory($level, $document::getLangByCodeField($document->getNameNodeDocument()));
		$xml .= $document->output($level+1);
		$xml .= $document->closeNodeDirectory($level, $document::getLangByCodeField($document->getNameNodeDocument()));
		return $xml;
	}

	/**
	 * @param DocumentBase[] $list
	 * @return DocumentBase[]
	 */
	protected function modifyDocumentsCollection(array $list)
	{
		$result = array();
		foreach ($list as $document)
		{
			if(!($document instanceof UserProfileDocument))
				$result[] = $document;
		}
		return $result;
	}

	/**
	 * @param EntityImport[] $items
	 */
	protected function initLogger(array $items)
	{
		foreach ($items as $item)
		{
			$item->initLogger();
		}
	}

	/**
	 * @param ImportBase $item
	 * @return DocumentBase
	 */
	protected function convertEntity(ImportBase $item)
	{
		$params = $item->getFieldValues();

		$settings = ManagerImport::getSettingsByType($item->getOwnerTypeId());

		$convertor = $this->converterFactoryCreate($item->getOwnerTypeId());
		$convertor->loadSettings($settings);

		$fields = $convertor->externalize($params);

		$document = $this->documentFactoryCreate($item->getOwnerTypeId());
		$document->setFields($fields);

		return $document;
	}

	/**
	 * @param DocumentBase[] $documents
	 * @return Result
	 */
	protected function export(array $documents)
	{
		$result = new Result();

		$xml = '';
		$r = $this->outputXmlDocuments($documents);
		if($r->isSuccess())
		{
			$xml = implode('', $r->getData());

			$this->setRawData($xml);
		}

		return $result->setData([$xml]);
	}

	/**
	 * @param ImportBase $item
	 * @param array $fields
	 * @param null $order
	 */
	protected static function load(ImportBase $item, array $fields, $order=null)
	{
		static::load_AliasTrait($item, $fields, $order);
		$item->initFields();
	}

	/**
	 * @param ImportBase[] $items
	 * @return Result
	 */
	protected function logger(array $items)
	{
		/** @var OrderImport $orderItem */
		$orderItem = $this->getEntityByTypeId(EntityType::ORDER, $items);
		return $this->loggerEntitiesPackage($items, $orderItem);
	}
}