• Модуль: sale
  • Путь к файлу: ~/bitrix/modules/sale/lib/shipment.php
  • Класс: BitrixSaleShipment
  • Вызов: Shipment::transferItem2SystemShipment
private function transferItem2SystemShipment(ShipmentItem $sourceItem, $quantity)
{
	$sourceItemCollection = $sourceItem->getCollection();
	if ($this !== $sourceItemCollection->getShipment())
	{
		throw new MainArgumentException("item");
	}

	$quantity = floatval($quantity);

	/** @var Shipment $systemShipment */
	$systemShipment = $this->getCollection()->getSystemShipment();

	/** @var BasketItem $basketItem */
	$basketItem = $sourceItem->getBasketItem();

	/** @var Order $order */
	$order = $basketItem->getCollection()->getOrder();

	$shipmentItemCode = $sourceItem->getBasketCode();

	if ($quantity === 0)
	{
		return new Result();
	}

	/** @var ShipmentItemCollection $systemShipmentItemCollection */
	$systemShipmentItemCollection = $systemShipment->getShipmentItemCollection();

	$systemShipmentItem = $systemShipmentItemCollection->getItemByBasketCode($shipmentItemCode);
	if (is_null($systemShipmentItem))
	{
		$systemShipmentItem = $systemShipmentItemCollection->createItem($basketItem);
	}

	$newSystemShipmentItemQuantity = $systemShipmentItem->getQuantity() + $quantity;
	if ($newSystemShipmentItemQuantity < 0)
	{
		$result = new Result();
		$result->addError(
			new ResultError(
				str_replace(
					["#NAME#", "#QUANTITY#"],
					[$sourceItem->getBasketItem()->getField("NAME"), abs($quantity)],
					Loc::getMessage('SALE_SHIPMENT_QUANTITY_MISMATCH')
				),
				'SALE_SHIPMENT_QUANTITY_MISMATCH'
			)
		);
		return $result;
	}

	$systemShipmentItem->setFieldNoDemand('QUANTITY', $newSystemShipmentItemQuantity);
	if ($newSystemShipmentItemQuantity <= 1e-10)
	{
		$systemShipmentItem->delete();
	}

	$affectedQuantity = 0;

	if ($quantity > 0)  // transfer to system shipment
	{
		if ($sourceItem->getReservedQuantity() > 0)
		{
			$affectedQuantity = $quantity;
			$originalQuantity = $sourceItem->getQuantity() + $quantity;
			if ($sourceItem->getReservedQuantity() < $originalQuantity)
			{
				$affectedQuantity -= $originalQuantity - $sourceItem->getReservedQuantity();
			}
		}
	}
	elseif ($quantity < 0)  // transfer from system shipment
	{
		if ($systemShipmentItem->getReservedQuantity() > 0)
		{
			$affectedQuantity = $quantity;
			if ($systemShipmentItem->getReservedQuantity() < -$affectedQuantity)
			{
				$affectedQuantity = -1 * $systemShipmentItem->getReservedQuantity();
			}
		}
	}

	if ($affectedQuantity != 0)  // if there are reserved items among transferred
	{
		$sourceItem->getFields()->set(
			'RESERVED_QUANTITY',
			$sourceItem->getField('RESERVED_QUANTITY') - $affectedQuantity
		);

		$systemShipmentItem->getFields()->set(
			'RESERVED_QUANTITY',
			$systemShipmentItem->getField('RESERVED_QUANTITY') + $affectedQuantity
		);

		$systemShipment->setFieldNoDemand(
			'RESERVED',
			($systemShipmentItem->getField("RESERVED_QUANTITY") > 0) ? "Y" : "N"
		);

		$shipmentItemForPool = $sourceItem;
		$sourceShipmentItemForPool = $systemShipmentItem;

		if ($quantity > 0)
		{
			$shipmentItemForPool = $systemShipmentItem;
			$sourceShipmentItemForPool = $sourceItem;
		}

		$productId = $basketItem->getProductId();

		$foundItem = false;
		$poolItems = InternalsItemsPool::get($order->getInternalId(), $productId);
		if (!empty($poolItems))
		{
			foreach ($poolItems as $poolIndex => $poolItem)
			{
				if ($poolItem->getInternalIndex() === $shipmentItemForPool->getInternalIndex())
				{
					$foundItem = true;
				}

				if (
					$sourceShipmentItemForPool
					&& $poolItem instanceof ShipmentItem
					&& $poolItem->getInternalIndex() === $sourceShipmentItemForPool->getInternalIndex()
				)
				{
					$reserveQuantity = $sourceShipmentItemForPool->getReservedQuantity();
					if (abs($reserveQuantity) <= 1e-6)
					{
						InternalsItemsPool::delete($order->getInternalId(), $productId, $poolIndex);
					}
				}
			}
		}

		if (!$foundItem)
		{
			InternalsItemsPool::add($order->getInternalId(), $productId, $shipmentItemForPool);
		}
	}

	$tryReserveResult = null;

	if ($quantity > 0)
	{
		if (Configuration::isEnableAutomaticReservation())
		{
			if ($systemShipment->needReservation())
			{
				$tryReserveResult = InternalsCatalogProvider::tryReserveShipmentItem($systemShipmentItem);
			}
			else
			{
				$tryReserveResult = InternalsCatalogProvider::tryUnreserveShipmentItem($systemShipmentItem);
			}
		}
	}
	elseif ($quantity < 0)  // transfer from system shipment
	{
		if (
			Configuration::isEnableAutomaticReservation()
			&& $sourceItemCollection->getShipment()->needReservation()
		)
		{
			$tryReserveResult = InternalsCatalogProvider::tryReserveShipmentItem($sourceItem);
		}
	}

	$canReserve = false;

	if ($tryReserveResult === null)
	{
		$canReserve = true;
	}

	if ($tryReserveResult !== null && ($tryReserveResult->isSuccess() && ($tryReserveResultData = $tryReserveResult->getData())))
	{
		if (array_key_exists('CAN_RESERVE', $tryReserveResultData))
		{
			$canReserve = $tryReserveResultData['CAN_RESERVE'];
		}
	}

	if (
		Configuration::isEnableAutomaticReservation()
		&& $systemShipment->needReservation()
		&& $canReserve
	)
	{
		$order = $this->getOrder();
		if ($order &&
			!InternalsActionEntity::isTypeExists(
				$order->getInternalId(),
				InternalsActionEntity::ACTION_ENTITY_SHIPMENT_COLLECTION_RESERVED_QUANTITY
			)
		)
		{
			InternalsActionEntity::add(
				$order->getInternalId(),
				InternalsActionEntity::ACTION_ENTITY_SHIPMENT_COLLECTION_RESERVED_QUANTITY,
				[
					'METHOD' => 'BitrixSaleShipmentCollection::updateReservedFlag',
					'PARAMS' => [$systemShipment->getCollection()]
				]
			);
		}
	}


	return new Result();
}