403Webshell
Server IP : 80.87.202.40  /  Your IP : 216.73.216.169
Web Server : Apache
System : Linux rospirotorg.ru 5.14.0-539.el9.x86_64 #1 SMP PREEMPT_DYNAMIC Thu Dec 5 22:26:13 UTC 2024 x86_64
User : bitrix ( 600)
PHP Version : 8.2.27
Disable Function : NONE
MySQL : OFF |  cURL : ON |  WGET : ON |  Perl : ON |  Python : OFF |  Sudo : ON |  Pkexec : ON
Directory :  /home/bitrix/ext_www/rospirotorg.ru/bitrix/modules/sale/lib/delivery/requests/

Upload File :
current_dir [ Writeable] document_root [ Writeable]

 

Command :


[ Back ]     

Current File : /home/bitrix/ext_www/rospirotorg.ru/bitrix/modules/sale/lib/delivery/requests/manager.php
<?php

namespace Bitrix\Sale\Delivery\Requests;

use Bitrix\Main;
use Bitrix\Main\Loader;
use Bitrix\Sale\Order;
use Bitrix\Sale\ResultWarning;
use Bitrix\Sale\Shipment;
use Bitrix\Sale\Internals;
use Bitrix\Sale\EntityMarker;
use Bitrix\Main\Localization\Loc;
use Bitrix\Sale\Delivery\Services;

Loc::loadMessages(__FILE__);

/**
 * Class Manager
 * @package Bitrix\Sale\Delivery\Requests
 * Manages the lifecycle of delivery requests items
 */
final class Manager
{
	public const STATUS_PREPARED = 0;
	public const STATUS_SENT = 10;
	public const STATUS_PROCESSED = 20;

	const FORM_FIELDS_TYPE_CREATE = 10;
	const FORM_FIELDS_TYPE_ADD = 20;
	const FORM_FIELDS_TYPE_ACTION = 30;

	public const REQUEST_CREATED_EVENT_CODE = 'OnDeliveryRequestCreated';
	public const REQUEST_DELETED_EVENT_CODE = 'OnDeliveryRequestDeleted';
	public const REQUEST_UPDATED_EVENT_CODE = 'OnDeliveryRequestUpdated';
	public const REQUEST_ACTION_EXECUTED_EVENT_CODE = 'OnDeliveryRequestActionExecuted';

	public const MESSAGE_RECEIVED_EVENT_CODE = 'OnDeliveryRequestMessageReceived';
	public const MESSAGE_MANAGER_ADDRESSEE = 'MANAGER';
	public const MESSAGE_RECIPIENT_ADDRESSEE = 'RECIPIENT';

	public const EXTERNAL_STATUS_SEMANTIC_SUCCESS = 'success';
	public const EXTERNAL_STATUS_SEMANTIC_PROCESS = 'process';

	protected static $isChangedShipmentNeedsMark = true;

	/**
	 * @param int $shipmentId
	 * @param int $requestId
	 * @return Result
	 * @throws Main\ArgumentException
	 */
	public static function getDeliveryRequestShipmentContent($requestId, $shipmentId)
	{
		$result = new Result();

		if (intval($shipmentId) <= 0)
		{
			$result->addError(new Main\Error(Loc::getMessage('SALE_DLVR_REQ_MNGR_ERROR_SHIPMENT_ID')));
			return $result;
		}

		$res = ShipmentTable::getList(array(
			'filter' => array(
				'=SHIPMENT_ID' => $shipmentId
			),
			'select' => array(
				'*',
				'DELIVERY_ID' => 'SHIPMENT.DELIVERY_ID'
			)
		));

		if (!($row = $res->fetch()))
		{
			$result->addError(
				new Main\Error(
					Loc::getMessage(
						'SALE_DLVR_REQ_MNGR_ERROR_SHIPMENT_NOT_IN_REQUEST',
						array('#SHIPMENT_ID#' => $shipmentId)
			)));

			return $result;
		}

		$deliveryId = intval($row['DELIVERY_ID']);

		if ($deliveryId <= 0)
		{
			$result->addError(
				new Main\Error(
					Loc::getMessage(
						'SALE_DLVR_REQ_MNGR_ERROR_DELIVERY_NOT_FOUND',
						array('#SHIPMENT_LINK#' => Helper::getShipmentEditLink($shipmentId)))));

			return $result;
		}

		$deliveryRequestHandler = self::getDeliveryRequestHandlerByDeliveryId($deliveryId);

		if (!$deliveryRequestHandler)
		{
			$result->addError(
				new Main\Error(
					Loc::getMessage(
						'SALE_DLVR_REQ_MNGR_ERROR_DELIVERY_NOT_SUPPORT',
						array('#DELIVERY_LINK#' => Helper::getDeliveryEditLink($deliveryId)))));

			return $result;
		}

		return $deliveryRequestHandler->getShipmentContent($requestId, $shipmentId);
	}

	/**
	 * @param Shipment $shipment
	 * @return array Shipment actions
	 * @throws Main\ArgumentNullException
	 */
	public static function getDeliveryRequestShipmentActions(Shipment $shipment)
	{
		$deliveryId = $shipment->getDeliveryId();

		if ($deliveryId <= 0)
			return array();

		if (!($delivery = Services\Manager::getObjectById($deliveryId)))
			return array();

		if (!($deliveryRequestHandler = $delivery->getDeliveryRequestHandler()))
			return array();

		return $deliveryRequestHandler->getShipmentActions($shipment);
	}

	/**
	 * @param int $requestId
	 * @return array Request actions
	 * @throws Main\ArgumentNullException
	 */
	public static function getDeliveryRequestActions($requestId)
	{
		$result = array();
		$deliveryRequestHandler = self::getDeliveryRequestHandlerByRequestId($requestId);

		if ($deliveryRequestHandler)
			$result = $deliveryRequestHandler->getActions($requestId);

		return $result;
	}

	/**
	 * @param int $requestId
	 * @return HandlerBase|null  Delivery request handler
	 * @throws Main\ArgumentNullException
	 */
	protected static function getDeliveryRequestHandlerByRequestId($requestId)
	{
		if (intval($requestId) <= 0)
			return null;

		if (!($requestFields = RequestTable::getById($requestId)->fetch()))
			return null;

		if (intval($requestFields['DELIVERY_ID']) <= 0)
			return null;

		return self::getDeliveryRequestHandlerByDeliveryId($requestFields['DELIVERY_ID']);
	}

	/**
	 * @param int $deliveryId
	 * @return HandlerBase|null Delivery request handler
	 * @throws Main\ArgumentNullException
	 * @throws Main\SystemException
	 */

	public static function getDeliveryRequestHandlerByDeliveryId($deliveryId)
	{
		if (intval($deliveryId) <= 0)
			return null;

		if (!($delivery = Services\Manager::getObjectById($deliveryId)))
			return null;

		return $delivery->getDeliveryRequestHandler();
	}

	/**
	 * @param int $deliveryId
	 * @param int[] $shipmentIds
	 * @param array $additional Additional info required for creation. Depends on delivery service.
	 * @return Result
	 * @throws Main\ArgumentException
	 * @throws Main\ArgumentNullException
	 * @throws Main\SystemException
	 * @throws \Exception
	 */

	public static function createDeliveryRequest($deliveryId, array $shipmentIds, array $additional = array())
	{
		$result = new Result();

		if (!($deliveryRequestHandler = self::getDeliveryRequestHandlerByDeliveryId($deliveryId)))
		{
			$result->addError(
				new Main\Error(
					Loc::getMessage(
						'SALE_DLVR_REQ_MNGR_ERROR_NOT_SUPPORT',
						array('#DELIVERY_LINK#' => Helper::getDeliveryEditLink($deliveryId))
			)));
			self::sendOnCreateDeliveryRequestEvent($result, $deliveryId, $shipmentIds, $additional);

			return $result;
		}

		/** @var ShipmentResult[] $checkResults */
		$checkResults = self::checkShipmentIdsBeforeAdd($shipmentIds);

		foreach ($checkResults as $res)
		{
			if ($res->isSuccess())
				continue;

			$result->addResult(
				self::processShipmentResult(
					$res
			));

			unset($shipmentIds[array_search($res->getInternalId(), $shipmentIds)]);
		}

		if (empty($shipmentIds))
		{
			$result->addError(new Main\Error(Loc::getMessage('SALE_DLVR_REQ_MNGR_ERROR_SHP_ABSENT')));
			self::sendOnCreateDeliveryRequestEvent($result, $deliveryId, $shipmentIds, $additional);

			return $result;
		}

		$handlerResult = $deliveryRequestHandler->create($shipmentIds, $additional);
		if ($handlerResult->isSuccess())
		{
			$result->addResults($handlerResult->getResults());
		}
		else
		{
			$result->addErrors($handlerResult->getErrors());

			foreach ($handlerResult->getShipmentResults() as $sRes)
			{
				$result->addResult(self::processShipmentResult($sRes));
			}
			self::sendOnCreateDeliveryRequestEvent($result, $deliveryId, $shipmentIds, $additional);

			return $result;
		}

		$results = $result->getResults();

		if (!is_array($results) || empty($results))
		{
			$result->addError(new Main\Error(Loc::getMessage('SALE_DLVR_REQ_MNGR_ERROR_RES_UNKNOWN')));

			self::sendOnCreateDeliveryRequestEvent($result, $deliveryId, $shipmentIds, $additional);

			return $result;
		}

		/** @var  ShipmentResult|RequestResult $requestResult */
		foreach ($results as $resId => $requestResult)
		{
			if ($requestResult instanceof ShipmentResult)
			{
				$requestResult = self::processShipmentResult($requestResult);
			}
			elseif ($requestResult instanceof RequestResult)
			{
				$requestId = 0;
				/** @var RequestResult  $requestResult*/
				if ($requestResult->isSuccess())
				{
					$handlerResultData = $handlerResult->getData();

					$res = RequestTable::add(array(
						'DELIVERY_ID' => $deliveryRequestHandler->getHandlingDeliveryServiceId(),
						'EXTERNAL_ID' => $requestResult->getExternalId(),
						'CREATED_BY' => ($GLOBALS['USER'] instanceof \CUser && (int)$GLOBALS['USER']->GetID() > 0)
							? (int)$GLOBALS['USER']->GetID()
							: null,
						'STATUS' => Manager::STATUS_SENT,
						'EXTERNAL_STATUS' => $handlerResultData['STATUS'] ?? null,
						'EXTERNAL_STATUS_SEMANTIC' => $handlerResultData['STATUS_SEMANTIC'] ?? null,
						'EXTERNAL_PROPERTIES' => (isset($handlerResultData['PROPERTIES']) && is_array($handlerResultData['PROPERTIES']))
							? $handlerResultData['PROPERTIES']
							: [],
					));

					if (!$res->isSuccess())
					{
						$requestResult->addErrors($res->getErrors());
						continue;
					}

					$requestId = $res->getId();

					if ($requestId > 0)
					{
						$requestResult->setInternalId($requestId);
					}
				}

				$shipmentsResults = $requestResult->getShipmentResults();

				if (empty($shipmentsResults))
					continue;

				foreach ($shipmentsResults as $sResIdx => $shipmentResult)
				{
					$shipmentsResults[$sResIdx] = self::processShipmentResult($shipmentResult, $requestId);
				}

				$requestResult->setResults($shipmentsResults);
			}
			else
			{
				$result->addError(new Main\Error(Loc::getMessage('SALE_DLVR_REQ_MNGR_ERROR_ANSW_TYPE').' "'.get_class($requestResult).'"'));
				continue;
			}

			$results[$resId] = $requestResult;
		}

		$result->setResults($results);
		self::sendOnCreateDeliveryRequestEvent($result, $deliveryId, $shipmentIds, $additional);

		return $result;
	}

	private static function sendOnCreateDeliveryRequestEvent(
		Result $result,
		int $deliveryId,
		array $shipmentIds,
		array $additional
	)
	{
		(new Main\Event(
			'sale',
			self::REQUEST_CREATED_EVENT_CODE,
			[
				'DELIVERY_ID' => $deliveryId,
				'SHIPMENT_IDS' => $shipmentIds,
				'ADDITIONAL' => $additional,
				'RESULT' => $result,
			]
		))->send();
	}

	/**
	 * @param ShipmentResult $result
	 * @param int $requestId
	 * @return ShipmentResult
	 */
	protected static function processShipmentResult($result, $requestId = 0)
	{
		if (!($result instanceof ShipmentResult))
			return $result;

		$shipmentId = $result->getInternalId();

		if (intval($shipmentId) <= 0)
		{
			$result->addError(new Main\Error(Loc::getMessage('SALE_DLVR_REQ_MNGR_ERROR_SAVE_SHIPMENT_ID')));
			return $result;
		}

		$extShipmentId = $result->getExternalId();

		if ($result->isSuccess())
		{
			if (intval($requestId) > 0)
			{
				$res = ShipmentTable::setShipment(array(
					'REQUEST_ID' => $requestId,
					'SHIPMENT_ID' => $shipmentId,
					'EXTERNAL_ID' => $extShipmentId,
					'ERROR_DESCRIPTION' => ''
				));

				if (!$res->isSuccess())
					$result->addErrors($res->getErrors());

				$res = self::saveShipmentResult($shipmentId, $result);

				if (!$res->isSuccess())
					$result->addErrors($res->getErrors());
			}
		}
		else
		{
			ShipmentTable::setShipment(array(
				'SHIPMENT_ID' => $shipmentId,
				'ERROR_DESCRIPTION' => implode("\n", $result->getErrorMessages())
			));
		}

		return $result;
	}

	/**
	 * @param int $deliveryId
	 * @param int $formFieldsType FORM_FIELDS_TYPE_ACTION | FORM_FIELDS_TYPE_ADD | FORM_FIELDS_TYPE_CREATE
	 * @param int[] $shipmentIds
	 * @param array $additional
	 * @return array Form fields
	 * @throws Main\ArgumentNullException
	 */
	public static function getDeliveryRequestFormFields($deliveryId, $formFieldsType, array $shipmentIds, array $additional = array())
	{
		if (!$deliveryRequestHandler = self::getDeliveryRequestHandlerByDeliveryId($deliveryId))
			return array();

		return $deliveryRequestHandler->getFormFields($formFieldsType, $shipmentIds, $additional);
	}

	/**
	 * @param int $requestId
	 * @return Result
	 * @throws \Exception
	 */
	public static function deleteDeliveryRequest($requestId)
	{
		$result = new Result();
		$shipmentIds = [];

		if (empty($requestId))
		{
			$result->addError(new Main\Error(Loc::getMessage('SALE_DLVR_REQ_MNGR_ERROR_REQ_ID')));
			return $result;
		}

		if ($deliveryRequestHandler = self::getDeliveryRequestHandlerByRequestId($requestId))
		{
			$res = $deliveryRequestHandler->delete($requestId);

			if (!$res->isSuccess())
				$result->addErrors($res->getErrors());
		}

		if ($result->isSuccess())
		{
			$requestShipmentList = ShipmentTable::getList(array('filter' => array('=REQUEST_ID' => $requestId)));
			while ($requestShipment = $requestShipmentList->fetch())
			{
				$shipmentIds[] = $requestShipment['SHIPMENT_ID'];
			}

			$con = Main\Application::getConnection();
			$con->queryExecute("DELETE FROM ".ShipmentTable::getTableName()." WHERE REQUEST_ID=".intval($requestId));
			$res = RequestTable::delete($requestId);

			if (!$res->isSuccess())
				$result->addErrors($res->getErrors());
		}

		(new Main\Event(
			'sale',
			self::REQUEST_DELETED_EVENT_CODE,
			[
				'REQUEST_ID' => $requestId,
				'SHIPMENT_IDS' => $shipmentIds,
				'RESULT' => $result
			]
		))->send();

		if ($result->isSuccess() && Loader::includeModule('pull'))
		{
			\CPullWatch::AddToStack(
				'SALE_DELIVERY_REQUEST',
				[
					'module_id' => 'sale',
					'command' => 'onDeliveryRequestDelete',
					'params' => [
						'ID' => $requestId,
					]
				]
			);
		}

		return $result;
	}

	/**
	 * @param $requestId
	 * @param array $fields
	 * @param bool $overwriteProperties
	 * @return Result
	 */
	public static function updateDeliveryRequest($requestId, array $fields, bool $overwriteProperties = false): Result
	{
		$result = new Result();

		if (empty($requestId))
		{
			$result->addError(new Main\Error(Loc::getMessage('SALE_DLVR_REQ_MNGR_ERROR_REQ_ID')));
			return $result;
		}

		if (isset($fields['EXTERNAL_PROPERTIES']) && !is_array($fields['EXTERNAL_PROPERTIES']))
		{
			unset($fields['EXTERNAL_PROPERTIES']);
		}

		if (
			$overwriteProperties === false
			&& isset($fields['EXTERNAL_PROPERTIES'])
			&& ($existingRequestFields = RequestTable::getById($requestId)->fetch())
		)
		{
			$existingProperties = array_column(
				is_null($existingRequestFields['EXTERNAL_PROPERTIES'])
					? []
					: $existingRequestFields['EXTERNAL_PROPERTIES'],
				null,
				'NAME'
			);
			$newProperties = array_column(
				$fields['EXTERNAL_PROPERTIES'],
				null,
				'NAME'
			);

			$fields['EXTERNAL_PROPERTIES'] = array_values(array_merge($existingProperties, $newProperties));
		}

 		$updateResult = RequestTable::update(
			$requestId,
			array_intersect_key(
				$fields,
				array_flip([
					'STATUS',
					'EXTERNAL_STATUS',
					'EXTERNAL_STATUS_SEMANTIC',
					'EXTERNAL_PROPERTIES',
				])
			)
		);
		if (!$updateResult->isSuccess())
		{
			$result->addErrors($updateResult->getErrors());
		}

		(new Main\Event(
			'sale',
			self::REQUEST_UPDATED_EVENT_CODE,
			[
				'REQUEST_ID' => $requestId,
				'FIELDS' => $fields,
				'RESULT' => $result,
			]
		))->send();

		if ($result->isSuccess() && Loader::includeModule('pull'))
		{
			\CPullWatch::AddToStack(
				'SALE_DELIVERY_REQUEST',
				[
					'module_id' => 'sale',
					'command' => 'onDeliveryRequestUpdate',
					'params' => [
						'ID' => $requestId,
					]
				]
			);
		}

		return $result;
	}

	/**
	 * @param int $requestId
	 * @param int[] $shipmentIds
	 * @return Result
	 */
	public static function deleteShipmentsFromDeliveryRequest($requestId, array $shipmentIds)
	{
		$result = new Result();

		if (empty($requestId))
		{
			$result->addError(new Main\Error(Loc::getMessage('SALE_DLVR_REQ_MNGR_ERROR_REQ_ID')));
			return $result;
		}

		if (empty($shipmentIds))
		{
			$result->addError(new Main\Error(Loc::getMessage('SALE_DLVR_REQ_MNGR_ERROR_SHP_ID_LIST_EMPTY')));
			return $result;
		}

		if (!($deliveryRequestHandler = self::getDeliveryRequestHandlerByRequestId($requestId)))
		{
			$result->addError(
				new Main\Error(
					Loc::getMessage(
						'SALE_DLVR_REQ_MNGR_ERROR_REQ_OBJ'
			)));

			return $result;
		}

		$checkResults = self::checkShipmentIdsBeforeDelete($shipmentIds);

		foreach ($checkResults as $res)
		{
			if (!$res->isSuccess())
			{
				$result->addErrors($res->getErrors());
				unset($shipmentIds[array_search($res->getInternalId(), $shipmentIds)]);
			}
		}

		if (empty($shipmentIds))
			return $result;

		$res = $deliveryRequestHandler->deleteShipments($requestId, $shipmentIds);
		$result->setResults($res->getResults());

		if (!$res->isSuccess())
		{
			$result->addErrors($res->getErrors());
			return $result;
		}

		$results = $result->getResults();

		if (!is_array($results) || empty($results))
		{
			$result->addError(new Main\Error(Loc::getMessage('SALE_DLVR_REQ_MNGR_ERROR_RES_UNKNOWN')));
			return $result;
		}

		$con = Main\Application::getConnection();

		/** @var  ShipmentResult $shpRes */
		foreach ($results as $resId => $shpRes)
		{
			if (!($shpRes instanceof ShipmentResult))
			{
				$result->addError(new Main\Error(Loc::getMessage('SALE_DLVR_REQ_MNGR_ERROR_ANSW_TYPE').' "'.get_class($shpRes).'"'));
				continue;
			}

			if ($shpRes->isSuccess())
			{
				$shpId = intval($shpRes->getInternalId());

				if ($shpId <= 0)
				{
					$result->addError(new Main\Error(Loc::getMessage('SALE_DLVR_REQ_MNGR_SHP_ID_LESS_ZERO')));
					continue;
				}

				$con->queryExecute("DELETE FROM ".ShipmentTable::getTableName()." WHERE REQUEST_ID=".intval($requestId)." AND SHIPMENT_ID=".intval($shpId));
				//Unset mark about changed shipment
				self::unSetMarkerShipmentChanged($shpId);

				//If there is no more shipments in this request
				if (!ShipmentTable::getList(array('filter' => array('=REQUEST_ID' => $requestId)))->fetch())
				{
					$res = RequestTable::delete($requestId);

					if ($res->isSuccess())
					{
						$result->addMessage(
							new Message(
								Loc::getMessage(
									'SALE_DLVR_REQ_MNGR_EMPTY_REQ_DELETED',
									array('#REQUEST_ID#' => $requestId)
						)));
					}
					else
					{
						$result->addError(
							new Main\Error(
								Loc::getMessage(
									'SALE_DLVR_REQ_MNGR_EMPTY_REQ_NOT_DELETED',
									array('#REQUEST_LINK#' => Helper::getRequestViewLink($requestId))
								).implode('; ',$result->getErrorMessages())
						));
					}
				}
			}

			$results[$resId] = $shpRes;
		}

		$result->setResults($results);
		return $result;
	}

	/**
	 * @param int $requestId
	 * @return Result
	 */
	public static function getDeliveryRequestContent($requestId)
	{
		$deliveryRequestHandler = self::getDeliveryRequestHandlerByRequestId($requestId);

		if (!$deliveryRequestHandler)
		{
			$result= new Result();
			$result->addError(new Main\Error(Loc::getMessage('SALE_DLVR_REQ_MNGR_ERROR_REQ_OBJ')));
			return $result;
		}

		return $deliveryRequestHandler->getContent($requestId);
	}

	/**
	 * @param int $requestId
	 * @param string $actionType
	 * @param array $additional
	 * @return Result
	 */
	public static function executeDeliveryRequestAction($requestId, $actionType, array $additional = array())
	{
		$deliveryRequestHandler = self::getDeliveryRequestHandlerByRequestId($requestId);

		if (!$deliveryRequestHandler)
		{
			$result = new Result();
			$result->addError(new Main\Error(Loc::getMessage('SALE_DLVR_REQ_MNGR_ERROR_ACTION_EXEC').'. '.Loc::getMessage('SALE_DLVR_REQ_MNGR_ERROR_REQ_OBJ')));
			return $result;
		}

		$result = $deliveryRequestHandler->executeAction($requestId, $actionType, $additional);

		(new Main\Event(
			'sale',
			self::REQUEST_ACTION_EXECUTED_EVENT_CODE,
			[
				'REQUEST_ID' => $requestId,
				'ACTION_TYPE' => $actionType,
				'ADDITIONAL' => $additional,
				'RESULT' => $result,
				'DELIVERY_REQUEST_HANDLER' => $deliveryRequestHandler,
			]
		))->send();

		return $result;
	}

	/**
	 * @param int $requestId
	 * @param int $shipmentId
	 * @param string $actionType
	 * @param array $additional
	 * @return Result
	 */
	public static function executeDeliveryRequestShipmentAction($requestId, $shipmentId, $actionType, array $additional = array())
	{
		$deliveryRequestHandler = self::getDeliveryRequestHandlerByRequestId($requestId);

		if (!$deliveryRequestHandler)
		{
			$result = new Result();
			$result->addError(new Main\Error(Loc::getMessage('SALE_DLVR_REQ_MNGR_ERROR_ACTION_EXEC').'. '.Loc::getMessage('SALE_DLVR_REQ_MNGR_ERROR_REQ_OBJ')));
			return $result;
		}

		return $deliveryRequestHandler->executeShipmentAction($requestId, $shipmentId, $actionType, $additional);
	}

	/**
	 * @param int[] $shipmentIds
	 * @return ShipmentResult[]
	 * @throws \Bitrix\Main\ArgumentException
	 */
	protected static function checkShipmentIdsBeforeAdd(array $shipmentIds)
	{
		$result = array();
		$positiveIds = self::filterPositiveIds($shipmentIds);

		foreach (array_diff($shipmentIds, $positiveIds) as $id)
		{
			$shpRes = new ShipmentResult($id);
			$shpRes->addError(
				new Main\Error(
					Loc::getMessage('SALE_DLVR_REQ_MNGR_ERROR_SHIPMENT_ID').' "'.$id.'"',
					$id
			));
			$result[] = $shpRes;
		}

		$addedIds = self::filterAddedIds($positiveIds);

		foreach (array_intersect($positiveIds, $addedIds) as $id)
		{
			$shpRes = new ShipmentResult($id);
			$shpRes->addError(
				new Main\Error(
					Loc::getMessage('SALE_DLVR_REQ_MNGR_ALREADY_ADDED')
			));
			$result[] = $shpRes;
		}

		$existingIds = self::filterExistIds($addedIds);

		foreach (array_diff($addedIds, $existingIds) as $id)
		{
			$shpRes = new ShipmentResult($id);
			$shpRes->addError(
				new Main\Error(
					Loc::getMessage('SALE_DLVR_REQ_MNGR_SHP_NOT_FOUND', array('#SHIPMENT_ID#' => $id)
			)));
			$result[] = $shpRes;
		}

		return $result;
	}

	/**
	 * @param int[] $shipmentIds
	 * @return int[] Choose ids only for existing shipments.
	 */
	protected static function filterExistIds(array $shipmentIds)
	{
		$result = array();

		$res = Internals\ShipmentTable::getList(array(
			'filter' => array(
				'=ID' => $shipmentIds,
			)
		));

		while ($row = $res->fetch())
			$result[] = $row['ID'];

		return $result;
	}

	/**
	 * @param int[] $shipmentIds
	 * @return int[]
	 */
	protected static function filterAddedIds(array $shipmentIds)
	{
		$result = array();

		$res = ShipmentTable::getList(array(
			'filter' => array(
				'=SHIPMENT_ID' => $shipmentIds,
				'!=REQUEST_ID' => false
			)
		));

		while ($row = $res->fetch())
			$result[] = $row['SHIPMENT_ID'];

		return $result;
	}

	/**
	 * @param int[] $shipmentIds
	 * @return int[]
	 */
	protected static function filterPositiveIds(array $shipmentIds)
	{
		$result = array();

		foreach ($shipmentIds as $id)
			if (intval($id) > 0)
				$result[] = $id;

		return $result;
	}

	/**
	 * @param int[] $shipmentIds
	 * @return ShipmentResult[]
	 */
	protected static function checkShipmentIdsBeforeDelete(array $shipmentIds)
	{
		return self::checkShipmentIdsBeforeUpdate($shipmentIds);
	}

	/**
	 * @param int[] $shipmentIds
	 * @return ShipmentResult[]
	 * @throws \Bitrix\Main\ArgumentException
	 */
	protected static function checkShipmentIdsBeforeUpdate(array $shipmentIds)
	{
		$result = array();
		$positiveIds = self::filterPositiveIds($shipmentIds);

		foreach (array_diff($shipmentIds, $positiveIds) as $id)
		{
			$shpRes = new ShipmentResult($id);
			$shpRes->addError(
				new Main\Error(
					Loc::getMessage('SALE_DLVR_REQ_MNGR_ERROR_SHIPMENT_ID').' "'.$id.'"')
			);
			$result[] = $shpRes;
		}

		$addedIds = self::filterAddedIds($positiveIds);

		foreach (array_diff($positiveIds, $addedIds) as $id)
		{
			$shpRes = new ShipmentResult($id);
			$shpRes->addError(
				new Main\Error(
					Loc::getMessage('SALE_DLVR_REQ_MNGR_ERROR_SHIPMENT_NOT_IN_REQUEST', array('#SHIPMENT_ID#' => $id)
			)));
			$result[] = $shpRes;
		}

		$existingIds = self::filterExistIds($addedIds);

		foreach (array_diff($addedIds, $existingIds) as $id)
		{
			$shpRes = new ShipmentResult($id);
			$shpRes->addError(
				new Main\Error(
					Loc::getMessage('SALE_DLVR_REQ_MNGR_SHP_NOT_FOUND', array('#SHIPMENT_ID#' => $id)
			)));
			$result[] = $shpRes;
		}

		return $result;
	}

	/**
	 * @param int $shipmentId
	 * @return bool
	 */
	public static function isShipmentSent($shipmentId)
	{
		return intval(self::getRequestIdByShipmentId($shipmentId)) > 0;
	}

	/**
	 * @param int $shipmentId
	 * @return int Request ID
	 */
	public static function getRequestIdByShipmentId($shipmentId)
	{
		$result = 0;

		$res = ShipmentTable::getList(array(
			'filter' => array(
				'=SHIPMENT_ID' => $shipmentId,
			)
		));

		if ($row = $res->fetch())
			$result = $row['REQUEST_ID'];

		return $result;
	}

	/**
	 * @param int $requestId
	 * @param int[] $shipmentIds
	 * @param array $additional
	 * @return Result
	 */
	public static function addShipmentsToDeliveryRequest($requestId, array $shipmentIds, array $additional = [])
	{
		$result = new Result();

		if (empty($requestId))
		{
			$result->addError(new Main\Error(Loc::getMessage('SALE_DLVR_REQ_MNGR_ERROR_REQ_ID')));
			return $result;
		}

		if (empty($shipmentIds))
		{
			$result->addError(new Main\Error(Loc::getMessage('SALE_DLVR_REQ_MNGR_ERROR_SHP_ID_LIST_EMPTY')));
			return $result;
		}

		if (!($deliveryRequestHandler = self::getDeliveryRequestHandlerByRequestId($requestId)))
		{
			$result->addError(
				new Main\Error(
					Loc::getMessage('SALE_DLVR_REQ_MNGR_ERROR_SHP_ADD2').'. '.
					Loc::getMessage('SALE_DLVR_REQ_MNGR_ERROR_REQ_OBJ',
						"",
						$requestId
			)));
			return $result;
		}

		$checkResults = self::checkShipmentIdsBeforeAdd($shipmentIds);

		foreach ($checkResults as $res)
		{
			if ($res->isSuccess())
				continue;

			$result->addResult(
				self::processShipmentResult(
					$res
				));

			unset($shipmentIds[array_search($res->getInternalId(), $shipmentIds)]);
		}

		if (empty($shipmentIds))
		{
			$result->addError(new Main\Error(Loc::getMessage('SALE_DLVR_REQ_MNGR_ERROR_SHP_ABSENT')));
			return $result;
		}

		$res = $deliveryRequestHandler->addShipments($requestId, $shipmentIds, $additional);

		if ($res->isSuccess())
		{
			$result->addResults($res->getResults());
		}
		else
		{
			$result->addErrors($res->getErrors());

			foreach ($res->getShipmentResults() as $sRes)
				$result->addResult(self::processShipmentResult($sRes));

			return $result;
		}

		$results = $result->getResults();

		if (!is_array($results) || empty($results))
		{
			$result->addError(new Main\Error(Loc::getMessage('SALE_DLVR_REQ_MNGR_ERROR_RES_UNKNOWN')));
			return $result;
		}

		$successResCount = 0;

		/** @var RequestResult $reqRes */
		foreach ($results as $resId => $reqRes)
		{
			if ($reqRes instanceof ShipmentResult)
			{
				$results[$resId] = self::processShipmentResult($reqRes, $requestId);
			}
			elseif ($reqRes instanceof RequestResult)
			{
				$reqShpResults = $reqRes->getShipmentResults();

				foreach ($reqShpResults as $id => $shpRes)
				{
					$reqShpResults[$id] = self::processShipmentResult($shpRes, $requestId);

					if ($shpRes->isSuccess())
						$successResCount++;
				}

				$reqRes->setResults($reqShpResults);
				$results[$resId] = $reqRes;
			}
			else
			{
				$result->addError(
					new Main\Error(
						Loc::getMessage(
							'SALE_DLVR_REQ_MNGR_RES_WRONG',
							array(
								'#CLASS_NAME#' => get_class($reqRes),
								'#REQUEST_ID#' => $requestId
							)
						)
					)
				);

				continue;
			}
		}

		if ($successResCount <= 0)
			$result->addError(new Main\Error(Loc::getMessage('SALE_DLVR_REQ_MNGR_ERROR_SHP_ABSENT2')));

		$result->setResults($results);
		return $result;
	}

	/**
	 * @param int $requestId
	 * @param int [] $shipmentIds
	 * @return Result
	 * @throws \Exception
	 */
	public static function updateShipmentsFromDeliveryRequest($requestId, array $shipmentIds)
	{
		$result = new Result();

		if (empty($requestId))
		{
			$result->addError(new Main\Error(Loc::getMessage('SALE_DLVR_REQ_MNGR_ERROR_REQ_ID')));
			return $result;
		}

		if (empty($shipmentIds))
		{
			$result->addError(new Main\Error(Loc::getMessage('SALE_DLVR_REQ_MNGR_ERROR_SHP_ID_LIST_EMPTY')));
			return $result;
		}

		$checkResults = self::checkShipmentIdsBeforeUpdate($shipmentIds);

		foreach ($checkResults as $res)
		{
			if ($res->isSuccess())
				continue;

			$result->addResult(
				self::processShipmentResult($res, $requestId)
			);

			unset($shipmentIds[array_search($res->getInternalId(), $shipmentIds)]);
		}

		if (empty($shipmentIds))
		{
			$result->addError(
				new Main\Error(
					Loc::getMessage(
						'SALE_DLVR_REQ_MNGR_ERROR_SHP_UPD',
						array('#REQUEST_LINK#' => Helper::getRequestViewLink($requestId))
			)));
			return $result;
		}

		$deliveryRequestHandler = self::getDeliveryRequestHandlerByRequestId($requestId);

		if (!$deliveryRequestHandler)
		{
			$result->addError(
				new Main\Error(
					Loc::getMessage(
						'SALE_DLVR_REQ_MNGR_ERROR_SHP_UPD',
						array('#REQUEST_LINK#' => Helper::getRequestViewLink($requestId))
					).'. '.
					Loc::getMessage('SALE_DLVR_REQ_MNGR_ERROR_REQ_OBJ')
			));

			return $result;
		}

		$res = $deliveryRequestHandler->updateShipments($requestId, $shipmentIds);
		$result->addResults($res->getResults());

		if (!$res->isSuccess())
		{
			$result->addErrors($res->getErrors());
			return $result;
		}

		$results = $res->getResults();

		if (empty($results))
		{
			$result->addError(new Main\Error(Loc::getMessage('SALE_DLVR_REQ_MNGR_ERROR_RES_EMPTY')));
			return $result;
		}

		$resultsFinal = array();

		foreach ($results as $res)
		{
			if ($res instanceof ShipmentResult)
			{
				$resultsFinal[] = self::processShipmentResult($res, $requestId);
			}
			elseif ($res instanceof RequestResult)
			{
				$reqShpResults = $res->getShipmentResults();

				foreach ($reqShpResults as $id => $shpRes)
				{
					$shpRes = self::processShipmentResult($shpRes, $requestId);

					if ($shpRes->isSuccess())
					{
						$shpInternalId = intval($shpRes->getInternalId());
						//Unset mark about changed shipments
						self::unSetMarkerShipmentChanged($shpInternalId);

						$dbRes = self::saveShipmentResult($shpRes->getInternalId(), $shpRes);

						if (!$dbRes->isSuccess())
							$shpRes->addErrors($dbRes->getErrors());
					}

					$resultsFinal[] = $shpRes;
				}
			}
			else
			{
				$result->addError(
					new Main\Error(
						Loc::getMessage('SALE_DLVR_REQ_MNGR_RES_WRONG_UPD')
				));

				continue;
			}
		}

		$result->setResults($resultsFinal);
		return $result;
	}

	/**
	 * @param $shipmentId
	 * @param ShipmentResult $shipmentResult
	 * @return Result
	 * @throws Main\ArgumentException
	 * @throws Main\ArgumentNullException
	 * @throws Main\ArgumentOutOfRangeException
	 * @throws Main\NotSupportedException
	 * @throws Main\ObjectNotFoundException
	 * @throws \Exception
	 */
	protected static function saveShipmentResult($shipmentId, ShipmentResult $shipmentResult)
	{
		$result = new Result();
		$shipments = Helper::getShipmentsByIds(array($shipmentId));

		if ($shipments[$shipmentId])
		{
			$shipments[$shipmentId]->setFields(array(
				'TRACKING_NUMBER' => $shipmentResult->getTrackingNumber(),
				'DELIVERY_DOC_NUM' => $shipmentResult->getDeliveryDocNum(),
				'DELIVERY_DOC_DATE' => $shipmentResult->getDeliveryDocDate()
			));

			static::$isChangedShipmentNeedsMark = false;
			$res = $shipments[$shipmentId]->getOrder()->save();
			static::$isChangedShipmentNeedsMark = true;

			if (!$res->isSuccess())
				$result->addError(new Main\Error(Loc::getMessage('SALE_DLVR_REQ_MNGR_ERROR_SAVE_SHIPMENT').'"'.$shipmentId.'"'));
		}
		else
		{
			$result->addError(
				new Main\Error(
					Loc::getMessage(
						'SALE_DLVR_REQ_MNGR_SHP_NOT_FOUND',
						array('#SHIPMENT_ID#' => $shipmentId)
			)));
		}

		return $result;
	}

	/**
	 * @param Order $order
	 * @param Shipment $shipment
	 */
	public static function onBeforeShipmentSave(&$order, &$shipment)
	{
		if (static::$isChangedShipmentNeedsMark && self::isShipmentSent($shipment->getId()))
		{
			self::setMarkerShipmentChanged($order, $shipment);
		}
	}

	/**
	 * @param Shipment $shipment
	 */
	public static function onBeforeShipmentDelete(&$shipment)
	{
		$shipmentId = $shipment->getId();

		if (self::isShipmentSent($shipmentId))
		{
			self::deleteShipmentsFromDeliveryRequest(
				self::getRequestIdByShipmentId($shipmentId),
				array($shipmentId)
			);
		}
	}

	/**
	 * @param Order $order
	 * @param Shipment $shipment
	 */
	protected static function setMarkerShipmentChanged(&$order, &$shipment)
	{
		$r = new \Bitrix\Sale\Result();

		$r->addWarning(
			new ResultWarning(
				Loc::getMessage(
					'SALE_DLVR_REQ_MNGR_NOT_UPDATED'
				),
				'DELIVERY_REQUEST_NOT_UPDATED'
		));

		EntityMarker::addMarker($order, $shipment, $r);
		$shipment->setField('MARKED', 'Y');
	}

	/**
	 * @param int  $shipmentId
	 */
	protected static function unSetMarkerShipmentChanged($shipmentId)
	{
		EntityMarker::deleteByFilter(array(
			'=ENTITY_TYPE' => EntityMarker::ENTITY_TYPE_SHIPMENT,
			'=ENTITY_ID' => $shipmentId,
			'=CODE' => 'DELIVERY_REQUEST_NOT_UPDATED'
		));
	}

	/**
	 * @param string $addressee
	 * @param Message\Message $message
	 * @param int $requestId
	 * @param int $shipmentId
	 */
	public static function sendMessage(
		string $addressee,
		Message\Message $message,
		int $requestId,
		int $shipmentId
	): void
	{
		(new Main\Event(
			'sale',
			self::MESSAGE_RECEIVED_EVENT_CODE,
			[
				'ADDRESSEE' => $addressee,
				'REQUEST_ID' => $requestId,
				'SHIPMENT_ID' => $shipmentId,
				'MESSAGE' => $message,
			]
		))->send();
	}

	/**
	 * @return string[]
	 */
	public static function getMessageAddressees(): array
	{
		return [
			self::MESSAGE_MANAGER_ADDRESSEE,
			self::MESSAGE_RECIPIENT_ADDRESSEE,
		];
	}

	/**
	 * @return string[]
	 */
	public static function getRequestStatusSemantics(): array
	{
		return [
			self::EXTERNAL_STATUS_SEMANTIC_SUCCESS,
			self::EXTERNAL_STATUS_SEMANTIC_PROCESS,
		];
	}

	public static function initJs()
	{
		\CJSCore::RegisterExt('sale_delivery_requests', array(
			'js' => '/bitrix/js/sale/delivery_request.js',
			'lang' => '/bitrix/modules/sale/lang/' . LANGUAGE_ID . '/admin/js/sale_delivery_requests.php',
			'rel' => array('core', 'ajax')
		));

		\CUtil::InitJSCore(array('sale_delivery_requests'));
	}
}

Youez - 2016 - github.com/yon3zu
LinuXploit