• Модуль: catalog
  • Путь к файлу: ~/bitrix/modules/catalog/lib/product/catalogprovider.php
  • Класс: BitrixCatalogProductCatalogProvider
  • Вызов: CatalogProvider::reserveStoreQuantityWithEnabledReservation
static function reserveStoreQuantityWithEnabledReservation(array $productData): SaleResult
	{
		$result = new SaleResult();

		$enableStoreControl = CatalogConfigState::isUsedInventoryManagement();

		$resultFields = [];
		$fields = []; // fields for update products
		$storeFields = []; // rows for update reserve in store
		$needShipList = [];

		$productId = $productData['PRODUCT_ID'];
		$storeProductQuantity = self::getStoreQuantityFromQuantityList($productData); // quantity with stores
		// empty store can't updated if used inventory managment
		if ($enableStoreControl && isset($storeProductQuantity[Base::EMPTY_STORE_ID]))
		{
			return $result;
		}

		$productQuantity = self::getTotalAmountFromQuantityList($productData);

		$isNeedReserve = ($productQuantity > 0);
		$catalogData = $productData['CATALOG'];

		$catalogReservedQuantity = (float)$catalogData['QUANTITY_RESERVED'];
		$catalogQuantity = self::getTotalAmountFromPriceList($catalogData);

		$sumCatalogQuantity = $catalogQuantity + $catalogReservedQuantity;

		if (isset($productData['NEED_SHIP']))
		{
			$needShipList = $productData['NEED_SHIP'];
		}

		$setQuantityReserved = $catalogReservedQuantity;

		if (!empty($needShipList) && !empty($productData['SHIPMENT_ITEM_DATA_LIST']))
		{
			$shipmentItemList = $productData['SHIPMENT_ITEM_DATA_LIST'];
			foreach ($needShipList as $shipmentItemIndex => $isNeedShip)
			{
				if ($setQuantityReserved <= 0)
				{
					$setQuantityReserved = 0;
					break;
				}

				if ($isNeedShip === true)
				{
					$shipmentItemQuantity = $shipmentItemList[$shipmentItemIndex];

					$setQuantityReserved -= $shipmentItemQuantity;
				}
			}
		}

		if ($catalogData["QUANTITY_TRACE"] == "N")
		{
			$fields["QUANTITY_RESERVED"] = $setQuantityReserved;
			$resultFields['IS_UPDATED'] = true;
			$resultFields['QUANTITY_RESERVED'] = 0;
		}
		else
		{
			$resultFields['QUANTITY_RESERVED'] = $catalogReservedQuantity;

			if (
				$productData['PRODUCT']['TYPE'] === CatalogProductTable::TYPE_PRODUCT
				|| $productData['PRODUCT']['TYPE'] === CatalogProductTable::TYPE_OFFER
			)
			{
				$storeFields = $enableStoreControl
					? self::loadCurrentStoreReserve($productId, $storeProductQuantity)
					: [];
			}

			if ($isNeedReserve)
			{
				if ($catalogData["CAN_BUY_ZERO"] == "Y")
				{
					$fields["QUANTITY_RESERVED"] = $catalogReservedQuantity + $productQuantity;
					$fields['QUANTITY'] = $catalogQuantity - $productQuantity;
				}
				else
				{
					if ($catalogQuantity >= $productQuantity)
					{
						$fields["QUANTITY"] = $catalogQuantity - $productQuantity;
						$fields["QUANTITY_RESERVED"] = $catalogReservedQuantity + $productQuantity;
					}
					else
					{
						$resultFields["QUANTITY_NOT_RESERVED"] = $productQuantity - $catalogQuantity;

						$fields["QUANTITY"] = 0;
						$fields["QUANTITY_RESERVED"] = $sumCatalogQuantity;

						$result->addWarning(
							new SaleResultWarning(
								MainLocalizationLoc::getMessage(
									"RSRV_QUANTITY_NOT_ENOUGH_ERROR",
									self::getProductCatalogInfo($productId)
								), "ERROR_NOT_ENOUGH_QUANTITY"
							)
						);
					}
				}
			}
			else //undo reservation
			{
				$correctReserve = 0;
				if ($enableStoreControl)
				{
					foreach (array_keys($storeFields) as $storeId)
					{
						if ($storeFields[$storeId]['ID'] === null)
						{
							continue;
						}
						$storeProductFields = $storeFields[$storeId];
						$newReserve = $storeProductFields['QUANTITY_RESERVED'] + $storeProductFields['ADD_QUANTITY_RESERVED'];
						if ($newReserve < 0)
						{
							$correctReserve -= $newReserve;
							$storeFields[$storeId]['ADD_QUANTITY_RESERVED'] -= $newReserve;
						}
					}
				}

				$needQuantity = abs($productQuantity) - $correctReserve;

				$fields["QUANTITY"] = $catalogQuantity + $needQuantity;

				$needReservedQuantity = $catalogReservedQuantity - $needQuantity;
				if ($needQuantity > $catalogReservedQuantity)
				{
					$needReservedQuantity = $catalogReservedQuantity;
				}

				$fields["QUANTITY_RESERVED"] = $needReservedQuantity;

				if ($enableStoreControl)
				{
					foreach (array_keys($storeFields) as $storeId)
					{
						if ($storeFields[$storeId]['ID'] === null)
						{
							unset($storeFields[$storeId]);
						}
					}
				}
			}

		} //quantity trace

		if (!$productData['PRODUCT']['USED_RESERVATION'])
		{
			if (isset($fields['QUANTITY_RESERVED']))
			{
				unset($fields['QUANTITY_RESERVED']);
			}
		}

		if (!empty($fields) && is_array($fields))
		{
			$storeSuccess = true;
			if ($enableStoreControl)
			{
				foreach (array_keys($storeFields) as $index)
				{
					if ($index === Base::EMPTY_STORE_ID)
					{
						$storeSuccess = false;
					}
					else
					{
						$storeProductFields = $storeFields[$index];
						$id = $storeProductFields['ID'];
						$storeProductFields['QUANTITY_RESERVED'] += $storeProductFields['ADD_QUANTITY_RESERVED'];
						unset($storeProductFields['ID'], $storeProductFields['ADD_QUANTITY_RESERVED']);
						if ($id === null)
						{
							$storeProductFields['AMOUNT'] = 0;
							$internalResult = CatalogStoreProductTable::add($storeProductFields);
						}
						else
						{
							unset($storeProductFields['STORE_ID'], $storeProductFields['PRODUCT_ID']);
							$internalResult = CatalogStoreProductTable::update($id, $storeProductFields);
						}
						if ($internalResult->isSuccess())
						{
							$storeFields[$index]['ID'] = (int)$internalResult->getId();
						}
						else
						{
							$storeFields[$index]['ERROR'] = true;
							$storeFields[$index]['ERROR_MESSAGES'] = $internalResult->getErrorMessages();
							$storeSuccess = false;
						}
					}
					if (!$storeSuccess)
					{
						break;
					}
				}
			}

			if (!$storeSuccess)
			{
				return $result;
			}

			$resultFields['IS_UPDATED'] = false;
			$internalResult = CatalogModelProduct::update($productId, $fields);
			if ($internalResult->isSuccess())
			{
				$resultFields['IS_UPDATED'] = true;
				$quantityValues = array();
				if (isset($fields['QUANTITY']))
				{
					$quantityValues[QuantityControl::QUANTITY] = $fields['QUANTITY'];
					QuantityControl::resetAvailableQuantity($productId);
				}

				if (isset($fields['QUANTITY_RESERVED']))
				{
					$quantityValues[QuantityControl::RESERVED_QUANTITY] = $fields['QUANTITY_RESERVED'];
				}

				if (!empty($quantityValues))
				{
					QuantityControl::setValues($productId, $quantityValues);
				}
			}
			else
			{
				self::convertErrors($internalResult);
			}
			unset($internalResult);
		}

		if (isset($resultFields['IS_UPDATED']))
		{
			if (isset($fields['QUANTITY_RESERVED']))
			{
				$needReserved = $fields["QUANTITY_RESERVED"] - $resultFields['QUANTITY_RESERVED'];
				if ($resultFields['QUANTITY_RESERVED'] > $fields["QUANTITY_RESERVED"])
				{
					$needReserved = $fields["QUANTITY_RESERVED"];
				}
				$resultFields["QUANTITY_RESERVED"] = $needReserved;
			}

			if (!empty($resultFields))
			{
				$result->setData($resultFields);
			}
		}

		return $result;
	}