• Модуль: sale
  • Путь к файлу: ~/bitrix/modules/sale/lib/providerbase.php
  • Класс: BitrixSaleProviderBase
  • Вызов: ProviderBase::tryReserveShipmentItem
static function tryReserveShipmentItem(ShipmentItem $shipmentItem)
{
	$result = new Result();

	if (floatval($shipmentItem->getQuantity()) == floatval($shipmentItem->getReservedQuantity()))
	{
		return $result;
	}

	/** @var ShipmentItemCollection $shipmentItemCollection */
	if (!$shipmentItemCollection = $shipmentItem->getCollection())
	{
		throw new ObjectNotFoundException('Entity "ShipmentItemCollection" not found');
	}

	/** @var Shipment $shipment */
	if (!$shipment = $shipmentItemCollection->getShipment())
	{
		throw new ObjectNotFoundException('Entity "Shipment" not found');
	}
	/** @var ShipmentCollection $shipmentCollection */
	if (!$shipmentCollection = $shipment->getCollection())
	{
		throw new ObjectNotFoundException('Entity "ShipmentCollection" not found');
	}

	/** @var Order $order */
	if (!$order = $shipmentCollection->getOrder())
	{
		throw new ObjectNotFoundException('Entity "Order" not found');
	}

	/** @var BasketItem $basketItem */
	if (!$basketItem = $shipmentItem->getBasketItem())
	{
		$result->addError(new ResultError(
			Loc::getMessage(
				'SALE_PROVIDER_BASKET_ITEM_NOT_FOUND',
				[
					'#BASKET_ITEM_ID#' => $shipmentItem->getBasketId(),
					'#SHIPMENT_ID#' => $shipment->getId(),
					'#SHIPMENT_ITEM_ID#' => $shipmentItem->getId(),
				]
			),
			'PROVIDER_RESERVE_SHIPMENT_ITEM_WRONG_BASKET_ITEM')
		);

		return $result;
	}

	if ($basketItem->isBundleParent())
	{
		return $result;
	}

	$needQuantity = ($shipmentItem->getQuantity() - $shipmentItem->getReservedQuantity());
	$canReserve = false;

	$providerName  = $basketItem->getProvider();

	if (class_exists($providerName))
	{
		if (empty($context))
		{
			if ($order)
			{
				$context = array(
					'USER_ID' => $order->getUserId(),
					'SITE_ID' => $order->getSiteId(),
					'CURRENCY' => $order->getCurrency(),
				);
			}
			else
			{
				global $USER;
				$context = array(
					'USER_ID' => $USER->getId(),
					'SITE_ID' => SITE_ID,
					'CURRENCY' => CurrencyCurrencyManager::getBaseCurrency(),
				);
			}
		}

		$availableQuantityData = array();

		$providerClass = new $providerName($context);
		if ($providerClass instanceof SaleProviderBase)
		{
			$creator = InternalsProviderCreator::create($context);
			$shipmentProductData = $creator->createItemForReserveByShipmentItem($shipmentItem);
			$creator->addProductData($shipmentProductData);

			$r = $creator->getAvailableQuantity();
			if ($r->isSuccess())
			{
				$resultData = $r->getData();
				if (!empty($resultData['AVAILABLE_QUANTITY_LIST']))
				{
					$productId = $basketItem->getProductId();

					$resultAvailableQuantityList = $resultData['AVAILABLE_QUANTITY_LIST'];
					if (mb_substr($providerName, 0, 1) == "\")
					{
						$providerName = mb_substr($providerName, 1);
					}

					if (isset($resultAvailableQuantityList[$providerName]) && isset($resultAvailableQuantityList[$providerName][$productId]))
					{
						$availableQuantityData = array(
							'HAS_PROVIDER' => true,
							'AVAILABLE_QUANTITY' => $resultAvailableQuantityList[$providerName][$productId]
						);
					}
				}

			}
			else
			{
				$result->addErrors($r->getErrors());
				return $result;
			}
		}
		else
		{
			/** @var Result $r */
			$r = static::tryReserveBasketItem($basketItem, $needQuantity);

			$availableQuantityData = $r->getData();
		}
	}
	else
	{
		/** @var Result $r */
		$r = static::tryReserveBasketItem($basketItem, $needQuantity);

		$availableQuantityData = $r->getData();
	}

	if (!$r->isSuccess())
	{
		$result->addErrors($r->getErrors());
		return $result;
	}
	elseif ($r->hasWarnings())
	{
		$result->addWarnings($r->getWarnings());
		return $result;
	}

	if (array_key_exists('AVAILABLE_QUANTITY', $availableQuantityData))
	{
		$availableQuantity = $availableQuantityData['AVAILABLE_QUANTITY'];
	}
	else
	{
		$result->addWarning( new ResultWarning(Loc::getMessage('SALE_PROVIDER_RESERVE_SHIPMENT_ITEM_WRONG_AVAILABLE_QUANTITY', array(
			'#PRODUCT_NAME#' => $basketItem->getField('NAME')
		)), 'SALE_PROVIDER_RESERVE_SHIPMENT_ITEM_WRONG_AVAILABLE_QUANTITY') );
		return $result;
	}

	if (array_key_exists('HAS_PROVIDER', $availableQuantityData))
	{
		$canReserve = $availableQuantityData['HAS_PROVIDER'];
	}

	if ($canReserve && array_key_exists('QUANTITY_TRACE', $availableQuantityData))
	{
		$canReserve = $availableQuantityData['QUANTITY_TRACE'];
	}

	if ($canReserve)
	{
		if ($r->isSuccess() && ($needQuantity > 0) && ($needQuantity > $availableQuantity)
			/*|| ($needReserved < 0) && ($availableQuantity < $needReserved) */)
		{
			$result->addWarning(new ResultWarning(Loc::getMessage("SALE_PROVIDER_RESERVE_SHIPMENT_ITEM_QUANTITY_NOT_ENOUGH", array(
				'#PRODUCT_NAME#' => $basketItem->getField('NAME')
			)), "SALE_PROVIDER_RESERVE_SHIPMENT_ITEM_QUANTITY_NOT_ENOUGH"));
			return $result;
		}

		// is not completely correct, but will be processed in real reservations while saving
		if (($availableQuantity < 0) && ($shipmentItem->getReservedQuantity() + $availableQuantity < 0))
		{
			$availableQuantity = -1 * $shipmentItem->getReservedQuantity();
		}

		if (Configuration::getProductReservationCondition() != ReserveCondition::ON_SHIP)
		{

			$reservedQuantity = ($availableQuantity >= $needQuantity ? $needQuantity : $availableQuantity);

			static::addReservationPoolItem($order->getInternalId(), $shipmentItem->getBasketItem(), $reservedQuantity);

			$r = $shipmentItem->setField('RESERVED_QUANTITY', $shipmentItem->getReservedQuantity() + $reservedQuantity);
			if (!$r->isSuccess())
			{
				$result->addErrors($r->getErrors());
			}
		}
	}

	$result->addData([
		'CAN_RESERVE' => $canReserve,
	]);

	return $result;
}