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/ |
Upload File : |
<?php namespace Bitrix\Sale\Internals; use Bitrix\Main; use Bitrix\Sale; /** * Class ShipmentRules * @package Bitrix\Sale\Internals */ class ShipmentRules { /** * ShipmentRules constructor. */ protected function __construct() {} /** * @param Sale\Order $order * @param PoolQuantity $pool * * @return array */ public static function createOrderRuleMap(Sale\Order $order, PoolQuantity $pool) { $resultList = array(); $productPool = ItemsPool::getPoolByCode($order->getInternalId()); if (empty($productPool)) { return $resultList; } foreach ($productPool as $productId => $itemList) { foreach ($itemList as $item) { if ($item instanceof Sale\ShipmentItem) { $itemRule = static::createReserveRuleForShipmentItem($item, $pool); if (!empty($itemRule) && is_array($itemRule)) { $resultList[] = $itemRule; } $itemRule = static::createShipRule($item, $pool); if (!empty($itemRule) && is_array($itemRule)) { $resultList[] = $itemRule; } } elseif ($item instanceof Sale\ReserveQuantity) { $itemRule = static::createReserveRule($item, $pool, $productId); if (!empty($itemRule) && is_array($itemRule)) { $resultList[] = $itemRule; } } } } return $resultList; } /** * @param Sale\ShipmentItem $shipmentItem * @param PoolQuantity $pool * * @return array|bool * @throws Main\ObjectNotFoundException */ private static function createShipRule(Sale\ShipmentItem $shipmentItem, PoolQuantity $pool) { $basketItem = $shipmentItem->getBasketItem(); if (!$basketItem->isReservableItem()) { return false; } $poolQuantitiesList = $pool->getQuantitiesWithStore(PoolQuantity::POOL_QUANTITY_TYPE); if (empty($poolQuantitiesList)) { return false; } $shipment = $shipmentItem->getCollection()->getShipment(); $coefficient = 1; if ($shipment->needShip() === Sale\Internals\Catalog\Provider::SALE_TRANSFER_PROVIDER_SHIPMENT_NEED_SHIP) { $coefficient = -1; } $needUseReserve = $coefficient < 1 || Sale\Configuration::isEnableAutomaticReservation(); $productId = $basketItem->getProductId(); $rule = array( 'SHIPMENT_ITEM' => $shipmentItem, 'BASKET_ITEM' => $basketItem, 'PRODUCT_ID' => $productId, 'PROVIDER_NAME' => $basketItem->getProvider(), ); $storeData = Sale\Internals\Catalog\Provider::createMapShipmentItemStoreData($shipmentItem, $needUseReserve); if (!empty($storeData)) { $reservedQuantity = 0; $needReserveByStore = []; foreach ($storeData as $item) { $reservedQuantity += $item['RESERVED_QUANTITY']; $needReserveByStore[$item['STORE_ID']] = $item['RESERVED_QUANTITY'] > 0; } $rule['STORE_DATA'] = [ $shipmentItem->getInternalIndex() => $storeData ]; $rule['NEED_RESERVE'] = $reservedQuantity > 0; $rule['NEED_RESERVE_BY_STORE'] = [ $shipmentItem->getInternalIndex() => $needReserveByStore ]; } else { $rule['NEED_RESERVE'] = $basketItem->getReservedQuantity() > 0; $rule['NEED_RESERVE_BY_STORE'] = [ $shipmentItem->getInternalIndex() => [ Sale\Configuration::getDefaultStoreId() => $rule['NEED_RESERVE'] ] ]; $reservedQuantity = 0; /** @var Sale\ReserveQuantityCollection $reserveQuantityCollection */ $reserveQuantityCollection = $basketItem->getReserveQuantityCollection(); if ($reserveQuantityCollection) { $reservedQuantity = $reserveQuantityCollection->getQuantityByStoreId( Sale\Configuration::getDefaultStoreId() ); } if ($shipmentItem->getQuantity() < $reservedQuantity) { $reservedQuantity = $shipmentItem->getQuantity(); } $rule['RESERVED_QUANTITY'] = $reservedQuantity; $rule['RESERVED_QUANTITY_BY_STORE'] = [ $shipmentItem->getInternalIndex() => [ Sale\Configuration::getDefaultStoreId() => $reservedQuantity ] ]; } if (array_key_exists($productId, $poolQuantitiesList)) { $quantityByStore = []; foreach ($storeData as $item) { $storeId = $item['STORE_ID']; $quantity = $coefficient * $item['QUANTITY']; if (!isset($quantityByStore[$storeId])) { $quantityByStore[$storeId] = 0; } $quantityByStore[$storeId] += $quantity; $poolQuantity = $poolQuantitiesList[$productId][$storeId] - $quantity; $pool->setByStore(PoolQuantity::POOL_QUANTITY_TYPE, $productId, $storeId, $poolQuantity); } if ($quantityByStore) { $rule['ACTION'][PoolQuantity::POOL_QUANTITY_TYPE] = [ 'QUANTITY_BY_STORE' => $quantityByStore, 'QUANTITY' => array_sum($quantityByStore) ]; } else { $storeId = Sale\Configuration::getDefaultStoreId(); $quantity = $coefficient * $shipmentItem->getQuantity(); $rule['ACTION'][PoolQuantity::POOL_QUANTITY_TYPE] = [ 'QUANTITY' => $quantity, 'QUANTITY_BY_STORE' => [ $storeId => $quantity ] ]; } } return $rule; } /** * @param Sale\ShipmentItem $shipmentItem * @param PoolQuantity $pool * * @return array|bool * @throws Main\ObjectNotFoundException */ private static function createReserveRuleForShipmentItem(Sale\ShipmentItem $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() === Sale\Internals\Catalog\Provider::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 Sale\ShipmentItemStoreCollection $shipmentItemStoreCollection */ $shipmentItemStoreCollection = $shipmentItem->getShipmentItemStoreCollection(); if ($shipmentItemStoreCollection) { /** @var Sale\ShipmentItemStore $itemStore */ foreach ($shipmentItemStoreCollection as $itemStore) { if ( isset($poolReservationList[$productId][$itemStore->getStoreId()]) && $poolReservationList[$productId][$itemStore->getStoreId()] == 0 ) { continue; } /** @var Sale\ReserveQuantity $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 = Sale\Configuration::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; } /** * @param Sale\ReserveQuantity $reserve * @param PoolQuantity $pool * @param int $productId * * @return array|bool */ private static function createReserveRule(Sale\ReserveQuantity $reserve, PoolQuantity $pool, int $productId) { $basketItem = $reserve->getCollection()->getBasketItem(); $poolReservationList = $pool->getQuantitiesWithStore(PoolQuantity::POOL_RESERVE_TYPE); if ( empty($poolReservationList) || !isset($poolReservationList[$productId]) ) { return false; } $rule = [ 'PRODUCT_ID' => $productId, 'BASKET_ITEM' => $basketItem, 'PROVIDER_NAME' => $basketItem->getProvider(), 'RESERVE_ITEM' => $reserve, 'STORE' => [] ]; $quantityByStore = []; if ($reserve->getQuantity() > 0) { $quantity = $reserve->getFields()->getOriginalValues()['QUANTITY'] ?? 0; $quantityByStore = [ $reserve->getStoreId() => $reserve->getQuantity() - $quantity ]; } elseif ($reserve->getQuantity() == 0) { $quantity = $reserve->getFields()->getOriginalValues()['QUANTITY']; $quantityByStore = [$reserve->getStoreId() => -$quantity]; } if ($quantityByStore) { $rule['ACTION'][PoolQuantity::POOL_RESERVE_TYPE] = [ 'QUANTITY_BY_STORE' => $quantityByStore, 'QUANTITY' => array_sum($quantityByStore), ]; } $pool->setByStore(PoolQuantity::POOL_RESERVE_TYPE, $productId, $reserve->getStoreId(), 0); return $rule; } /** * @param array $rules * @param array $context * * @return Sale\Result * @throws Main\ObjectNotFoundException */ public static function saveRules(array $rules, array $context) { $result = new Sale\Result(); $shipProductsList = array(); foreach ($rules as $ruleData) { if (empty($ruleData['ACTION'])) { continue; } foreach ($ruleData['ACTION'] as $action => $quantityItem) { if (is_array($quantityItem)) { $quantity = $quantityItem['QUANTITY']; $quantityByStore = $quantityItem['QUANTITY_BY_STORE'] ?? 0; } else { $quantity = $quantityItem; $quantityByStore = []; } if ($quantity == 0) { continue; } $fields = $ruleData; $fields['QUANTITY'] = $quantity; $fields['QUANTITY_BY_STORE'] = $quantityByStore; unset($fields['ACTION']); if ($action === PoolQuantity::POOL_QUANTITY_TYPE) { $shipProductsList[] = $fields; } elseif ($action === PoolQuantity::POOL_RESERVE_TYPE) { $reserveProductsList[] = $fields; } } } if (!empty($reserveProductsList)) { if (self::isHasDoubleBasketItems($reserveProductsList)) { // each item is processed separately so that the number of identical basket items is not summed up. foreach ($reserveProductsList as $reserveProductData) { $creator = Sale\Internals\ProviderCreator::create($context); $creator->addProductData($reserveProductData); $r = $creator->reserve(); if (!$r->isSuccess()) { $result->addErrors($r->getErrors()); } } } else { $creator = Sale\Internals\ProviderCreator::create($context); foreach ($reserveProductsList as $reserveProductData) { $creator->addProductData($reserveProductData); } $r = $creator->reserve(); if (!$r->isSuccess()) { $result->addErrors($r->getErrors()); } } } if (!empty($shipProductsList)) { $creator = Sale\Internals\ProviderCreator::create($context); foreach ($shipProductsList as $shipProductData) { $creator->addProductData($shipProductData); } $r = $creator->ship(); if (!$r->isSuccess()) { $result->addErrors($r->getErrors()); } if ($r->hasWarnings()) { $result->addWarnings($r->getWarnings()); } $r = $creator->setItemsResultAfterShip($r); if (!$r->isSuccess()) { $result->addErrors($r->getErrors()); } } return $result; } /** * There are duplicate basket items in the list of reserve items. * * @param array $reserveProductsList * * @return bool */ private static function isHasDoubleBasketItems(array $reserveProductsList): bool { if (count($reserveProductsList) <= 1) { return false; } $map = []; foreach ($reserveProductsList as $item) { $basketItem = $item['BASKET_ITEM'] ?? null; if ($basketItem instanceof Sale\BasketItem) { $basketCode = $basketItem->getBasketCode(); if (isset($map[$basketCode])) { return true; } $map[$basketCode] = true; } } return false; } }