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/cvetdv.ru/bitrix/modules/sale/lib/internals/catalog/ |
Upload File : |
<?php namespace Bitrix\Sale\Internals\Catalog; use Bitrix\Main; use Bitrix\Sale; use Bitrix\Sale\Internals\PoolQuantity; final class Provider { const SALE_TRANSFER_PROVIDER_SHIPMENT_NEED_SHIP = true; const SALE_TRANSFER_PROVIDER_SHIPMENT_NEED_NOT_SHIP = false; const SALE_TRANSFER_PROVIDER_SHIPMENT_NEED_EMPTY = null; private static $ignoreErrors = false; /** * @param $basketList * @param array $context * * @return Sale\Result * @throws Main\ArgumentNullException * @throws Main\ArgumentTypeException */ public static function getProductData($basketList, array $context) { $result = new Sale\Result(); if (empty($context)) { throw new Main\ArgumentNullException('context'); } if (!is_array($basketList) && !($basketList instanceof Sale\BasketBase)) { throw new Main\ArgumentTypeException('basketList'); } $creator = Sale\Internals\ProviderCreator::create($context); /** @var Sale\BasketItem $basketItem */ foreach ($basketList as $basketItem) { $creator->addBasketItem($basketItem); } $r = $creator->getProductData(); if ($r->isSuccess()) { $data = $r->getData(); if (array_key_exists('PRODUCT_DATA_LIST', $data)) { $result->setData($data); } } else { $result->addErrors($r->getErrors()); } return $result; } /** * @param Sale\BasketItemBase $basketItem * @param array $context * * @return Sale\Result * @throws Main\ArgumentNullException */ public static function getBundleItems(Sale\BasketItemBase $basketItem, array $context) { if (empty($context)) { throw new Main\ArgumentNullException('context'); } $result = new Sale\Result(); $creator = Sale\Internals\ProviderCreator::create($context); /** @var Sale\BasketItem $basketItem */ $creator->addBasketItem($basketItem); $r = $creator->getBundleItems(); if ($r->isSuccess()) { return $r; } else { $result->addErrors($r->getErrors()); } return $result; } /** * @param Sale\BasketItemBase $basketItem * @param array|null $context * * @return Sale\Result */ public static function getAvailableQuantityAndPriceByBasketItem(Sale\BasketItemBase $basketItem, array $context = array()) { $result = new Sale\Result(); /** @var Sale\Basket $basket */ $basket = $basketItem->getCollection(); $order = $basket->getOrder(); if (empty($context) && !$order) { $context = $basket->getContext(); } if (empty($context) && $order) { $context = self::prepareContext($order, $context); } $r = self::checkContext($context); if (!$r->isSuccess()) { return $r; } $resultData = array(); $creator = Sale\Internals\ProviderCreator::create($context); /** @var Sale\BasketItem $basketItem */ $creator->addBasketItem($basketItem); $r = $creator->getAvailableQuantityAndPrice(); if ($r->isSuccess()) { $providerName = $basketItem->getProviderName(); if (strval($providerName) == '') { $providerName = $basketItem->getCallbackFunction(); } $providerName = self::clearProviderName($providerName); $checkProviderName = $providerName; $data = $r->getData(); if (array_key_exists('PRODUCT_DATA_LIST', $data) && isset($data['PRODUCT_DATA_LIST'][$checkProviderName])) { $productData = $data['PRODUCT_DATA_LIST'][$checkProviderName]; if (isset($productData['PRICE_LIST'][$basketItem->getProductId()][$basketItem->getBasketCode()])) { $resultData['PRICE_DATA'] = $productData['PRICE_LIST'][$basketItem->getProductId()][$basketItem->getBasketCode()]; } if (isset($productData['AVAILABLE_QUANTITY_LIST'][$basketItem->getProductId()])) { $resultData['AVAILABLE_QUANTITY'] = $productData['AVAILABLE_QUANTITY_LIST'][$basketItem->getProductId()]; } } } else { $result->addErrors($r->getErrors()); } if (isset($resultData)) { $result->setData( $resultData ); } return $result; } /** * @param Sale\Shipment $shipment * @param array $context * * @return Sale\Result * @throws Main\ArgumentNullException * @throws Main\ObjectNotFoundException */ public static function tryReserveShipment(Sale\Shipment $shipment) { $context = self::prepareContext($shipment->getOrder()); $r = self::checkContext($context); if (!$r->isSuccess()) { return $r; } $shipmentItemList = []; /** @var Sale\ShipmentItem $item */ foreach ($shipment->getShipmentItemCollection() as $item) { $basketItem = $item->getBasketItem(); if ($basketItem->isReservableItem()) { $shipmentItemList[] = $item; } } return self::tryReserveShipmentItemArray($shipmentItemList, $context); } /** * @param array $shipmentItemList * @param array $context * * @return Sale\Result * @throws Main\ArgumentNullException * @throws Main\ObjectNotFoundException */ protected static function tryReserveShipmentItemArray(array $shipmentItemList, array $context) { $result = new Sale\Result(); /** @var Sale\ShipmentItem $shipmentItem */ $shipmentItem = current($shipmentItemList); if (!$shipmentItem) { return $result; } $availableQuantityList = []; $needQuantityList = self::getNeedQuantityByShipmentItemList($shipmentItemList); if (!$needQuantityList) { return $result; } $creator = Sale\Internals\ProviderCreator::create($context); /** @var Sale\ShipmentItem $shipmentItem */ foreach ($shipmentItemList as $shipmentItem) { $productData = $creator->createItemForReserveByShipmentItem($shipmentItem); $creator->addProductData($productData); } $r = $creator->getAvailableQuantityByStore(); if ($r->isSuccess()) { $data = $r->getData(); if (array_key_exists('AVAILABLE_QUANTITY_LIST_BY_STORE', $data)) { $availableQuantityList = $data['AVAILABLE_QUANTITY_LIST_BY_STORE']; } } else { $result->addErrors($r->getErrors()); } if ($r->hasWarnings()) { $result->addWarnings($r->getWarnings()); } if (!$result->isSuccess()) { return $result; } $applyItemsList = []; $pool = PoolQuantity::getInstance($shipmentItem->getCollection()->getShipment()->getOrder()->getInternalId()); foreach ($availableQuantityList as $providerName => $productAvailableQuantityList) { $providerName = trim($providerName); foreach ($productAvailableQuantityList as $productId => $quantityByStore) { if (array_key_exists($productId, $needQuantityList[$providerName])) { if (Sale\Configuration::getProductReservationCondition() !== Sale\Reservation\Configuration\ReserveCondition::ON_SHIP) { if (!isset($applyItemsList[$providerName][$productId])) { $applyItemsList[$providerName][$productId] = []; } foreach ($quantityByStore as $storeId => $quantity) { if ($quantity < $needQuantityList[$providerName][$productId][$storeId]) { $poolQuantity = (float)$pool->getByStore( PoolQuantity::POOL_QUANTITY_TYPE, $productId, $storeId ); $delta = $needQuantityList[$providerName][$productId][$storeId] - $quantity; if ($delta < $poolQuantity) { $applyItemsList[$providerName][$productId][$storeId] = $needQuantityList[$providerName][$productId][$storeId]; } elseif ($poolQuantity > 0) { $applyItemsList[$providerName][$productId][$storeId] = $quantity + $poolQuantity; } else { $applyItemsList[$providerName][$productId][$storeId] = $quantity; } } else { $applyItemsList[$providerName][$productId][$storeId] = $quantity; } } } } else { /** @var Sale\ShipmentItem $shipmentItem */ foreach ($shipmentItemList as $shipmentItem) { $basketItem = $shipmentItem->getBasketItem(); if ($basketItem->getProductId() === $productId) { $result->addWarning( new Sale\ResultWarning( Main\Localization\Loc::getMessage( 'SALE_PROVIDER_RESERVE_SHIPMENT_ITEM_WRONG_AVAILABLE_QUANTITY', ['#PRODUCT_NAME#' => $basketItem->getField('NAME')] ), 'SALE_PROVIDER_RESERVE_SHIPMENT_ITEM_WRONG_AVAILABLE_QUANTITY' ) ); break; } } } } } if (!empty($applyItemsList)) { $shipmentItemMap = self::createProductShipmentItemMap($shipmentItemList); self::setQuantityAfterReserve($shipmentItemMap, $applyItemsList); } return $result; } /** * @param Sale\ShipmentItem $shipmentItem * @param array $context * * @return Sale\Result * @throws Main\ArgumentNullException * @throws Main\ObjectNotFoundException * @throws \Exception */ public static function tryReserveShipmentItem(Sale\ShipmentItem $shipmentItem, array $context = array()) { /** @var Sale\Order $order */ $order = $shipmentItem->getCollection()->getShipment()->getOrder(); $context = self::prepareContext($order, $context); $r = self::checkContext($context); if (!$r->isSuccess()) { return $r; } return self::tryReserveShipmentItemArray([$shipmentItem], $context); } /** * @param Sale\ReserveQuantity $reserveQuantity * @param $quantity * @param array $context * @return Sale\Result * @throws Main\ArgumentNullException */ public static function tryReserve(Sale\ReserveQuantity $reserveQuantity, array $context = array()) { $result = new Sale\Result(); $basketItem = $reserveQuantity->getCollection()->getBasketItem(); $order = $basketItem->getBasket()->getOrder(); $context = self::prepareContext($order, $context); $r = self::checkContext($context); if (!$r->isSuccess()) { return $r; } $creator = Sale\Internals\ProviderCreator::create($context); $productData = $creator->createItemForReserve($reserveQuantity); $creator->addProductData($productData); $availableQuantityList = []; $r = $creator->getAvailableQuantityByStore(); if ($r->isSuccess()) { $data = $r->getData(); if (array_key_exists('AVAILABLE_QUANTITY_LIST_BY_STORE', $data)) { $availableQuantityList = $data['AVAILABLE_QUANTITY_LIST_BY_STORE']; } } else { return $result->addErrors($r->getErrors()); } if ($r->hasWarnings()) { $result->addWarnings($r->getWarnings()); } $pool = PoolQuantity::getInstance($order->getInternalId()); $providerName = $basketItem->getProviderName(); $providerName = self::clearProviderName($providerName); $storeId = $reserveQuantity->getStoreId(); $availableQuantity = $availableQuantityList[$providerName][$basketItem->getProductId()][$storeId] ?? 0; if ($availableQuantity < $productData['QUANTITY']) { $result->addError( new Sale\ResultError( Main\Localization\Loc::getMessage('SALE_PROVIDER_RESERVE_WRONG_AVAILABLE_QUANTITY'), 'SALE_PROVIDER_RESERVE_WRONG_AVAILABLE_QUANTITY' ) ); } else { $pool->addByStore( Sale\Internals\PoolQuantity::POOL_RESERVE_TYPE, $basketItem->getProductId(), $storeId, $productData['QUANTITY'] ); $foundItem = false; $poolItems = Sale\Internals\ItemsPool::get($order->getInternalId(), $basketItem->getProductId()); if (!empty($poolItems)) { foreach ($poolItems as $poolItem) { if ( $poolItem instanceof Sale\ReserveQuantity && $poolItem->getInternalIndex() === $reserveQuantity->getInternalIndex() && $poolItem->getCollection()->getBasketItem()->getInternalIndex() === $reserveQuantity->getCollection()->getBasketItem()->getInternalIndex() ) { $foundItem = true; break; } } } if (!$foundItem) { Sale\Internals\ItemsPool::add( $order->getInternalId(), $basketItem->getProductId(), $reserveQuantity ); } } return $result; } /** * @param Sale\ShipmentItem $shipmentItem * @return Sale\Result * @throws Main\ArgumentNullException * @throws Main\ArgumentOutOfRangeException * @throws Main\NotImplementedException */ public static function tryUnreserveShipmentItem(Sale\ShipmentItem $shipmentItem) : Sale\Result { $result = new Sale\Result(); /** @var Sale\Order $order */ $order = $shipmentItem->getCollection()->getShipment()->getOrder(); $pool = PoolQuantity::getInstance($order->getInternalId()); /** @var Sale\BasketItem $basketItem */ $basketItem = $shipmentItem->getBasketItem(); $productId = $basketItem->getProductId(); $reservedQuantity = $shipmentItem->getReservedQuantity(); if ($reservedQuantity == 0) { return $result; } $pool->add(Sale\Internals\PoolQuantity::POOL_RESERVE_TYPE, $productId, -1 * $reservedQuantity); $foundItem = false; $poolItems = Sale\Internals\ItemsPool::get($order->getInternalId(), $productId); if (!empty($poolItems)) { /** @var Sale\ShipmentItem $poolItem */ foreach ($poolItems as $poolItem) { if ( $poolItem instanceof Sale\ShipmentItem && $poolItem->getInternalIndex() == $shipmentItem->getInternalIndex() ) { $foundItem = true; break; } } } if (!$foundItem) { Sale\Internals\ItemsPool::add($order->getInternalId(), $productId, $shipmentItem); } $r = $shipmentItem->setField('RESERVED_QUANTITY', $shipmentItem->getReservedQuantity() + -1 * $reservedQuantity); if (!$r->isSuccess()) { $result->addErrors($r->getErrors()); } return $result; } /** * @param array $shipmentItemList * @return array * @throws Main\ArgumentNullException */ private static function getNeedQuantityByShipmentItemList(array $shipmentItemList) : array { $needQuantityList = []; /** @var Sale\ShipmentItem $shipmentItem */ foreach ($shipmentItemList as $shipmentItem) { $quantityList = self::getNeedQuantityByShipmentItem($shipmentItem); $providerName = key($quantityList); $productId = key($quantityList[$providerName]); foreach ($quantityList[$providerName][$productId] as $storeId => $quantity) { if (!isset($needQuantityList[$providerName][$productId][$storeId])) { $needQuantityList[$providerName][$productId][$storeId] = 0; } $needQuantityList[$providerName][$productId][$storeId] += $quantity; } } return $needQuantityList; } /** * @param Sale\ShipmentItem $shipmentItem * @return \array[][] * @throws Main\ArgumentNullException * @throws Main\LoaderException */ private static function getNeedQuantityByShipmentItem(Sale\ShipmentItem $shipmentItem) : array { $basketItem = $shipmentItem->getBasketItem(); $productId = $basketItem->getProductId(); $providerName = $basketItem->getProviderName(); $providerName = self::clearProviderName($providerName); $quantity = $shipmentItem->getQuantity(); if ($quantity == 0) { return [ $providerName => [ $productId => [ Sale\Configuration::getDefaultStoreId() => -$shipmentItem->getReservedQuantity(), ], ], ]; } else { $quantityByStore = []; /** @var Sale\ShipmentItemStoreCollection $shipmentItemStoreCollection */ $shipmentItemStoreCollection = $shipmentItem->getShipmentItemStoreCollection(); if ($shipmentItemStoreCollection) { /** @var Sale\ShipmentItemStore $shipmentItemStore */ foreach ($shipmentItemStoreCollection as $shipmentItemStore) { if (!isset($quantityByStore[$shipmentItemStore->getStoreId()])) { $quantityByStore[$shipmentItemStore->getStoreId()] = 0; } $quantityByStore[$shipmentItemStore->getStoreId()] += $shipmentItemStore->getQuantity(); $quantity -= $shipmentItemStore->getQuantity(); } } if ($quantity) { $storeId = Sale\Configuration::getDefaultStoreId(); if (!isset($quantityByStore[$storeId])) { $quantityByStore[$storeId] = 0; } $quantityByStore[$storeId] += $quantity; } return [ $providerName => [ $productId => $quantityByStore, ], ]; } } /** * @param Sale\Shipment $shipment * * @return Sale\Result * @throws Main\ArgumentOutOfRangeException * @throws Main\ObjectNotFoundException * @throws \Exception */ public static function tryUnreserveShipment(Sale\Shipment $shipment) { $result = new Sale\Result(); /** @var Sale\Order $order */ $order = $shipment->getOrder(); $pool = PoolQuantity::getInstance($order->getInternalId()); /** @var Sale\ShipmentItem $shipmentItem */ foreach ($shipment->getShipmentItemCollection() as $shipmentItem) { /** @var Sale\BasketItem $basketItem */ if (!$basketItem = $shipmentItem->getBasketItem()) { continue; } if ((int)$shipmentItem->getReservedQuantity() === 0) { continue; } $shipmentItemReserveQuantity = $shipmentItem->getReservedQuantity(); /** @var Sale\ReserveQuantityCollection $reserveCollection */ $reserveCollection = $basketItem->getReserveQuantityCollection(); if (!$reserveCollection) { continue; } /** @var Sale\ShipmentItemStoreCollection $shipmentItemStoreCollection */ $shipmentItemStoreCollection = $shipmentItem->getShipmentItemStoreCollection(); if ($shipmentItemStoreCollection) { /** @var Sale\ShipmentItemStore $itemStore */ foreach ($shipmentItemStoreCollection as $itemStore) { if ($shipmentItemReserveQuantity == 0) { break; } /** @var Sale\ReserveQuantity $reserve */ foreach ($reserveCollection as $reserve) { if ($reserve->getStoreId() !== $itemStore->getStoreId()) { continue; } // try to guess reserved quantity on shipment item store if ($shipmentItemReserveQuantity > $itemStore->getQuantity()) { $reserveStoreQuantity = $itemStore->getQuantity(); } else { $reserveStoreQuantity = $shipmentItemReserveQuantity; } if ($reserveStoreQuantity >= $reserve->getQuantity()) { $poolQuantity = $reserve->getQuantity(); $reserve->deleteNoDemand(); } else { $poolQuantity = $reserveStoreQuantity; $reserve->setFieldNoDemand('QUANTITY', $reserve->getQuantity() - $reserveStoreQuantity); } $shipmentItemReserveQuantity -= $reserveStoreQuantity; $pool->addByStore( PoolQuantity::POOL_RESERVE_TYPE, $basketItem->getProductId(), $itemStore->getStoreId(), -$poolQuantity ); } } } if ($shipmentItemReserveQuantity > 0) { $storeId = Sale\Configuration::getDefaultStoreId(); foreach ($reserveCollection as $reserve) { if ($shipmentItemReserveQuantity == 0) { break; } if ($reserve->getStoreId() !== $storeId) { continue; } if ($shipmentItemReserveQuantity >= $reserve->getQuantity()) { $poolQuantity = $reserve->getQuantity(); $shipmentItemReserveQuantity -= $poolQuantity; $reserve->deleteNoDemand(); } else { $reserve->setFieldNoDemand('QUANTITY', $reserve->getQuantity() - $shipmentItemReserveQuantity); $shipmentItemReserveQuantity = 0; $poolQuantity = $shipmentItemReserveQuantity; } $pool->addByStore( PoolQuantity::POOL_RESERVE_TYPE, $basketItem->getProductId(), $storeId, -$poolQuantity ); } } $shipmentItem->getFields()->set('RESERVED_QUANTITY', 0); if (!Sale\Internals\ActionEntity::isTypeExists( $order->getInternalId(), Sale\Internals\ActionEntity::ACTION_ENTITY_SHIPMENT_COLLECTION_RESERVED_QUANTITY ) ) { Sale\Internals\ActionEntity::add( $order->getInternalId(), Sale\Internals\ActionEntity::ACTION_ENTITY_SHIPMENT_COLLECTION_RESERVED_QUANTITY, [ 'METHOD' => 'Bitrix\Sale\Shipment::updateReservedFlag', 'PARAMS' => [$shipment], ] ); } $foundItem = false; $poolItems = Sale\Internals\ItemsPool::get($order->getInternalId(), $basketItem->getProductId()); if (!empty($poolItems)) { /** @var Sale\Shipment $poolItem */ foreach ($poolItems as $poolItem) { if ( $poolItem instanceof Sale\ShipmentItem && $poolItem->getInternalIndex() == $shipmentItem->getInternalIndex() ) { $foundItem = true; break; } } } if (!$foundItem) { Sale\Internals\ItemsPool::add($order->getInternalId(), $basketItem->getProductId(), $shipmentItem); } } return $result; } /** * @param array $shipmentItemList * * @return array */ private static function createProductShipmentItemMap(array $shipmentItemList) { $result = []; /** @var Sale\ShipmentItem $shipmentItem */ foreach ($shipmentItemList as $shipmentItem) { $basketItem = $shipmentItem->getBasketItem(); $providerName = self::clearProviderName($basketItem->getProviderName()); $result[$providerName][$basketItem->getProductId()][$shipmentItem->getInternalIndex()] = $shipmentItem; } return $result; } /** * @param Sale\Order $order * @param array $shipmentItemMap * @param array $availableQuantityList * * @return Sale\Result * @throws \Exception */ private static function setQuantityAfterReserve(array $shipmentItemMap, array $availableQuantityList) { $result = new Sale\Result(); foreach ($availableQuantityList as $providerName => $productsList) { foreach ($productsList as $productId => $reservedQuantityByStore) { foreach ($reservedQuantityByStore as $storeId => $reservedQuantity) { $r = self::setReserveQuantityByProduct($shipmentItemMap[$providerName][$productId], $storeId, $reservedQuantity); if (!$r->isSuccess()) { $result->addErrors($r->getErrors()); } } } } return $result; } private static function setReserveQuantityByProduct(array $shipmentItemList, $storeId, $quantity) : Sale\Result { $result = new Sale\Result(); if ($quantity == 0) { return $result; } /** @var Sale\ShipmentItem $shipmentItem */ foreach ($shipmentItemList as $shipmentItem) { $basketItem = $shipmentItem->getBasketItem(); if (!$basketItem->isReservableItem()) { continue; } /** @var Sale\ReserveQuantityCollection $reserveQuantityCollection */ $reserveQuantityCollection = $basketItem->getReserveQuantityCollection(); if (!$reserveQuantityCollection) { continue; } $productId = $basketItem->getProductId(); /** @var Sale\Order $order */ $order = $basketItem->getBasket()->getOrder(); $pool = PoolQuantity::getInstance($order->getInternalId()); $reserve = null; /** @var Sale\ReserveQuantity $item */ foreach ($reserveQuantityCollection as $item) { if ($item->getStoreId() === $storeId) { $reserve = $item; break; } } if ($reserve === null) { $reserve = $reserveQuantityCollection->create(); $reserve->setStoreId($storeId); } if ($quantity < 0) { $settableQuantity = $quantity; if ($shipmentItem->getReservedQuantity() < $quantity) { $settableQuantity = $shipmentItem->getReservedQuantity(); } } else { $needQuantity = $basketItem->getQuantity() - $reserve->getQuantity(); $settableQuantity = (abs($needQuantity) >= abs($quantity)) ? $quantity : $needQuantity; } $reserve->setFieldNoDemand('QUANTITY', $reserve->getQuantity() + $settableQuantity); self::applyReserveToShipmentItem($shipmentItem, $settableQuantity); $quantity -= $settableQuantity; $pool->addByStore(Sale\Internals\PoolQuantity::POOL_RESERVE_TYPE, $productId, $storeId, $settableQuantity); $foundItem = false; $poolItems = Sale\Internals\ItemsPool::get($order->getInternalId(), $productId); if (!empty($poolItems)) { /** @var Sale\ShipmentItem $poolItem */ foreach ($poolItems as $poolItem) { if ( $poolItem instanceof Sale\ShipmentItem && $poolItem->getInternalIndex() == $shipmentItem->getInternalIndex() ) { $foundItem = true; break; } } } if (!$foundItem) { Sale\Internals\ItemsPool::add($order->getInternalId(), $productId, $shipmentItem); } } return $result; } protected static function applyReserveToShipmentItem(Sale\ShipmentItem $item, $quantity) { $item->getFields()->set('RESERVED_QUANTITY', $item->getReservedQuantity() + $quantity); $shipment = $item->getCollection()->getShipment(); $order = $shipment->getOrder(); if (!Sale\Internals\ActionEntity::isTypeExists( $order->getInternalId(), Sale\Internals\ActionEntity::ACTION_ENTITY_SHIPMENT_RESERVED_QUANTITY ) ) { Sale\Internals\ActionEntity::add( $order->getInternalId(), Sale\Internals\ActionEntity::ACTION_ENTITY_SHIPMENT_RESERVED_QUANTITY, [ 'METHOD' => 'Bitrix\Sale\Shipment::updateReservedFlag', 'PARAMS' => [$shipment], ] ); } } /** * @param Sale\Shipment $shipment * @param array $context * * @return Sale\Result * @throws Main\ObjectNotFoundException */ public static function tryShipShipment(Sale\Shipment $shipment, array $context = array()) { $result = new Sale\Result(); $order = $shipment->getOrder(); $context = self::prepareContext($order, $context); $pool = PoolQuantity::getInstance($order->getInternalId()); /** @var Sale\ShipmentItemCollection $shipmentItemCollection */ $shipmentItemCollection = $shipment->getShipmentItemCollection(); $needShipList = array(); $creator = Sale\Internals\ProviderCreator::create($context); /** @var Sale\ShipmentItem $shipmentItem */ foreach ($shipmentItemCollection as $shipmentItem) { $creator->addShipmentItem($shipmentItem); } $r = $creator->isNeedShip(); if ($r->isSuccess()) { $data = $r->getData(); if (array_key_exists('IS_NEED_SHIP', $data)) { $needShipList = $data['IS_NEED_SHIP'] + $needShipList; } } $creator = Sale\Internals\ProviderCreator::create($context); /** @var Sale\ShipmentItem $shipmentItem */ foreach ($shipmentItemCollection as $shipmentItem) { $shipmentProductData = $creator->createItemForShip($shipmentItem, $needShipList); $creator->addProductData($shipmentProductData); } $tryShipProductList = array(); $isIgnoreErrors = false; $r = $creator->tryShip(); $needSetAfterResult = false; if ($r->isSuccess()) { if ($r->hasWarnings()) { $result->addWarnings($r->getWarnings()); } else { $needSetAfterResult = true; } } else { $result->addWarnings($r->getErrors()); if (self::isIgnoreErrors()) { $isIgnoreErrors = true; $needSetAfterResult = true; } else { $result->addErrors($r->getErrors()); } } $data = $r->getData(); if (array_key_exists('TRY_SHIP_PRODUCTS_LIST', $data)) { $tryShipProductList = $data['TRY_SHIP_PRODUCTS_LIST'] + $tryShipProductList; } if ($needSetAfterResult && !empty($tryShipProductList)) { if ($isIgnoreErrors) { foreach ($tryShipProductList as &$productList) { $productList = array_fill_keys(array_keys($productList), true); } } $creator->setItemsResultAfterTryShip($pool, $tryShipProductList); } return $result; } public static function deliver(Sale\Shipment $shipment) { $result = new Sale\Result(); $order = $shipment->getOrder(); $context = array( 'USER_ID' => $order->getUserId(), 'SITE_ID' => $order->getSiteId(), ); $creator = Sale\Internals\ProviderCreator::create($context); foreach ($shipment->getShipmentItemCollection() as $shipmentItem) { $creator->addShipmentItem($shipmentItem); } $r = $creator->deliver(); if ($r->isSuccess()) { $r = $creator->createItemsResultAfterDeliver($r); if ($r->isSuccess()) { $data = $r->getData(); if ( !empty($data['RESULT_AFTER_DELIVER_LIST']) && is_array($data['RESULT_AFTER_DELIVER_LIST']) ) { $result->setData($data['RESULT_AFTER_DELIVER_LIST']); } } } else { $result->addErrors($r->getErrors()); } return $result; } public static function changeProductBatchBalance(Sale\Shipment $shipment): Sale\Result { $result = new Sale\Result(); $order = $shipment->getOrder(); $context = array( 'USER_ID' => $order->getUserId(), 'SITE_ID' => $order->getSiteId(), ); $creator = Sale\Internals\ProviderCreator::create($context); foreach ($shipment->getShipmentItemCollection() as $shipmentItem) { $creator->addShipmentItem($shipmentItem); } $r = $shipment->isShipped() ? $creator->writeOffProductBatches() : $creator->returnProductBatches() ; if (!$r->isSuccess()) { $result->addErrors($r->getErrors()); } return $result; } /** * @internal * @param Sale\ShipmentItem $shipmentItem * * @return array|bool * @throws Main\ObjectNotFoundException */ public static function createMapShipmentItemStoreData(Sale\ShipmentItem $shipmentItem, $needUseReserve = true) { $resultList = array(); /** @var Sale\BasketItem $basketItem */ $basketItem = $shipmentItem->getBasketItem(); if (!$basketItem->isReservableItem()) { return false; } /** @var Sale\ReserveQuantityCollection $reserveQuantityCollection */ $reserveQuantityCollection = $basketItem->getReserveQuantityCollection(); if (!$reserveQuantityCollection) { return false; } $reserveQuantityStoreList = []; $countBarcode = 0; /** @var Sale\ShipmentItemStoreCollection $shipmentItemStoreCollection */ $shipmentItemStoreCollection = $shipmentItem->getShipmentItemStoreCollection(); if ($shipmentItemStoreCollection) { /** @var Sale\ShipmentItemStore $shipmentItemStore */ foreach ($shipmentItemStoreCollection as $shipmentItemStore) { $productId = $basketItem->getProductId(); $storeId = $shipmentItemStore->getStoreId(); if (!isset($reserveQuantityStoreList[$storeId])) { $reserveQuantityStoreList[$storeId] = $reserveQuantityCollection->getQuantityByStoreId($shipmentItemStore->getStoreId()); } if (!isset($resultList[$storeId])) { $resultList[$storeId] = [ 'PRODUCT_ID' => $productId, 'QUANTITY' => 0, 'RESERVED_QUANTITY' => 0, 'STORE_ID' => $storeId, 'IS_BARCODE_MULTI' => $basketItem->isBarcodeMulti(), 'BARCODE' => [], ]; } $barcodeId = ($shipmentItemStore->getId() > 0)? $shipmentItemStore->getId() : 'n'.$countBarcode; $countBarcode++; $resultList[$storeId]['QUANTITY'] += $basketItem->isBarcodeMulti()? 1 : $shipmentItemStore->getQuantity(); $resultList[$storeId]['BARCODE'][$barcodeId] = $shipmentItemStore->getBarcode(); if ($needUseReserve) { if ($reserveQuantityStoreList[$storeId] > $resultList[$storeId]['QUANTITY']) { $resultList[$storeId]['RESERVED_QUANTITY'] = $resultList[$storeId]['QUANTITY']; } elseif ($reserveQuantityStoreList[$storeId] > 0) { $resultList[$storeId]['RESERVED_QUANTITY'] = $reserveQuantityStoreList[$storeId]; } $reserveQuantityStoreList[$storeId] -= $resultList[$storeId]['RESERVED_QUANTITY']; } } } return $resultList; } /** * @internal * @param $shipmentItemList * * @return array * @throws Main\ObjectNotFoundException * @throws Main\SystemException */ public static function createMapShipmentItemCollectionStoreData($shipmentItemList) { $resultList = array(); /** @var Sale\ShipmentItem $shipmentItem */ foreach ($shipmentItemList as $shipmentItem) { $basketCode = $shipmentItem->getBasketCode(); if (!isset($resultList[$basketCode])) { $resultList[$basketCode] = array(); } $map = self::createMapShipmentItemStoreData($shipmentItem); if (!empty($map) && is_array($map)) { $resultList[$basketCode] = $map + $resultList[$basketCode]; } } return $resultList; } /** * @param Sale\Order $order * @param array|null $context * * @return Sale\Result * @throws Main\SystemException */ public static function save(Sale\Order $order, array $context = array()) { $result = new Sale\Result(); $context = self::prepareContext($order, $context); $r = self::checkContext($context); if (!$r->isSuccess()) { $result->addErrors($r->getErrors()); return $result; } $pool = PoolQuantity::getInstance($order->getInternalId()); $rulesMap = Sale\Internals\ShipmentRules::createOrderRuleMap($order, $pool); if (empty($rulesMap)) { return $result; } $r = Sale\Internals\ShipmentRules::saveRules($rulesMap, $context); if (!$r->isSuccess()) { $result->addErrors($r->getErrors()); } if ($r->hasWarnings()) { $result->addWarnings($r->getWarnings()); } $pool->reset(PoolQuantity::POOL_QUANTITY_TYPE); $pool->reset(PoolQuantity::POOL_RESERVE_TYPE); return $result; } /** * @param Sale\OrderBase $order * @param array $context * * @return array */ private static function prepareContext(Sale\OrderBase $order, array $context = array()) { if (empty($context)) { $context = [ 'SITE_ID' => $order->getSiteId(), 'USER_ID' => $order->getUserId(), 'CURRENCY' => $order->getCurrency(), ]; } if (!empty($context)) { if (empty($context['SITE_ID'])) { $context['SITE_ID'] = $order->getSiteId(); } if (empty($context['USER_ID']) && $order->getUserId() > 0) { $context['USER_ID'] = $order->getUserId(); } if (empty($context['CURRENCY'])) { $context['CURRENCY'] = $order->getCurrency(); } } return $context; } /** * @param array $context * * @return Sale\Result * @throws Main\ArgumentNullException */ private static function checkContext(array $context) { $result = new Sale\Result(); if (empty($context['SITE_ID'])) { throw new Main\ArgumentNullException('SITE_ID'); } if (empty($context['CURRENCY'])) { throw new Main\ArgumentNullException('CURRENCY'); } return $result; } /** * @param $module * @param $name * * @return string|null * @throws Main\LoaderException */ public static function getProviderName($module, $name) { static $providerProxy = array(); $code = $module."|".$name; if (array_key_exists($code, $providerProxy)) { return $providerProxy[$code]; } $providerName = null; if (strval($module) != '' && Main\Loader::includeModule($module) && class_exists($name)) { $provider = self::getProviderEntity($name); if ($provider) { $providerName = $name; } } if ($providerName !== null) { $providerProxy[$code] = $providerName; } return $providerName; } /** * @param $name * * @return mixed|null */ public static function getProviderEntity($name) { static $providerEntityProxy = array(); if (array_key_exists($name, $providerEntityProxy)) { return $providerEntityProxy[$name]; } if ( class_exists($name) && ( is_subclass_of($name, Sale\SaleProviderBase::class) || is_subclass_of($name, \IBXSaleProductProvider::class) ) ) { $providerEntityProxy[$name] = new $name(); return $providerEntityProxy[$name]; } return null; } /** * @param $providerName * * @return string */ private static function clearProviderName($providerName) { if (empty($providerName) || !is_string($providerName)) { return ''; } if (mb_substr($providerName, 0, 1) === "\\") { $providerName = mb_substr($providerName, 1); } return trim($providerName); } /** * @internal * @param $value */ public static function setIgnoreErrors($value) { self::$ignoreErrors = ($value === true); } /** * @internal * @return bool */ public static function isIgnoreErrors() { return self::$ignoreErrors; } }