• Модуль: sale
  • Путь к файлу: ~/bitrix/modules/sale/lib/internals/shipmentrules.php
  • Класс: BitrixSaleInternalsShipmentRules
  • Вызов: ShipmentRules::createReserveRuleForShipmentItem
static function createReserveRuleForShipmentItem(SaleShipmentItem $shipmentItem, PoolQuantity $pool)
{
	$basketItem = $shipmentItem->getBasketItem();
	if (!$basketItem->isReservableItem())
	{
		return false;
	}

	$reserveCollection = $basketItem->getReserveQuantityCollection();
	if (!$reserveCollection)
	{
		return false;
	}

	$poolReservationList = $pool->getQuantitiesWithStore(PoolQuantity::POOL_RESERVE_TYPE);
	if (empty($poolReservationList))
	{
		return false;
	}

	$shipment = $shipmentItem->getCollection()->getShipment();
	if ($shipment->needShip() === SaleInternalsCatalogProvider::SALE_TRANSFER_PROVIDER_SHIPMENT_NEED_NOT_SHIP)
	{
		return false;
	}

	$productId = $basketItem->getProductId();

	$rule = [
		'SHIPMENT_ITEM' => $shipmentItem,
		'BASKET_ITEM' => $basketItem,
		'PRODUCT_ID' => $productId,
		'PROVIDER_NAME' => $basketItem->getProvider(),
		'STORE' => []
	];

	if (!isset($poolReservationList[$productId]))
	{
		return $rule;
	}

	$needReserveQuantity = $shipmentItem->getNeedReserveQuantity();
	if ($needReserveQuantity == 0)
	{
		$needQuantityByStore = $poolReservationList[$productId];
		$rule['ACTION'][PoolQuantity::POOL_RESERVE_TYPE] = [
			'QUANTITY_BY_STORE' => $needQuantityByStore,
			'QUANTITY' => array_sum($needQuantityByStore),
		];

		$pool->delete(PoolQuantity::POOL_RESERVE_TYPE, $productId);

		return $rule;
	}

	$needQuantityByStore = [];

	/** @var SaleShipmentItemStoreCollection $shipmentItemStoreCollection */
	$shipmentItemStoreCollection = $shipmentItem->getShipmentItemStoreCollection();
	if ($shipmentItemStoreCollection)
	{
		/** @var SaleShipmentItemStore $itemStore */
		foreach ($shipmentItemStoreCollection as $itemStore)
		{
			if (
				isset($poolReservationList[$productId][$itemStore->getStoreId()])
				&& $poolReservationList[$productId][$itemStore->getStoreId()] == 0
			)
			{
				continue;
			}

			/** @var SaleReserveQuantity $reserve */
			foreach ($reserveCollection as $reserve)
			{
				if (
					$reserve->getStoreId() !== $itemStore->getStoreId()
					|| !$reserve->getFields()->isChanged('QUANTITY')
				)
				{
					continue;
				}

				if (!isset($needQuantityByStore[$reserve->getStoreId()]))
				{
					$needQuantityByStore[$reserve->getStoreId()] = 0;
				}

				$needQuantity = $reserve->getQuantity() - $reserve->getFields()->getOriginalValues()['QUANTITY'];
				if (abs($needQuantity) > abs($needReserveQuantity))
				{
					$needQuantityByStore[$reserve->getStoreId()] += $needReserveQuantity;
					$needReserveQuantity = 0;
					$poolReservationList[$productId][$reserve->getStoreId()] -= $needReserveQuantity;
				}
				else
				{
					$needQuantityByStore[$reserve->getStoreId()] += $needQuantity;
					$needReserveQuantity -= $needQuantity;
					$poolReservationList[$productId][$reserve->getStoreId()] -= $needQuantity;
				}
			}
		}
	}

	if ($needReserveQuantity != 0)
	{
		$storeId = SaleConfiguration::getDefaultStoreId();
		if (!isset($needQuantityByStore[$storeId]))
		{
			$needQuantityByStore[$storeId] = 0;
		}

		foreach ($reserveCollection as $reserve)
		{
			if (
				!$reserve->getStoreId() === $storeId
				|| !$reserve->getFields()->isChanged('QUANTITY')
			)
			{
				continue;
			}

			$needQuantity = $reserve->getQuantity() - $reserve->getFields()->getOriginalValues()['QUANTITY'];
			if (abs($needQuantity) > abs($needReserveQuantity))
			{
				$needQuantityByStore[$reserve->getStoreId()] += $needReserveQuantity;
				$needReserveQuantity = 0;
				$poolReservationList[$productId][$reserve->getStoreId()] -= $needReserveQuantity;
			}
			else
			{
				$needQuantityByStore[$reserve->getStoreId()] += $needQuantity;
				$needReserveQuantity -= $needQuantity;
				$poolReservationList[$productId][$reserve->getStoreId()] -= $needQuantity;
			}
		}

		if ($needReserveQuantity != 0)
		{
			foreach ($poolReservationList[$productId] as $storeId => $quantity)
			{
				if ($needReserveQuantity == 0)
				{
					break;
				}

				if ($quantity != 0)
				{
					if (!isset($needQuantityByStore[$storeId]))
					{
						$needQuantityByStore[$storeId] = 0;
					}

					if (abs($needReserveQuantity) > abs($quantity))
					{
						$needQuantityByStore[$storeId] += $quantity;
						$needReserveQuantity -= $quantity;

						$poolReservationList[$productId][$storeId] = 0;
					}
					else
					{
						$needQuantityByStore[$storeId] += $needReserveQuantity;
						$needReserveQuantity = 0;


						$poolReservationList[$productId][$storeId] -= $quantity;
					}

				}
			}
		}
	}

	foreach ($poolReservationList as $productId => $quantityByStore)
	{
		foreach ($quantityByStore as $storeId => $quantity)
		{
			$pool->setByStore(PoolQuantity::POOL_RESERVE_TYPE, $productId, $storeId, $quantity);
		}
	}

	$rule['ACTION'][PoolQuantity::POOL_RESERVE_TYPE] = [
		'QUANTITY_BY_STORE' => $needQuantityByStore,
		'QUANTITY' => array_sum($needQuantityByStore),
	];

	return $rule;
}