27 $resultList = array();
30 if (empty($productPool))
35 foreach ($productPool as $productId => $itemList)
37 foreach ($itemList as $item)
41 $itemRule = static::createReserveRuleForShipmentItem($item, $pool);
42 if (!empty($itemRule) && is_array($itemRule))
44 $resultList[] = $itemRule;
47 $itemRule = static::createShipRule($item, $pool);
48 if (!empty($itemRule) && is_array($itemRule))
50 $resultList[] = $itemRule;
55 $itemRule = static::createReserveRule($item, $pool, $productId);
56 if (!empty($itemRule) && is_array($itemRule))
58 $resultList[] = $itemRule;
76 $basketItem = $shipmentItem->getBasketItem();
77 if (!$basketItem->isReservableItem())
83 if (empty($poolQuantitiesList))
88 $shipment = $shipmentItem->getCollection()->getShipment();
91 if ($shipment->needShip() ===
Sale\Internals\Catalog\Provider::SALE_TRANSFER_PROVIDER_SHIPMENT_NEED_SHIP)
96 $needUseReserve = $coefficient < 1 || Sale\Configuration::isEnableAutomaticReservation();
98 $productId = $basketItem->getProductId();
101 'SHIPMENT_ITEM' => $shipmentItem,
102 'BASKET_ITEM' => $basketItem,
103 'PRODUCT_ID' => $productId,
104 'PROVIDER_NAME' => $basketItem->getProvider(),
107 $storeData = Sale\Internals\Catalog\Provider::createMapShipmentItemStoreData($shipmentItem, $needUseReserve);
108 if (!empty($storeData))
110 $reservedQuantity = 0;
111 $needReserveByStore = [];
112 foreach ($storeData as $item)
114 $reservedQuantity += $item[
'RESERVED_QUANTITY'];
116 $needReserveByStore[$item[
'STORE_ID']] = $item[
'RESERVED_QUANTITY'] > 0;
119 $rule[
'STORE_DATA'] = [
120 $shipmentItem->getInternalIndex() => $storeData
123 $rule[
'NEED_RESERVE'] = $reservedQuantity > 0;
125 $rule[
'NEED_RESERVE_BY_STORE'] = [
126 $shipmentItem->getInternalIndex() => $needReserveByStore
131 $rule[
'NEED_RESERVE'] = $basketItem->getReservedQuantity() > 0;
132 $rule[
'NEED_RESERVE_BY_STORE'] = [
133 $shipmentItem->getInternalIndex() => [
134 Sale\Configuration::getDefaultStoreId() => $rule[
'NEED_RESERVE']
138 $reservedQuantity = 0;
141 $reserveQuantityCollection = $basketItem->getReserveQuantityCollection();
142 if ($reserveQuantityCollection)
144 $reservedQuantity = $reserveQuantityCollection->getQuantityByStoreId(
149 if ($shipmentItem->getQuantity() < $reservedQuantity)
151 $reservedQuantity = $shipmentItem->getQuantity();
154 $rule[
'RESERVED_QUANTITY'] = $reservedQuantity;
155 $rule[
'RESERVED_QUANTITY_BY_STORE'] = [
156 $shipmentItem->getInternalIndex() => [
157 Sale\Configuration::getDefaultStoreId() => $reservedQuantity
162 if (array_key_exists($productId, $poolQuantitiesList))
164 $quantityByStore = [];
165 foreach ($storeData as $item)
168 $quantity = $coefficient * $item[
'QUANTITY'];
170 if (!isset($quantityByStore[$storeId]))
175 $quantityByStore[
$storeId] += $quantity;
182 if ($quantityByStore)
185 'QUANTITY_BY_STORE' => $quantityByStore,
186 'QUANTITY' => array_sum($quantityByStore)
191 $storeId = Sale\Configuration::getDefaultStoreId();
193 $quantity = $coefficient * $shipmentItem->getQuantity();
196 'QUANTITY' => $quantity,
197 'QUANTITY_BY_STORE' => [
214 private static function createReserveRuleForShipmentItem(
Sale\ShipmentItem $shipmentItem, PoolQuantity $pool)
216 $basketItem = $shipmentItem->getBasketItem();
217 if (!$basketItem->isReservableItem())
222 $reserveCollection = $basketItem->getReserveQuantityCollection();
223 if (!$reserveCollection)
229 if (empty($poolReservationList))
234 $shipment = $shipmentItem->getCollection()->getShipment();
235 if ($shipment->needShip() ===
Sale\Internals\Catalog\Provider::SALE_TRANSFER_PROVIDER_SHIPMENT_NEED_NOT_SHIP)
243 'SHIPMENT_ITEM' => $shipmentItem,
244 'BASKET_ITEM' => $basketItem,
246 'PROVIDER_NAME' => $basketItem->getProvider(),
250 if (!isset($poolReservationList[$productId]))
255 $needReserveQuantity = $shipmentItem->getNeedReserveQuantity();
256 if ($needReserveQuantity == 0)
258 $needQuantityByStore = $poolReservationList[
$productId];
260 'QUANTITY_BY_STORE' => $needQuantityByStore,
261 'QUANTITY' => array_sum($needQuantityByStore),
269 $needQuantityByStore = [];
272 $shipmentItemStoreCollection = $shipmentItem->getShipmentItemStoreCollection();
273 if ($shipmentItemStoreCollection)
276 foreach ($shipmentItemStoreCollection as $itemStore)
279 isset($poolReservationList[$productId][$itemStore->getStoreId()])
280 && $poolReservationList[$productId][$itemStore->getStoreId()] == 0
287 foreach ($reserveCollection as $reserve)
290 $reserve->getStoreId() !== $itemStore->getStoreId()
291 || !$reserve->getFields()->isChanged(
'QUANTITY')
297 if (!isset($needQuantityByStore[$reserve->getStoreId()]))
299 $needQuantityByStore[$reserve->getStoreId()] = 0;
302 $needQuantity = $reserve->getQuantity() - $reserve->getFields()->getOriginalValues()[
'QUANTITY'];
303 if (abs($needQuantity) > abs($needReserveQuantity))
305 $needQuantityByStore[$reserve->getStoreId()] += $needReserveQuantity;
306 $needReserveQuantity = 0;
307 $poolReservationList[
$productId][$reserve->getStoreId()] -= $needReserveQuantity;
311 $needQuantityByStore[$reserve->getStoreId()] += $needQuantity;
312 $needReserveQuantity -= $needQuantity;
313 $poolReservationList[
$productId][$reserve->getStoreId()] -= $needQuantity;
319 if ($needReserveQuantity != 0)
321 $storeId = Sale\Configuration::getDefaultStoreId();
322 if (!isset($needQuantityByStore[$storeId]))
327 foreach ($reserveCollection as $reserve)
330 !$reserve->getStoreId() === $storeId
331 || !$reserve->getFields()->isChanged(
'QUANTITY')
337 $needQuantity = $reserve->getQuantity() - $reserve->getFields()->getOriginalValues()[
'QUANTITY'];
338 if (abs($needQuantity) > abs($needReserveQuantity))
340 $needQuantityByStore[$reserve->getStoreId()] += $needReserveQuantity;
341 $needReserveQuantity = 0;
342 $poolReservationList[
$productId][$reserve->getStoreId()] -= $needReserveQuantity;
346 $needQuantityByStore[$reserve->getStoreId()] += $needQuantity;
347 $needReserveQuantity -= $needQuantity;
348 $poolReservationList[
$productId][$reserve->getStoreId()] -= $needQuantity;
352 if ($needReserveQuantity != 0)
354 foreach ($poolReservationList[$productId] as $storeId => $quantity)
356 if ($needReserveQuantity == 0)
363 if (!isset($needQuantityByStore[$storeId]))
368 if (abs($needReserveQuantity) > abs($quantity))
370 $needQuantityByStore[
$storeId] += $quantity;
371 $needReserveQuantity -= $quantity;
377 $needQuantityByStore[
$storeId] += $needReserveQuantity;
378 $needReserveQuantity = 0;
389 foreach ($poolReservationList as $productId => $quantityByStore)
391 foreach ($quantityByStore as $storeId => $quantity)
398 'QUANTITY_BY_STORE' => $needQuantityByStore,
399 'QUANTITY' => array_sum($needQuantityByStore),
412 private static function createReserveRule(
Sale\ReserveQuantity $reserve, PoolQuantity $pool,
int $productId)
414 $basketItem = $reserve->getCollection()->getBasketItem();
418 empty($poolReservationList)
419 || !isset($poolReservationList[$productId])
427 'BASKET_ITEM' => $basketItem,
428 'PROVIDER_NAME' => $basketItem->getProvider(),
429 'RESERVE_ITEM' => $reserve,
433 $quantityByStore = [];
434 if ($reserve->getQuantity() > 0)
436 $quantity = $reserve->getFields()->getOriginalValues()[
'QUANTITY'] ?? 0;
438 $reserve->getStoreId() => $reserve->getQuantity() - $quantity
441 elseif ($reserve->getQuantity() == 0)
443 $quantity = $reserve->getFields()->getOriginalValues()[
'QUANTITY'];
444 $quantityByStore = [$reserve->getStoreId() => -$quantity];
447 if ($quantityByStore)
450 'QUANTITY_BY_STORE' => $quantityByStore,
451 'QUANTITY' => array_sum($quantityByStore),
468 public static function saveRules(array $rules, array $context)
471 $shipProductsList = array();
473 foreach ($rules as $ruleData)
475 if (empty($ruleData[
'ACTION']))
480 foreach ($ruleData[
'ACTION'] as $action => $quantityItem)
482 if (is_array($quantityItem))
484 $quantity = $quantityItem[
'QUANTITY'];
485 $quantityByStore = $quantityItem[
'QUANTITY_BY_STORE'] ?? 0;
489 $quantity = $quantityItem;
490 $quantityByStore = [];
499 $fields[
'QUANTITY'] = $quantity;
500 $fields[
'QUANTITY_BY_STORE'] = $quantityByStore;
501 unset($fields[
'ACTION']);
505 $shipProductsList[] = $fields;
509 $reserveProductsList[] = $fields;
514 if (!empty($reserveProductsList))
516 if (self::isHasDoubleBasketItems($reserveProductsList))
519 foreach ($reserveProductsList as $reserveProductData)
521 $creator = Sale\Internals\ProviderCreator::create($context);
522 $creator->addProductData($reserveProductData);
523 $r = $creator->reserve();
524 if (!$r->isSuccess())
526 $result->addErrors($r->getErrors());
532 $creator = Sale\Internals\ProviderCreator::create($context);
533 foreach ($reserveProductsList as $reserveProductData)
535 $creator->addProductData($reserveProductData);
538 $r = $creator->reserve();
539 if (!$r->isSuccess())
541 $result->addErrors($r->getErrors());
546 if (!empty($shipProductsList))
548 $creator = Sale\Internals\ProviderCreator::create($context);
549 foreach ($shipProductsList as $shipProductData)
551 $creator->addProductData($shipProductData);
554 $r = $creator->ship();
555 if (!$r->isSuccess())
557 $result->addErrors($r->getErrors());
560 if ($r->hasWarnings())
562 $result->addWarnings($r->getWarnings());
565 $r = $creator->setItemsResultAfterShip($r);
566 if (!$r->isSuccess())
568 $result->addErrors($r->getErrors());
583 private static function isHasDoubleBasketItems(array $reserveProductsList): bool
585 if (count($reserveProductsList) <= 1)
591 foreach ($reserveProductsList as $item)
593 $basketItem = $item[
'BASKET_ITEM'] ??
null;
596 $basketCode = $basketItem->getBasketCode();
597 if (isset($map[$basketCode]))
602 $map[$basketCode] =
true;