1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
providerbase.php
См. документацию.
1<?php
8
9namespace Bitrix\Sale;
10
11use Bitrix\Main\ArgumentNullException;
12use Bitrix\Main\ArgumentTypeException;
13use Bitrix\Main\Localization\Loc;
14use Bitrix\Main\NotImplementedException;
15use Bitrix\Main\NotSupportedException;
16use Bitrix\Main\ObjectNotFoundException;
17use Bitrix\Main\SystemException;
18use Bitrix\Sale;
19use Bitrix\Sale\Internals;
20use Bitrix\Currency;
21use Bitrix\Sale\Reservation\Configuration\ReserveCondition;
22
23Loc::loadMessages(__FILE__);
24
29abstract class ProviderBase
30{
32 protected static $reservationPool = array();
33
35 protected static $hitCache = array();
36
38 protected static $trustData = array();
39
41 protected static $useReadTrustData = false;
42
44 protected static $quantityPool = array();
45
46 static $productData = array();
47
48 const POOL_ACTION_RESERVATION = "RESERVE";
49 const POOL_ACTION_SHIP = "SHIP";
50
55 protected static function getReservationPool($key)
56 {
58 return $pool->getByType(Internals\PoolQuantity::POOL_RESERVE_TYPE);
59 }
60
66 protected static function resetReservationPool($key)
67 {
70 }
71
77 public static function getReservationPoolItem($key, BasketItem $item)
78 {
80 return $pool->get(Internals\PoolQuantity::POOL_RESERVE_TYPE, $item->getField('PRODUCT_ID'));
81 }
82
88 protected static function setReservationPoolItem($key, BasketItem $item, $value)
89 {
91 $code = $item->getBasketCode()."|".$item->getField('MODULE')."|".$item->getField('PRODUCT_ID');
92 $poolInstance->set(Internals\PoolQuantity::POOL_RESERVE_TYPE, $code, $value);
93
94 $pool = $poolInstance->getByType(Internals\PoolQuantity::POOL_RESERVE_TYPE);
95 $pool->addItem($code, $item);
96 }
97
103 protected static function addReservationPoolItem($key, BasketItem $item, $value)
104 {
106 $pool->add(Internals\PoolQuantity::POOL_RESERVE_TYPE, $item->getField('PRODUCT_ID'), $value);
107 }
108
113 protected static function getQuantityPool($key)
114 {
116 return $pool->getByType(Internals\PoolQuantity::POOL_QUANTITY_TYPE);
117 }
118
122 protected static function resetQuantityPool($key)
123 {
126 }
127
133 public static function getQuantityPoolItem($key, BasketItem $item)
134 {
136 return $pool->get(Internals\PoolQuantity::POOL_QUANTITY_TYPE, $item->getField('PRODUCT_ID'));
137 }
138
144 protected static function setQuantityPoolItem($key, BasketItem $item, $value)
145 {
146 $code = $item->getBasketCode()."|".$item->getField('MODULE')."|".$item->getField('PRODUCT_ID');
148 $poolInstance->set(Internals\PoolQuantity::POOL_RESERVE_TYPE, $code, $value);
149
150 $pool = $poolInstance->getByType(Internals\PoolQuantity::POOL_RESERVE_TYPE);
151 $pool->addItem($code, $item);
152 }
153
161 public static function addQuantityPoolItem($key, BasketItem $item, $value)
162 {
164 $pool->add(Internals\PoolQuantity::POOL_QUANTITY_TYPE, $item->getField('PRODUCT_ID'), $value);
165 }
166
173 public static function onOrderSave(Order $order)
174 {
175 $result = new Result();
176
177 static::resetTrustData($order->getSiteId());
178
181 if (!$r->isSuccess())
182 {
183 $result->addErrors($r->getErrors());
184 }
185
186 if ($r->hasWarnings())
187 {
188 $result->addWarnings($r->getWarnings());
189 EntityMarker::addMarker($order, $order, $r);
190 if ($order->getId() > 0)
191 {
192 Internals\OrderTable::update($order->getId(), array('MARKED' => 'Y'));
193 }
194 }
195
196 static::refreshMarkers($order);
197
198 return $result;
199 }
200
201
210 public static function shipBasketItem(BasketItemBase $basketItem)
211 {
212
213 $result = new Result();
214
216 if (!$basket = $basketItem->getCollection())
217 {
218 throw new ObjectNotFoundException('Entity "Basket" not found');
219 }
220
222 if (!$order = $basket->getOrder())
223 {
224 throw new ObjectNotFoundException('Entity "Order" not found');
225 }
226
228 $shipmentCollection = $order->getShipmentCollection();
229
231 foreach ($shipmentCollection as $shipment)
232 {
233 $needShip = $shipment->needShip();
234 if ($needShip === null)
235 continue;
236
237 $r = static::shipShipment($shipment);
238 if (!$r->isSuccess())
239 {
240 $result->addErrors($r->getErrors());
241 }
242 elseif ($r->hasWarnings())
243 {
244 $result->addWarnings($r->getWarnings());
245 EntityMarker::addMarker($order, $shipment, $r);
246 if (!$shipment->isSystem())
247 {
248 $shipment->setField('MARKED', 'Y');
249 }
250 }
251 }
252
253 return $result;
254 }
255
262 public static function shipShipment(Shipment $shipment)
263 {
264 $result = new Result();
265
267 if (!$shipmentItemCollection = $shipment->getShipmentItemCollection())
268 {
269 throw new ObjectNotFoundException('Entity "ShipmentCollection" not found');
270 }
271
273 if (!$shipmentCollection = $shipment->getCollection())
274 {
275 throw new ObjectNotFoundException('Entity "ShipmentCollection" not found');
276 }
277
279 if (!$order = $shipmentCollection->getOrder())
280 {
281 throw new ObjectNotFoundException('Entity "Order" not found');
282 }
283
284 $pool = Internals\PoolQuantity::getInstance($order->getInternalId());
285 $quantityPool = $pool->getQuantities(Internals\PoolQuantity::POOL_QUANTITY_TYPE);
286 if (empty($quantityPool))
287 {
288 return $result;
289 }
290
291 $reverse = false;
292
293 $resultList = array();
294
295 $basketList = static::getBasketFromShipmentItemCollection($shipmentItemCollection);
296
297 $basketProviderMap = static::createProviderBasketMap($basketList, array('QUANTITY', 'RESERVED'));
298 $basketProviderList = static::redistributeToProviders($basketProviderMap);
299 $storeDataList = array();
300
302 {
303
305 $r = static::getStoreDataFromShipmentItemCollection($shipmentItemCollection);
306 if (!$r->isSuccess())
307 {
308 $result->addErrors($r->getErrors());
309 }
310 else
311 {
312 $resultStoreData = $r->getData();
313 if (!empty($resultStoreData['STORE_DATA_LIST']))
314 {
315 $storeDataList = $resultStoreData['STORE_DATA_LIST'];
316 }
317
318 }
319 }
320
321 if (!empty($basketProviderList))
322 {
323 foreach ($basketProviderList as $provider => $providerBasketItemList)
324 {
325 if ($provider && array_key_exists("IBXSaleProductProvider", class_implements($provider)))
326 {
327
328 foreach ($providerBasketItemList as $providerBasketItem)
329 {
330
331 if ($providerBasketItem['BASKET_ITEM']->isBundleParent())
332 {
333 continue;
334 }
335
336 $poolQuantity = static::getQuantityPoolItem($order->getInternalId(), $providerBasketItem['BASKET_ITEM']);
337
338 if ($poolQuantity == 0)
339 continue;
340
341 if ($providerBasketItem['BASKET_ITEM']->getField('MODULE') != '')
342 {
343 $shipFields = array_merge($providerBasketItem, array(
344 'DEDUCTION' => ($poolQuantity < 0)
345 ));
346
347 $r = static::shipProductData($provider, $shipFields, $storeDataList);
348
349 if (!$r->isSuccess())
350 {
351 $result->addErrors($r->getErrors());
352 }
353 $resultProductData = $r->getData();
354
355 }
356 else
357 {
358 $resultProductData['RESULT'] = true;
359 }
360
361 $resultList[$providerBasketItem['BASKET_CODE']] = $resultProductData;
362
363 if (array_key_exists("RESULT", $resultProductData)
364 && $resultProductData['RESULT'] === false && $poolQuantity < 0)
365 {
366 $reverse = true;
367 break;
368 }
369
370 }
371
372 }
373 elseif (class_exists($provider))
374 {
375 $context = array(
376 'SITE_ID' => $order->getSiteId(),
377 'CURRENCY' => $order->getCurrency(),
378 );
379
380 if ($order->getUserId() > 0)
381 {
382 $context['USER_ID'] = $order->getUserId();
383 }
384 else
385 {
386 global $USER;
387 $context['USER_ID'] = $USER->getId();
388 }
389
390 $creator = Internals\ProviderCreator::create($context);
392 foreach ($shipmentItemCollection as $shipmentItem)
393 {
394 $basketItem = $shipmentItem->getBasketItem();
395 $providerClass = $basketItem->getProviderEntity();
396
397 if ($providerClass instanceof SaleProviderBase)
398 {
399 $shipmentProductData = $creator->createItemForShip($shipmentItem);
400 $creator->addProductData($shipmentProductData);
401 }
402 }
403
404 $r = $creator->ship();
405 if (!$r->isSuccess())
406 {
407 $result->addErrors($r->getErrors());
408 }
409
410 $r = $creator->setItemsResultAfterShip($r);
411 if (!$r->isSuccess())
412 {
413 $result->addErrors($r->getErrors());
414 }
415 }
416 }
417 }
418
419 if ($reverse === true)
420 {
421 static::reverseShipment($shipment, $resultList);
422 }
423 else
424 {
425 static::setShipmentItemReserved($shipment);
426 }
427
428 return $result;
429 }
430
438 public static function shipProductData($provider, array $fields, array $storeDataList = array())
439 {
440 $result = new Result();
441
442 $quantity = $fields['QUANTITY'];
443 $basketCode = $fields['BASKET_CODE'];
444
446 $basketItem = $fields['BASKET_ITEM'];
447
449 $basket = $basketItem->getCollection();
450
452 $order = $basket->getOrder();
453
454 $data = array(
455 "BASKET_ITEM" => $basketItem,
456 "PRODUCT_ID" => $fields['PRODUCT_ID'],
457 "QUANTITY" => $quantity,
458 "PRODUCT_RESERVED" => "N",
459 'UNDO_DEDUCTION' => $fields['DEDUCTED']? 'N' : 'Y',
460 'EMULATE' => 'N',
461 );
462
463 if ($data['UNDO_DEDUCTION'] == 'N')
464 {
465 $data['PRODUCT_RESERVED'] = "Y";
466 }
467
468 if (!empty($fields['RESERVED']))
469 {
470 $data['PRODUCT_RESERVED'] = $fields['RESERVED'] ? 'Y' : 'N';
471 }
472
473 $resultProductData = array();
474
476 {
477
478 if (!empty($storeDataList) && is_array($storeDataList) && isset($storeDataList[$basketCode]))
479 {
480 $data['STORE_DATA'] = $storeDataList[$basketCode];
481 }
482
483 if (!empty($data['STORE_DATA']))
484 {
485 $allBarcodeQuantity = 0;
486 foreach($data['STORE_DATA'] as $basketShipmentItemStore)
487 {
488 $allBarcodeQuantity += $basketShipmentItemStore['QUANTITY'];
489 }
490
491 if ($quantity > $allBarcodeQuantity)
492 {
493 $result->addWarning(new ResultWarning(Loc::getMessage('SALE_PROVIDER_SHIPMENT_SHIPPED_LESS_QUANTITY', array(
494 '#PRODUCT_NAME#' => $basketItem->getField('NAME')
495 )), 'SALE_PROVIDER_SHIPMENT_SHIPPED_LESS_QUANTITY'));
496
497 $resultProductData['RESULT'] = false;
498 }
499 elseif ($quantity < $allBarcodeQuantity)
500 {
501 $result->addWarning(new ResultWarning(Loc::getMessage('SALE_PROVIDER_SHIPMENT_SHIPPED_MORE_QUANTITY', array(
502 '#PRODUCT_NAME#' => $basketItem->getField('NAME')
503 )), 'SALE_PROVIDER_SHIPMENT_SHIPPED_MORE_QUANTITY'));
504
505 $resultProductData['RESULT'] = false;
506 }
507 }
508
509 }
510
511 if (!isset($resultProductData['RESULT'])
512 || $resultProductData['RESULT'] !== false)
513 {
514 global $APPLICATION;
515 $APPLICATION->ResetException();
516 $resultProductData = $provider::DeductProduct($data);
517
518 $result->setData($resultProductData);
519
520 $needShip = $fields['DEDUCTED'];
521 $oldException = $APPLICATION->GetException();
522 if (!empty($oldException))
523 {
524 if ($needShip === true)
525 {
526 $result->addWarning( new ResultWarning($oldException->GetString(), $oldException->GetID()) );
527 }
528 }
529
530 if (($oldException && $needShip === false) || !$oldException)
531 {
532 static::addQuantityPoolItem($order->getInternalId(), $basketItem, ($needShip? 1 : -1) * $quantity);
533 }
534 }
535
536 return $result;
537 }
538
545 private static function reverseShipment(Shipment $shipment, array $shippedList)
546 {
547 $needShip = $shipment->needShip();
548
549 $correct = null;
550
551 $shipmentItemCollection = $shipment->getShipmentItemCollection();
552 $basketList = static::getBasketFromShipmentItemCollection($shipmentItemCollection);
553
554 $bundleIndexList = static::getBundleIndexFromShipmentItemCollection($shipmentItemCollection);
555
556 $basketProviderMap = static::createProviderBasketMap($basketList, array('QUANTITY', 'RESERVED'));
557 $basketProviderList = static::redistributeToProviders($basketProviderMap);
558
560 {
562 $r = static::getStoreDataFromShipmentItemCollection($shipmentItemCollection);
563 }
564
565 if (!empty($basketProviderList))
566 {
567 foreach ($basketProviderList as $provider => $providerBasketItemList)
568 {
569 if ($provider && array_key_exists("IBXSaleProductProvider", class_implements($provider)))
570 {
571
572 foreach ($providerBasketItemList as $providerBasketItem)
573 {
574 if ($providerBasketItem['BASKET_ITEM']->isBundleParent())
575 {
576 continue;
577 }
578
579 $basketCode = $providerBasketItem['BASKET_CODE'];
580 if (!isset($shippedList[$basketCode])
581 || (array_key_exists("RESULT", $shippedList[$basketCode]) && $shippedList[$basketCode]['RESULT'] === false))
582 {
583 if ($needShip && $shipment->isShipped())
584 {
585 $correct = true;
586 }
587 continue;
588 }
589
590 if ($providerBasketItem['BASKET_ITEM']->getField('MODULE') != '')
591 {
592 $data = array(
593 "BASKET_ITEM" => $providerBasketItem['BASKET_ITEM'],
594 "PRODUCT_ID" => $providerBasketItem['PRODUCT_ID'],
595 "QUANTITY" => $providerBasketItem['QUANTITY'],
596 "PRODUCT_RESERVED" => "Y",
597 'UNDO_DEDUCTION' => $needShip? 'Y' : 'N',
598 'EMULATE' => 'N',
599 );
600
601 if (Configuration::useStoreControl() && !empty($storeData) && is_array($storeData) && isset($storeData[$providerBasketItem['BASKET_CODE']]))
602 {
603 $data['STORE_DATA'] = $storeData[$providerBasketItem['BASKET_CODE']];
604
605 $barcodeReverseList = array();
606
607 if (!empty($shippedList[$basketCode]['BARCODE']) && is_array($shippedList[$basketCode]['BARCODE']))
608 {
609 foreach ($shippedList[$basketCode]['BARCODE'] as $barcodeValue => $barcodeShipped)
610 {
611 if ($barcodeShipped === true)
612 {
613 $barcodeReverseList[] = $barcodeValue;
614 }
615 }
616
617 foreach ($data['STORE_DATA'] as $storeId => $barcodeData)
618 {
619 if (!empty($barcodeData['BARCODE']) && is_array($barcodeData['BARCODE']))
620 {
621 if (empty($barcodeReverseList))
622 {
623 $data['STORE_DATA'][$storeId]['BARCODE'] = array();
624 }
625 else
626 {
627 foreach ($barcodeData['BARCODE'] as $barcodeId => $barcodeValue)
628 {
629 if (!in_array($barcodeValue, $barcodeReverseList))
630 {
631 unset($data['STORE_DATA'][$storeId]['BARCODE'][$barcodeId]);
632 $data['STORE_DATA'][$storeId]['QUANTITY'] -= 1;
633 }
634 }
635 }
636
637 }
638 }
639 }
640 }
641
642 $resultProductData = $provider::DeductProduct($data);
643 }
644 else
645 {
646 $resultProductData['RESULT'] = true;
647 }
648
649
650 $result[$providerBasketItem['BASKET_CODE']] = $resultProductData;
651
652 if (isset($resultProductData['RESULT'])
653 && $resultProductData['RESULT'] === true)
654 {
655 $correct = true;
656 }
657
658 }
659
660 }
661 }
662 }
663
664 if ($correct === true)
665 {
666 $shipment->setFieldNoDemand('DEDUCTED', $needShip? 'N' : 'Y');
667 }
668
669 if (!empty($result)
670 && !empty($bundleIndexList) && is_array($bundleIndexList))
671 {
672
673 foreach ($bundleIndexList as $bundleParentBasketCode => $bundleChildList)
674 {
675 $tryShipmentBundle = false;
676 foreach($bundleChildList as $bundleChildBasketCode)
677 {
678 if (isset($result[$bundleChildBasketCode])
679 && $result[$bundleChildBasketCode]['RESULT'] === true)
680 {
681 $tryShipmentBundle = true;
682 }
683 else
684 {
685 $tryShipmentBundle = false;
686 break;
687 }
688 }
689
690 $result[$bundleParentBasketCode] = array(
691 'RESULT' => $tryShipmentBundle
692 );
693 }
694
695 }
696 }
697
704 private static function setShipmentItemReserved(Shipment $shipment)
705 {
706
707 $result = new Result();
708
709 $needShip = $shipment->needShip();
710
711 if ($needShip === null
712 || ($needShip === false && !$shipment->isReserved()))
713 {
714 return $result;
715 }
716
717 $order = $shipment->getParentOrder();
718 if (!$order)
719 {
720 throw new ObjectNotFoundException('Entity "Order" not found');
721 }
722
723 if (
725 && !$shipment->needReservation()
726 )
727 {
728 if ($needShip === false)
729 {
730 if (!Internals\ActionEntity::isTypeExists(
731 $order->getInternalId(),
733 )
734 )
735 {
736 Internals\ActionEntity::add(
737 $order->getInternalId(),
739 array(
740 'METHOD' => 'Bitrix\Sale\ShipmentCollection::updateReservedFlag',
741 'PARAMS' => array($shipment->getCollection())
742 )
743 );
744 }
745 }
746
747 return $result;
748 }
749
751 $shipmentItemCollection = $shipment->getShipmentItemCollection();
752
754 foreach ($shipmentItemCollection as $shipmentItem)
755 {
756
758 $basketItem = $shipmentItem->getBasketItem();
759 if (!$basketItem)
760 {
761 $result->addError(new ResultError(
762 Loc::getMessage(
763 'SALE_PROVIDER_BASKET_ITEM_NOT_FOUND',
764 [
765 '#BASKET_ITEM_ID#' => $shipmentItem->getBasketId(),
766 '#SHIPMENT_ID#' => $shipment->getId(),
767 '#SHIPMENT_ITEM_ID#' => $shipmentItem->getId(),
768 ]
769 ),
770 'PROVIDER_SET_SHIPMENT_ITEM_RESERVED_WRONG_BASKET_ITEM')
771 );
772
773 return $result;
774 }
775
776 $providerName = $basketItem->getProvider();
777 $providerClass = null;
778
779 if (class_exists($providerName))
780 {
781 $providerClass = new $providerName();
782 }
783 if ($providerClass && ($providerClass instanceof SaleProviderBase))
784 {
785 continue;
786 }
787
788 $setReservedQuantity = 0;
789 if ($needShip === false)
790 {
791 if ($basketItem->isBundleParent())
792 {
793 continue;
794 }
795 $setReservedQuantity = $shipmentItem->getQuantity();
796 }
797
798 $shipmentItem->setFieldNoDemand('RESERVED_QUANTITY', $setReservedQuantity);
799 }
800
801 if ($needShip === false)
802 {
803 if (!Internals\ActionEntity::isTypeExists(
804 $order->getInternalId(),
806 )
807 )
808 {
809 Internals\ActionEntity::add(
810 $order->getInternalId(),
812 array(
813 'METHOD' => 'Bitrix\Sale\ShipmentCollection::updateReservedFlag',
814 'PARAMS' => array($shipment->getCollection())
815 )
816 );
817 }
818 }
819
820 return $result;
821 }
822
829 public static function getProductAvailableQuantity(Basket $basketCollection, BasketItem $refreshItem = null)
830 {
831
832 static $proxyProductAvailableQuantity = array();
833 $resultList = array();
834 $userId = null;
835
836 if (($order = $basketCollection->getOrder()) !== null)
837 {
838 $userId = $order->getUserId();
839 }
840
841 $basketList = static::makeArrayFromBasketCollection($basketCollection, $refreshItem);
842
843 $basketProviderMap = static::createProviderBasketMap($basketList);
844 $basketProviderList = static::redistributeToProviders($basketProviderMap);
845
846 $context = array();
847 $productsList = array();
848 $providerList = array();
849 $basketCodeIndex = array();
850 if (!empty($basketProviderList))
851 {
852 foreach ($basketProviderList as $provider => $providerBasketItemList)
853 {
854 if (array_key_exists("IBXSaleProductProvider", class_implements($provider)))
855 {
856 foreach ($providerBasketItemList as $providerBasketItemData)
857 {
858
859 $proxyProductKey = $providerBasketItemData['PRODUCT_ID']."|".$userId;
860 if (!empty($proxyProductAvailableQuantity[$proxyProductKey]) && is_array($proxyProductAvailableQuantity[$proxyProductKey]))
861 {
862 $resultProductData = $proxyProductAvailableQuantity[$proxyProductKey];
863 }
864 else
865 {
866 $resultProductData = $resultProductData = $provider::getProductAvailableQuantity($providerBasketItemData['PRODUCT_ID'], $userId);
867 $proxyProductAvailableQuantity[$proxyProductKey] = $resultProductData;
868 }
869
870
871 $basketCode = $providerBasketItemData['BASKET_ITEM']->getBasketCode();
872 $resultList[$basketCode] = $resultProductData;
873 }
874 }
875 elseif (class_exists($provider))
876 {
877 if (empty($context))
878 {
879 if ($order)
880 {
881 $context = array(
882 'USER_ID' => $order->getUserId(),
883 'SITE_ID' => $order->getSiteId(),
884 'CURRENCY' => $order->getCurrency(),
885 );
886 }
887 else
888 {
889 global $USER;
890 $context = array(
891 'USER_ID' => $USER->getId(),
892 'SITE_ID' => SITE_ID,
893 'CURRENCY' => Currency\CurrencyManager::getBaseCurrency(),
894 );
895 }
896 }
897
898 $providerClass = new $provider($context);
899 if (!$providerClass instanceof SaleProviderBase)
900 {
901 continue;
902 }
903
905 foreach ($providerBasketItemList as $providerBasketItemData)
906 {
907 $basketItem = $providerBasketItemData['BASKET_ITEM'];
908
909 $productId = $basketItem->getProductId();
910 $basketCode = $basketItem->getBasketCode();
911 $basketCodeIndex[$productId][] = $basketItem->getBasketCode();
912
913 $providerList[$provider] = $providerClass;
914
915 if (empty($productsList[$provider][$productId]))
916 {
917 $productsList[$provider][$productId] = $providerBasketItemData;
918 }
919
920 $productsList[$provider][$productId]['QUANTITY_LIST'][$basketCode] = $basketItem->getQuantity();
921 $resultList[$basketCode] = 0;
922 }
923 }
924 else
925 {
926 foreach ($providerBasketItemList as $providerBasketItemData)
927 {
928 $resultProductData = \CSaleBasket::ExecuteCallbackFunction(
929 $providerBasketItemData['CALLBACK_FUNC'],
930 $providerBasketItemData['MODULE'],
931 $providerBasketItemData['PRODUCT_ID']
932 );
933
934 $basketCode = $providerBasketItemData['BASKET_ITEM']->getBasketCode();
935 $resultList[$basketCode] = $resultProductData;
936 }
937 }
938 }
939
940
941 if (!empty($productsList))
942 {
943 foreach ($productsList as $providerName => $products)
944 {
946 $providerClass = $providerList[$providerName];
947
948 $r = $providerClass->getAvailableQuantity($products);
949 if ($r->isSuccess())
950 {
951 $resultData = $r->getData();
952 if (!empty($resultData['AVAILABLE_QUANTITY_LIST']))
953 {
954
955 foreach ($resultData['AVAILABLE_QUANTITY_LIST'] as $productId => $availableQuantity)
956 {
957 if (!empty($basketCodeIndex[$productId]))
958 {
959 foreach ($basketCodeIndex[$productId] as $basketCode)
960 {
961 $resultList[$basketCode] = $availableQuantity;
962 }
963 }
964 }
965 }
966 }
967 }
968 }
969 }
970
971 return $resultList;
972 }
973
983 public static function getProductData(BasketItemCollection $basketCollection, array $select = array(), BasketItem $refreshItem = null)
984 {
985 $resultList = array();
986
987 $orderId = null;
988 $userId = null;
989 $siteId = null;
990 $currency = null;
991
992 if (($order = $basketCollection->getOrder()) !== null)
993 {
994 $userId = $order->getUserId();
995 $siteId = $order->getSiteId();
996 $currency = $order->getCurrency();
997 }
998
999 if ($siteId === null)
1000 {
1001 $basket = $basketCollection->getBasket();
1002 $siteId = $basket->getSiteId();
1003 }
1004
1005 if ($siteId === null)
1006 return array();
1007
1008 if ($currency === null)
1009 {
1011 if (!$currency)
1012 $currency = Currency\CurrencyManager::getBaseCurrency();
1013 }
1014
1015 $context = array(
1016 "USER_ID" => $userId,
1017 "SITE_ID" => $siteId,
1018 "CURRENCY" => $currency,
1019 );
1020
1021 $basketList = static::makeArrayFromBasketCollection($basketCollection, $refreshItem);
1022
1023 // Process each element separately so that it works correctly with duplicates.
1024 $basketProviderMap = static::createProviderBasketMap($basketList, array('QUANTITY', 'RENEWAL', 'SITE_ID', 'USER_ID'));
1025 foreach ($basketProviderMap as $basketProviderMapItem)
1026 {
1027 $basketProviderList = static::redistributeToProviders([
1028 $basketProviderMapItem,
1029 ]);
1030
1031 if (!empty($basketProviderList))
1032 {
1033 $options = array(
1034 'RETURN_BASKET_ID'
1035 );
1036
1037 foreach ($basketProviderList as $providerClassName => $productValueList)
1038 {
1039 $r = static::getProductDataByList($productValueList, $providerClassName, $select, $context, $options);
1040 if ($r->isSuccess())
1041 {
1042 $resultData = $r->getData();
1043 if (!empty($resultData['PRODUCT_DATA_LIST']))
1044 {
1045 $resultList = $resultData['PRODUCT_DATA_LIST'] + $resultList;
1046 }
1047 }
1048 }
1049
1050 }
1051 }
1052
1053 return $resultList;
1054 }
1055
1066 public static function getProductDataByList(array $products, $providerClassName, array $select, array $context, array $options = array())
1067 {
1068 $result = new Result();
1069 $resultList = array();
1070
1071 $needPrice = in_array('PRICE', $select);
1072 $needBasePrice = in_array('BASE_PRICE', $select);
1073 $needCoupons = in_array('COUPONS', $select);
1074 $data = array(
1075 'USER_ID' => $context['USER_ID'],
1076 'SITE_ID' => $context['SITE_ID'],
1077 'CURRENCY' => $context['CURRENCY'],
1078 'CHECK_QUANTITY' => (in_array('QUANTITY', $select) ? 'Y' : 'N'),
1079 'AVAILABLE_QUANTITY' => (in_array('AVAILABLE_QUANTITY', $select) ? 'Y' : 'N'),
1080 'CHECK_PRICE' => ($needPrice ? 'Y' : 'N'),
1081 'CHECK_COUPONS' => ($needCoupons ? 'Y' : 'N'),
1082 'RENEWAL' => (in_array('RENEWAL', $select) ? 'Y' : 'N')
1083 );
1084
1085 if ($needBasePrice)
1086 $data['CHECK_DISCOUNT'] = 'N';
1087
1088 $useOrderProduct = false;
1089 if ($needPrice)
1090 $useOrderProduct = true;
1091
1092 if ($needCoupons)
1093 $useOrderProduct = false;
1094
1095 $data['USE_ORDER_PRODUCT'] = $useOrderProduct;
1096
1097 unset($needCoupons, $needPrice);
1098
1099
1100 if ($providerClassName)
1101 {
1102 if (array_key_exists("IBXSaleProductProvider", class_implements($providerClassName)))
1103 {
1104 $resultProductList = static::getProductProviderData($products, $providerClassName, $data, $select);
1105 if (in_array('RETURN_BASKET_ID', $options))
1106 {
1107 $basketList = array();
1108 foreach ($products as $productId => $productData)
1109 {
1110 $basketItem = $productData['BASKET_ITEM'];
1111 $basketList[] = $basketItem;
1112 }
1113
1114 $resultProductList = static::createItemsAfterGetProductData($basketList, $resultProductList, $select);
1115 }
1116 }
1117 elseif (class_exists($providerClassName))
1118 {
1119 $basketList = array();
1120 foreach ($products as $productId => $productData)
1121 {
1122 $basketList[] = $productData['BASKET_ITEM'];
1123 }
1124
1125 $r = Internals\Catalog\Provider::getProductData($basketList, $context);
1126 if ($r->isSuccess())
1127 {
1128 $resultProductData = $r->getData();
1129 if (!empty($resultProductData['PRODUCT_DATA_LIST']))
1130 {
1131 $itemsList = $resultProductData['PRODUCT_DATA_LIST'];
1132 $resultItemsList = array();
1133 $resultProductList = array();
1134
1135 foreach ($itemsList as $providerName => $products)
1136 {
1137 $resultItemsList = static::createItemsAfterGetProductData($basketList, $products, $select);
1138 }
1139
1140 $resultProductList = $resultProductList + $resultItemsList;
1141
1142 }
1143 }
1144 }
1145
1146 if (!empty($resultProductList))
1147 {
1148 if (!empty($resultList) && is_array($resultList))
1149 {
1150 $resultList = $resultList + $resultProductList;
1151 }
1152 else
1153 {
1154 $resultList = $resultProductList;
1155 }
1156 }
1157 }
1158 else
1159 {
1160 $priceFields = static::getPriceFields();
1161
1162 foreach ($products as $productId => $productData)
1163 {
1164 $callbackFunction = null;
1165 if (!empty($productData['CALLBACK_FUNC']))
1166 {
1167 $callbackFunction = $productData['CALLBACK_FUNC'];
1168 }
1169
1170 $quantityList = array();
1171
1172 if (array_key_exists('QUANTITY', $productData))
1173 {
1174 $quantityList = array($productData['BASKET_CODE'] => $productData['QUANTITY']);
1175
1176 }
1177 elseif (!empty($productData['QUANTITY_LIST']))
1178 {
1179 $quantityList = $productData['QUANTITY_LIST'];
1180 }
1181
1182 foreach($quantityList as $basketCode => $quantity)
1183 {
1184 if (!empty($callbackFunction))
1185 {
1186 $resultProductData = \CSaleBasket::executeCallbackFunction(
1187 $callbackFunction,
1188 $productData['MODULE'],
1189 $productId,
1190 $quantity
1191 );
1192 }
1193 else
1194 {
1195 $resultProductData = array(
1196 'QUANTITY' => $quantity,
1197 'AVAILABLE_QUANTITY' => $quantity,
1198 );
1199 }
1200
1201 $itemCode = $productId;
1202 if (in_array('RETURN_BASKET_ID', $options))
1203 {
1204 $itemCode = $basketCode;
1205 }
1206
1207 if (empty($resultList[$itemCode]))
1208 {
1209 $resultList[$itemCode] = $resultProductData;
1210 }
1211
1212 if (!empty($resultProductData))
1213 {
1214 $resultList[$itemCode]['PRICE_LIST'][$basketCode] = array(
1215 'QUANTITY' => $resultProductData['QUANTITY'],
1216 'AVAILABLE_QUANTITY' => $resultProductData['AVAILABLE_QUANTITY'],
1217 "ITEM_CODE" => $productId,
1218 "BASKET_CODE" => $basketCode,
1219 );
1220
1221 foreach ($priceFields as $fieldName)
1222 {
1223 if (isset($resultProductData[$fieldName]))
1224 {
1225 $resultList[$itemCode]['PRICE_LIST'][$basketCode][$fieldName] = $resultProductData[$fieldName];
1226 }
1227 }
1228 }
1229 }
1230
1231 }
1232 }
1233
1234
1235 if (!empty($resultList))
1236 {
1237 $result->setData(
1238 array(
1239 'PRODUCT_DATA_LIST' => $resultList
1240 )
1241 );
1242 }
1243
1244 return $result;
1245 }
1246
1255 private static function createItemsAfterGetProductData($basketList, array $productDataList, array $select = array())
1256 {
1257 $resultList = array();
1258 $basketIndexList = array();
1259 $basketMap = array();
1260
1261 if (!is_array($basketList) && !($basketList instanceof BasketBase))
1262 {
1263 throw new ArgumentTypeException('basketList');
1264 }
1265
1267 foreach ($basketList as $basketItem)
1268 {
1269 $basketCode = $basketItem->getBasketCode();
1270 $productId = $basketItem->getProductId();
1271
1272 $basketIndexList[$productId][] = $basketCode;
1273 $basketMap[$basketCode] = $basketItem;
1274 }
1275
1276 if (empty($productDataList))
1277 {
1278 return $resultList;
1279 }
1280
1281 foreach ($productDataList as $productId => $productData)
1282 {
1283 if (empty($basketIndexList[$productId]))
1284 continue;
1285
1286 if (empty($productData))
1287 continue;
1288
1289 foreach ($basketIndexList[$productId] as $basketCode)
1290 {
1291 if (!empty($productData['PRICE_LIST']) && !empty($productData['PRICE_LIST'][$basketCode]))
1292 {
1293 $priceData = $productData['PRICE_LIST'][$basketCode];
1294
1295 if (array_key_exists('AVAILABLE_QUANTITY', $priceData)
1296 && !array_key_exists('QUANTITY', $priceData))
1297 {
1298 $priceData['QUANTITY'] = $priceData['AVAILABLE_QUANTITY'];
1299 }
1300
1302 $basketItem = $basketMap[$basketCode];
1303
1304 if (in_array('PRICE', $select) || $basketItem->getId() == 0)
1305 {
1306 $productData = $priceData + $productData;
1307 }
1308 else
1309 {
1310 if (isset($priceData['QUANTITY']))
1311 {
1312 $productData['QUANTITY'] = $priceData['QUANTITY'];
1313 }
1314
1315 if (isset($priceData['AVAILABLE_QUANTITY']))
1316 {
1317 $productData['AVAILABLE_QUANTITY'] = $priceData['AVAILABLE_QUANTITY'];
1318 }
1319
1320 unset($productData['PRICE_LIST']);
1321 }
1322 }
1323
1324 if (in_array('AVAILABLE_QUANTITY', $select) && isset($productData['AVAILABLE_QUANTITY']))
1325 {
1326 $productData['QUANTITY'] = $productData['AVAILABLE_QUANTITY'];
1327 }
1328
1329 $resultList[$basketCode] = $productData;
1330 }
1331 }
1332
1333 return $resultList;
1334 }
1335
1345 public static function getProductProviderData(array $products, $provider, array $data, array $select = array())
1346 {
1347 $result = array();
1348
1349 foreach ($products as $productData)
1350 {
1351 $productSelect = array_fill_keys($select, true);
1352 $productId = $productData['PRODUCT_ID'];
1353
1354 $currentUseOrderProduct = $data['USE_ORDER_PRODUCT'];
1355 if (isset($productData['IS_NEW']) && $productData['IS_NEW'])
1356 {
1357 $currentUseOrderProduct = false;
1358 }
1359
1360 $fields = $data;
1361
1362 if (isset($productData['IS_ORDERABLE']) && $productData['IS_ORDERABLE'])
1363 {
1364 $fields['CHECK_COUPONS'] = 'Y';
1365 }
1366 else
1367 {
1368 $fields['CHECK_COUPONS'] = 'N';
1369 }
1370
1371 if (isset($productData['IS_BUNDLE_CHILD']) && $productData['IS_BUNDLE_CHILD'])
1372 {
1373 $fields['CHECK_DISCOUNT'] = 'N';
1374 $fields['CHECK_COUPONS'] = 'N';
1375 }
1376
1377 $fields['PRODUCT_ID'] = $productId;
1378
1379 if (isset($productData['SUBSCRIBE']) && $productData['SUBSCRIBE'] === true)
1380 {
1381 unset($productSelect['QUANTITY'], $productSelect['AVAILABLE_QUANTITY']);
1382
1383 $fields['CHECK_QUANTITY'] = 'N';
1384 $fields['AVAILABLE_QUANTITY'] = 'N';
1385 }
1386
1387 $quantityList = array();
1388
1389 if (!empty($productData['QUANTITY_LIST']))
1390 {
1391 $quantityList = $productData['QUANTITY_LIST'];
1392 }
1393 else
1394 {
1395 $quantityList[$productData['BASKET_CODE']] = $productData['QUANTITY'];
1396 }
1397
1398 $basketId = null;
1399
1400 if (!empty($productData['BASKET_ID']))
1401 {
1402 $basketId = $productData['BASKET_ID'];
1403 }
1404
1405
1406 if (intval($basketId) == 0)
1407 {
1409 $basketItem = $productData['BASKET_ITEM'];
1410 if ($basketItem)
1411 {
1412 $basketId = $basketItem->getId();
1413 }
1414 }
1415//
1416 if (intval($basketId) > 0)
1417 {
1418 $fields['BASKET_ID'] = $basketId;
1419 }
1420
1421 $hasTrustData = false;
1422
1423 $trustData = static::getTrustData($data['SITE_ID'], $productData['MODULE'], $productData['PRODUCT_ID']);
1424 $resultProductData = array();
1425
1426 if (static::isReadTrustData() === true
1427 && !empty($trustData) && is_array($trustData))
1428 {
1429 $hasTrustData = true;
1430 $resultProductData = $trustData;
1431
1432 foreach (static::getProductDataRequiredFields() as $requiredField)
1433 {
1434 if (!array_key_exists($requiredField, $resultProductData))
1435 {
1436 $hasTrustData = false;
1437 break;
1438 }
1439 }
1440
1441
1442 if ($hasTrustData && isset($productSelect['PRICE']))
1443 {
1444 foreach (static::getProductDataRequiredPriceFields() as $requiredField)
1445 {
1446 if (!array_key_exists($requiredField, $resultProductData))
1447 {
1448 $hasTrustData = false;
1449 break;
1450 }
1451 }
1452 }
1453 }
1454
1455 $itemCode = $productData['PRODUCT_ID'];
1456
1457 $resultProviderDataList = array();
1458
1459 if(!$hasTrustData)
1460 {
1461 foreach($quantityList as $basketCode => $quantity)
1462 {
1463 if (!empty($resultProviderDataList[$quantity]))
1464 {
1465 $resultProviderDataList[$quantity]['BASKET_CODE'][] = $basketCode;
1466 continue;
1467 }
1468
1469 $requestFields = $fields;
1470 $requestFields['QUANTITY'] = $quantity;
1471
1472 $resultProviderDataList[$quantity] = array(
1473 'BASKET_CODE' => array($basketCode),
1474 'DATA' => ($currentUseOrderProduct ? $provider::OrderProduct(
1475 $requestFields
1476 ) : $provider::GetProductData($requestFields))
1477 );
1478
1479 }
1480
1481 }
1482 else
1483 {
1484
1485 if (!isset($productSelect['AVAILABLE_QUANTITY']) && array_key_exists("AVAILABLE_QUANTITY", $resultProductData))
1486 {
1487 unset($resultProductData['AVAILABLE_QUANTITY']);
1488 }
1489
1490 $productQuantity = floatval($resultProductData['QUANTITY']);
1491
1492 $resultProviderDataList[$productQuantity] = array(
1493 'BASKET_CODE' => array($productData['BASKET_CODE']),
1494 'DATA' => $resultProductData
1495 );
1496
1497 }
1498
1499 $priceFields = static::getPriceFields();
1500
1501 foreach ($resultProviderDataList as $quantity => $providerData)
1502 {
1503 if (empty($result[$itemCode]))
1504 {
1505 $result[$itemCode] = $providerData['DATA'];
1506 }
1507
1508 $basketCodeList = $providerData['BASKET_CODE'];
1509
1510 foreach ($basketCodeList as $basketCode)
1511 {
1512 $result[$itemCode]['PRICE_LIST'][$basketCode] = array(
1513 "ITEM_CODE" => $itemCode,
1514 "BASKET_CODE" => $basketCode,
1515 );
1516
1517 if (isset($providerData['DATA']['QUANTITY']) && $providerData['DATA']['QUANTITY'] > 0)
1518 {
1519 $result[$itemCode]['PRICE_LIST'][$basketCode]['QUANTITY'] = $providerData['DATA']['QUANTITY'];
1520 }
1521
1522 if (isset($providerData['DATA']['AVAILABLE_QUANTITY']))
1523 {
1524 $result[$itemCode]['PRICE_LIST'][$basketCode]['AVAILABLE_QUANTITY'] = $providerData['DATA']['AVAILABLE_QUANTITY'];
1525 }
1526 }
1527
1528 foreach ($priceFields as $fieldName)
1529 {
1530 if (isset($providerData['DATA'][$fieldName]))
1531 {
1532 foreach ($basketCodeList as $basketCode)
1533 {
1534 $result[$itemCode]['PRICE_LIST'][$basketCode][$fieldName] = $providerData['DATA'][$fieldName];
1535 }
1536 }
1537 }
1538 }
1539
1540// $result[$itemCode]['ITEM_CODE'] = $productData['ITEM_CODE'];
1541
1542 if (isset($productData['IS_BUNDLE_PARENT']) && $productData['IS_BUNDLE_PARENT'])
1543 {
1544 $result[$itemCode]["BUNDLE_ITEMS"] = array();
1546 $bundleChildDataList = static::getBundleChildItemsByProductData($provider, $productData);
1547 if (!empty($bundleChildDataList) && is_array($bundleChildDataList))
1548 {
1549 $quantity = $productData['QUANTITY'] ?? $productData['QUANTITY_LIST'][$basketCode] ?? 0;
1550
1551 foreach ($bundleChildDataList["ITEMS"] as &$itemData)
1552 {
1553 $itemData['QUANTITY'] = $itemData['QUANTITY'] * $quantity;
1554 }
1555 unset($itemData);
1556 $result[$itemCode]["BUNDLE_ITEMS"] = $bundleChildDataList["ITEMS"];
1557 }
1558 }
1559 }
1560
1561 return $result;
1562 }
1563
1571 public static function getCatalogData(array $basketProviderList, array $context, array $select = array())
1572 {
1573 $needPrice = in_array('PRICE', $select);
1574 $needBasePrice = in_array('BASE_PRICE', $select);
1575 $needCoupons = in_array('COUPONS', $select);
1576
1577 $result = array();
1578// $orderId = null;
1579 $userId = null;
1580 $siteId = null;
1581 $currency = null;
1582
1583 if (!empty($context['USER_ID']) && intval($context['USER_ID']) > 0)
1584 {
1585 $userId = $context['USER_ID'];
1586 }
1587
1588 if (array_key_exists('SITE_ID', $context))
1589 {
1590 $siteId = $context['SITE_ID'];
1591 }
1592
1593 if (array_key_exists('CURRENCY', $context))
1594 {
1595 $currency = $context['CURRENCY'];
1596 }
1597
1598 $data = array(
1599 'USER_ID' => $userId,
1600 'SITE_ID' => $siteId,
1601 'CURRENCY' => $currency,
1602 'CHECK_QUANTITY' => (in_array('QUANTITY', $select) ? 'Y' : 'N'),
1603 'AVAILABLE_QUANTITY' => (in_array('AVAILABLE_QUANTITY', $select) ? 'Y' : 'N'),
1604 'CHECK_PRICE' => ($needPrice ? 'Y' : 'N'),
1605 'CHECK_COUPONS' => ($needCoupons ? 'Y' : 'N'),
1606 'RENEWAL' => (in_array('RENEWAL', $select) ? 'Y' : 'N')
1607 );
1608
1609 if ($needBasePrice)
1610 $data['CHECK_DISCOUNT'] = 'N';
1611
1612 $useOrderProduct = false;
1613 if ($needPrice)
1614 $useOrderProduct = true;
1615
1616 if ($needCoupons)
1617 $useOrderProduct = false;
1618
1619 unset($needCoupons, $needPrice);
1620
1621 foreach ($basketProviderList as $provider => $providerBasketItemList)
1622 {
1623 if ($provider && array_key_exists("IBXSaleProductProvider", class_implements($provider)))
1624 {
1625 foreach ($providerBasketItemList as $providerBasketItem)
1626 {
1627 $currentUseOrderProduct = $useOrderProduct;
1628 if (!isset($providerBasketItem['BASKET_ID']) || (int)$providerBasketItem['BASKET_ID'] <= 0)
1629 $currentUseOrderProduct = false;
1630
1631 $providerFields = $data;
1632
1633 if ($providerBasketItem['BASKET_ITEM']->isBundleChild())
1634 {
1635 $providerFields['CHECK_DISCOUNT'] = 'N';
1636 }
1637
1638 if ($providerBasketItem['BASKET_ITEM']->getField("CAN_BUY") == "N"
1639 || $providerBasketItem['BASKET_ITEM']->getField("DELAY") == "Y"
1640 || $providerBasketItem['BASKET_ITEM']->getField("SUBSCRIBE") == "Y"
1641 )
1642 {
1643 $providerFields['CHECK_COUPONS'] = 'N';
1644 }
1645 else
1646 {
1647 $providerFields['CHECK_COUPONS'] = 'Y';
1648 }
1649
1650 $providerFields['PRODUCT_ID'] = $providerBasketItem['PRODUCT_ID'];
1651 $providerFields['QUANTITY'] = $providerBasketItem['QUANTITY'];
1652
1653 if (intval($providerBasketItem['BASKET_ID']) > 0)
1654 {
1655 $providerFields['BASKET_ID'] = $providerBasketItem['BASKET_ID'];
1656 }
1657
1658 $hasTrustData = false;
1659
1660 $trustData = static::getTrustData($siteId, $providerBasketItem['MODULE'], $providerBasketItem['PRODUCT_ID']);
1661
1662 if (static::isReadTrustData() === true
1663 && !empty($trustData) && is_array($trustData))
1664 {
1665 $hasTrustData = true;
1666 $resultProductData = $trustData;
1667
1668 foreach (static::getProductDataRequiredFields() as $requiredField)
1669 {
1670 if (!array_key_exists($requiredField, $resultProductData))
1671 {
1672 $hasTrustData = false;
1673 break;
1674 }
1675 }
1676
1677
1678 if ($hasTrustData && in_array('PRICE', $select))
1679 {
1680 foreach (static::getProductDataRequiredPriceFields() as $requiredField)
1681 {
1682 if (!array_key_exists($requiredField, $resultProductData))
1683 {
1684 $hasTrustData = false;
1685 break;
1686 }
1687 }
1688 }
1689 }
1690
1691
1692 if(!$hasTrustData)
1693 {
1694 $resultProductData = ($currentUseOrderProduct ? $provider::OrderProduct($providerFields) : $provider::GetProductData($providerFields));
1695 }
1696 else
1697 {
1698 if (!in_array('AVAILABLE_QUANTITY', $select) && array_key_exists("AVAILABLE_QUANTITY", $resultProductData))
1699 {
1700 unset($resultProductData['AVAILABLE_QUANTITY']);
1701 }
1702 }
1703
1704 $basketCode = $providerBasketItem['BASKET_ITEM']->getBasketCode();
1705 $result[$basketCode] = $resultProductData;
1706
1707 if ($providerBasketItem['BASKET_ITEM']->isBundleParent())
1708 {
1709
1710 $result[$basketCode]["BUNDLE_ITEMS"] = array();
1712 $bundleChildDataList = static::getSetItems($providerBasketItem['BASKET_ITEM']);
1713 if (!empty($bundleChildDataList) && is_array($bundleChildDataList))
1714 {
1715 $bundleChildList = reset($bundleChildDataList);
1716
1717 foreach ($bundleChildList["ITEMS"] as &$itemData)
1718 {
1719 $itemData['QUANTITY'] = $itemData['QUANTITY'] * $providerBasketItem['BASKET_ITEM']->getQuantity();
1720 }
1721 unset($itemData);
1722 $result[$basketCode]["BUNDLE_ITEMS"] = $bundleChildList["ITEMS"];
1723 }
1724
1725 }
1726 }
1727 }
1728 else
1729 {
1730 foreach ($providerBasketItemList as $providerBasketItem)
1731 {
1732 $resultProductData = \CSaleBasket::executeCallbackFunction(
1733 $providerBasketItem['CALLBACK_FUNC'],
1734 $providerBasketItem['MODULE'],
1735 $providerBasketItem['PRODUCT_ID'],
1736 $providerBasketItem['QUANTITY']
1737 );
1738
1739 $basketCode = $providerBasketItem['BASKET_ITEM']->getBasketCode();
1740 $result[$basketCode] = $resultProductData;
1741 }
1742 }
1743 }
1744
1745 return $result;
1746 }
1747
1756 public static function tryShipment(Shipment $shipment)
1757 {
1758 $result = new Result();
1759 $needShip = $shipment->needShip();
1760 if ($needShip === null)
1761 return $result;
1762
1763 $resultList = array();
1764 $storeData = array();
1765
1767 $shipmentItemCollection = $shipment->getShipmentItemCollection();
1768 if (!$shipmentItemCollection)
1769 {
1770 throw new ObjectNotFoundException('Entity "ShipmentItemCollection" not found');
1771 }
1772
1774 $shipment = $shipmentItemCollection->getShipment();
1775 if (!$shipment)
1776 {
1777 throw new ObjectNotFoundException('Entity "ShipmentCollection" not found');
1778 }
1779
1781 $shipmentCollection = $shipment->getCollection();
1782 if (!$shipmentCollection)
1783 {
1784 throw new ObjectNotFoundException('Entity "ShipmentCollection" not found');
1785 }
1786
1787 $r = static::tryShipmentItemList($shipmentItemCollection);
1788
1789 $basketList = static::getBasketFromShipmentItemCollection($shipmentItemCollection);
1790
1791 $bundleIndexList = static::getBundleIndexFromShipmentItemCollection($shipmentItemCollection);
1792
1793 $basketCountList = static::getBasketCountFromShipmentItemCollection($shipmentItemCollection);
1794
1795 $basketProviderMap = static::createProviderBasketMap($basketList, array('RESERVED', 'SITE_ID'));
1796 $basketProviderList = static::redistributeToProviders($basketProviderMap);
1797
1799 {
1801 $r = static::getStoreDataFromShipmentItemCollection($shipmentItemCollection);
1802 if ($r->isSuccess())
1803 {
1804 $resultStoreData = $r->getData();
1805 if (!empty($resultStoreData['STORE_DATA_LIST']))
1806 {
1807 $storeDataList = $resultStoreData['STORE_DATA_LIST'];
1808 }
1809 }
1810 else
1811 {
1812 $result->addErrors($r->getErrors());
1813 }
1814
1815 }
1816
1817 if (!empty($basketProviderList))
1818 {
1819 foreach ($basketProviderList as $provider => $providerBasketItemList)
1820 {
1821 if ($provider && array_key_exists("IBXSaleProductProvider", class_implements($provider)))
1822 {
1823 foreach ($providerBasketItemList as $providerBasketItem)
1824 {
1825 if ($providerBasketItem['BASKET_ITEM']->isBundleParent())
1826 {
1827 continue;
1828 }
1829
1830 $resultProduct = new Result();
1831
1832
1833 $quantity = 0;
1834 $basketStoreData = array();
1835
1836 $basketCode = $providerBasketItem['BASKET_CODE'];
1837
1839 if (!$basketItem = $providerBasketItem['BASKET_ITEM'])
1840 {
1841 throw new ObjectNotFoundException('Entity "BasketItem" not found');
1842 }
1843
1845 {
1846 $quantity = $basketCountList[$basketCode];
1847
1848 if (!empty($storeDataList) && is_array($storeDataList)
1849 && isset($storeDataList[$basketCode]))
1850 {
1851 $basketStoreData = $storeDataList[$basketCode];
1852 }
1853
1854 if (!empty($basketStoreData))
1855 {
1856 $allBarcodeQuantity = 0;
1857 foreach($basketStoreData as $basketShipmentItemStore)
1858 {
1859 $allBarcodeQuantity += $basketShipmentItemStore['QUANTITY'];
1860 }
1861
1862 if ($quantity > $allBarcodeQuantity)
1863 {
1864 $resultProduct->addError(new ResultError(Loc::getMessage('SALE_PROVIDER_SHIPMENT_SHIPPED_LESS_QUANTITY', array(
1865 '#PRODUCT_NAME#' => $basketItem->getField('NAME')
1866 )), 'SALE_PROVIDER_SHIPMENT_SHIPPED_LESS_QUANTITY'));
1867 }
1868 elseif ($quantity < $allBarcodeQuantity)
1869 {
1870 $resultProduct->addError(new ResultError(Loc::getMessage('SALE_PROVIDER_SHIPMENT_SHIPPED_MORE_QUANTITY', array(
1871 '#PRODUCT_NAME#' => $basketItem->getField('NAME')
1872 )), 'SALE_PROVIDER_SHIPMENT_SHIPPED_MORE_QUANTITY'));
1873 }
1874 }
1875
1876 }
1877
1878 if ($resultProduct->isSuccess())
1879 {
1880
1881 if ($needShip === true)
1882 {
1883 if (method_exists($provider, 'tryShipmentProduct'))
1884 {
1886 $resultProduct = $provider::tryShipmentProduct($basketItem, $providerBasketItem['RESERVED'], $basketStoreData, $quantity);
1887 }
1888 }
1889 else
1890 {
1891 if (method_exists($provider, 'tryUnshipmentProduct'))
1892 {
1894 $resultProduct = $provider::tryUnshipmentProduct($providerBasketItem['PRODUCT_ID']);
1895 }
1896 }
1897 }
1898
1899 $resultList[$basketCode] = $resultProduct;
1900
1901 }
1902 }
1903 elseif (class_exists($provider))
1904 {
1905
1907 if (!$shipmentCollection = $shipment->getCollection())
1908 {
1909 throw new ObjectNotFoundException('Entity "ShipmentCollection" not found');
1910 }
1911
1913 if (!$order = $shipmentCollection->getOrder())
1914 {
1915 throw new ObjectNotFoundException('Entity "Order" not found');
1916 }
1917
1918 $pool = Internals\PoolQuantity::getInstance($order->getInternalId());
1919
1920 $context = array(
1921 'SITE_ID' => $order->getSiteId(),
1922 'CURRENCY' => $order->getCurrency(),
1923 );
1924
1925 if ($order->getUserId() > 0)
1926 {
1927 $context['USER_ID'] = $order->getUserId();
1928 }
1929 else
1930 {
1931 global $USER;
1932 $context['USER_ID'] = $USER->getId();
1933 }
1934
1935 $creator = Internals\ProviderCreator::create($context);
1936
1937 $tryShipProductList = array();
1939 foreach ($shipmentItemCollection as $shipmentItem)
1940 {
1941 $basketItem = $shipmentItem->getBasketItem();
1942 $providerClass = $basketItem->getProviderEntity();
1943
1944 if ($providerClass instanceof SaleProviderBase)
1945 {
1946 $shipmentProductData = $creator->createItemForShip($shipmentItem);
1947 $creator->addProductData($shipmentProductData);
1948 }
1949 }
1950
1951 $r = $creator->tryShip();
1952 if ($r->isSuccess())
1953 {
1954 if ($r->hasWarnings())
1955 {
1956 $result->addWarnings($r->getWarnings());
1957 }
1958 else
1959 {
1960 $data = $r->getData();
1961 if (array_key_exists('TRY_SHIP_PRODUCTS_LIST', $data))
1962 {
1963 $tryShipProductList = $data['TRY_SHIP_PRODUCTS_LIST'] + $tryShipProductList;
1964
1965 $creator->setItemsResultAfterTryShip($pool, $tryShipProductList);
1966
1967 }
1968 }
1969 }
1970 else
1971 {
1972 $result->addWarnings($r->getErrors());
1973 }
1974 }
1975 }
1976 }
1977
1978 if (!empty($resultList)
1979 && !empty($bundleIndexList) && is_array($bundleIndexList))
1980 {
1981
1982 foreach ($bundleIndexList as $bundleParentBasketCode => $bundleChildList)
1983 {
1984// $tryShipmentBundle = false;
1985 foreach($bundleChildList as $bundleChildBasketCode)
1986 {
1987 if (!isset($resultList[$bundleChildBasketCode]))
1988 {
1989 if (!isset($resultList[$bundleParentBasketCode]))
1990 {
1991 $resultList[$bundleParentBasketCode] = new Result();
1992 }
1993
1994 $resultList[$bundleParentBasketCode]->addError(new ResultError('Bundle child item not found', 'SALE_PROVIDER_SHIPMENT_SHIPPED_BUNDLE_CHILD_ITEM_NOT_FOUND'));
1995 }
1996
1997 }
1998 }
1999
2000 }
2001
2002 if (!empty($resultList))
2003 {
2005 if (!$shipmentCollection = $shipment->getCollection())
2006 {
2007 throw new ObjectNotFoundException('Entity "ShipmentCollection" not found');
2008 }
2009
2011 if (!$order = $shipmentCollection->getOrder())
2012 {
2013 throw new ObjectNotFoundException('Entity "Order" not found');
2014 }
2015
2016 $hasErrors = false;
2017
2019 foreach ($shipmentItemCollection as $shipmentItem)
2020 {
2022 if(!$basketItem = $shipmentItem->getBasketItem())
2023 {
2024 throw new ObjectNotFoundException('Entity "BasketItem" not found');
2025 }
2026
2027 if (isset($resultList[$basketItem->getBasketCode()]) && !$resultList[$basketItem->getBasketCode()]->isSuccess())
2028 {
2029 $hasErrors = true;
2030 break;
2031 }
2032 }
2033
2034 if (!$hasErrors)
2035 {
2037 foreach ($shipmentItemCollection as $shipmentItem)
2038 {
2040 if(!$basketItem = $shipmentItem->getBasketItem())
2041 {
2042 throw new ObjectNotFoundException('Entity "BasketItem" not found');
2043 }
2044
2045 if (isset($resultList[$basketItem->getBasketCode()]) && $resultList[$basketItem->getBasketCode()]->isSuccess())
2046 {
2047 static::addQuantityPoolItem($order->getInternalId(), $basketItem, ($needShip? -1 : 1) * $shipmentItem->getQuantity());
2048
2049 if ($needShip)
2050 $shipmentItem->setFieldNoDemand("RESERVED_QUANTITY", 0);
2051
2052 }
2053 }
2054 }
2055
2056 $result->setData($resultList);
2057 }
2058
2059 return $result;
2060 }
2061
2068 public static function tryShipmentItemList($shipmentItemList)
2069 {
2070 $result = new Result();
2071
2072 $resultList = array();
2073 $bundleIndexList = static::getBundleIndexFromShipmentItemCollection($shipmentItemList);
2074
2076 {
2078 $r = static::getStoreDataFromShipmentItemCollection($shipmentItemList);
2079 if ($r->isSuccess())
2080 {
2081 $resultStoreData = $r->getData();
2082 if (!empty($resultStoreData['STORE_DATA_LIST']))
2083 {
2084 $storeDataList = $resultStoreData['STORE_DATA_LIST'];
2085 }
2086 }
2087 else
2088 {
2089 $result->addErrors($r->getErrors());
2090 }
2091
2092 }
2093
2094 $shipmentItemParentsList = array();
2095
2096 $tryShipProductList = array();
2097
2099 foreach ($shipmentItemList as $shipmentItem)
2100 {
2101 $itemIndex = $shipmentItem->getInternalIndex();
2102 $basketItem = $shipmentItem->getBasketItem();
2103 $providerName = $basketItem->getProviderName();
2104
2106 $shipmentItemCollection = $shipmentItem->getCollection();
2107 if (!$shipmentItemCollection)
2108 {
2109 throw new ObjectNotFoundException('Entity "ShipmentItemCollection" not found');
2110 }
2111
2113 $shipment = $shipmentItemCollection->getShipment();
2114 if (!$shipment)
2115 {
2116 throw new ObjectNotFoundException('Entity "Shipment" not found');
2117 }
2118
2119 $shipmentItemParentsList[$itemIndex] = array(
2120 'BASKET_ITEM' => $basketItem,
2121 'SHIPMENT' => $shipment,
2122 'SHIPMENT_ITEM_COLLECTION' => $shipmentItemCollection,
2123 );
2124
2125 $needShip = $shipment->needShip();
2126 if ($needShip === null)
2127 continue;
2128
2129
2130 if ($providerName && array_key_exists("IBXSaleProductProvider", class_implements($providerName)))
2131 {
2132 $basketItem = $shipmentItem->getBasketItem();
2133 if (!$basketItem)
2134 {
2135 throw new ObjectNotFoundException('Entity "BasketItem" not found');
2136 }
2137
2138 if ($basketItem->isBundleParent())
2139 {
2140 continue;
2141 }
2142
2143 $basketCode = $basketItem->getBasketCode();
2144 $quantity = $shipmentItem->getQuantity();
2145 $basketStoreData = array();
2146
2147 $resultProduct = new Result();
2148
2150 {
2151 if (!empty($storeDataList) && is_array($storeDataList)
2152 && isset($storeDataList[$basketCode]))
2153 {
2154 $basketStoreData = $storeDataList[$basketCode];
2155 }
2156
2157 if (!empty($basketStoreData))
2158 {
2159 $allBarcodeQuantity = 0;
2160 foreach($basketStoreData as $basketShipmentItemStore)
2161 {
2162 $allBarcodeQuantity += $basketShipmentItemStore['QUANTITY'];
2163 }
2164
2165 if ($quantity > $allBarcodeQuantity)
2166 {
2167 $resultProduct->addError(new ResultError(Loc::getMessage('SALE_PROVIDER_SHIPMENT_SHIPPED_LESS_QUANTITY', array(
2168 '#PRODUCT_NAME#' => $basketItem->getField('NAME')
2169 )), 'SALE_PROVIDER_SHIPMENT_SHIPPED_LESS_QUANTITY'));
2170 }
2171 elseif ($quantity < $allBarcodeQuantity)
2172 {
2173 $resultProduct->addError(new ResultError(Loc::getMessage('SALE_PROVIDER_SHIPMENT_SHIPPED_MORE_QUANTITY', array(
2174 '#PRODUCT_NAME#' => $basketItem->getField('NAME')
2175 )), 'SALE_PROVIDER_SHIPMENT_SHIPPED_MORE_QUANTITY'));
2176 }
2177 }
2178
2179 }
2180
2181 if ($resultProduct->isSuccess())
2182 {
2183
2184 if ($needShip === true)
2185 {
2186 if (method_exists($providerName, 'tryShipmentProduct'))
2187 {
2189 $resultProduct = $providerName::tryShipmentProduct($basketItem, $basketItem->getField('RESERVED'), $basketStoreData, $quantity);
2190 }
2191 }
2192 else
2193 {
2194 if (method_exists($providerName, 'tryUnshipmentProduct'))
2195 {
2197 $resultProduct = $providerName::tryUnshipmentProduct($basketItem->getProductId());
2198 }
2199 }
2200 }
2201
2202 $resultList[$basketCode] = $resultProduct;
2203
2204 }
2205 elseif ($providerName && class_exists($providerName))
2206 {
2208 $shipmentCollection = $shipment->getCollection();
2209 if (!$shipmentCollection)
2210 {
2211 throw new ObjectNotFoundException('Entity "ShipmentCollection" not found');
2212 }
2213
2215 $order = $shipmentCollection->getOrder();
2216 if (!$order)
2217 {
2218 throw new ObjectNotFoundException('Entity "Order" not found');
2219 }
2220
2221 $shipmentItemParentsList[$itemIndex]['SHIPMENT_COLLECTION'] = $shipmentCollection;
2222 $shipmentItemParentsList[$itemIndex]['ORDER'] = $order;
2223
2224 $pool = Internals\PoolQuantity::getInstance($order->getInternalId());
2225
2226 $context = array(
2227 'SITE_ID' => $order->getSiteId(),
2228 'CURRENCY' => $order->getCurrency(),
2229 );
2230
2231 if ($order->getUserId() > 0)
2232 {
2233 $context['USER_ID'] = $order->getUserId();
2234 }
2235 else
2236 {
2237 global $USER;
2238 $context['USER_ID'] = $USER->getId();
2239 }
2240
2241 $creator = Internals\ProviderCreator::create($context);
2242
2243 $shipmentProductData = $creator->createItemForShip($shipmentItem);
2244 $creator->addProductData($shipmentProductData);
2245
2246 $r = $creator->tryShip();
2247 if ($r->isSuccess())
2248 {
2249 if ($r->hasWarnings())
2250 {
2251 $result->addWarnings($r->getWarnings());
2252 }
2253 else
2254 {
2255 $data = $r->getData();
2256 if (array_key_exists('TRY_SHIP_PRODUCTS_LIST', $data))
2257 {
2258 $tryShipProductList = $data['TRY_SHIP_PRODUCTS_LIST'] + $tryShipProductList;
2259 $creator->setItemsResultAfterTryShip($pool, $tryShipProductList);
2260 }
2261 }
2262 }
2263 else
2264 {
2265 $result->addWarnings($r->getErrors());
2266 }
2267 }
2268 }
2269
2270 if (!empty($resultList)
2271 && !empty($bundleIndexList) && is_array($bundleIndexList))
2272 {
2273
2274 foreach ($bundleIndexList as $bundleParentBasketCode => $bundleChildList)
2275 {
2276 foreach($bundleChildList as $bundleChildBasketCode)
2277 {
2278 if (!isset($resultList[$bundleChildBasketCode]))
2279 {
2280 if (!isset($resultList[$bundleParentBasketCode]))
2281 {
2282 $resultList[$bundleParentBasketCode] = new Result();
2283 }
2284
2285 $resultList[$bundleParentBasketCode]->addError(new ResultError('Bundle child item not found', 'SALE_PROVIDER_SHIPMENT_SHIPPED_BUNDLE_CHILD_ITEM_NOT_FOUND'));
2286 }
2287
2288 }
2289 }
2290
2291 }
2292
2293 if (!empty($resultList))
2294 {
2295
2296 $hasErrors = false;
2297
2299 foreach ($shipmentItemList as $shipmentItem)
2300 {
2301 $itemIndex = $shipmentItem->getInternalIndex();
2302
2304 $basketItem = $shipmentItemParentsList[$itemIndex]['BASKET_ITEM'];
2305
2306 if (isset($resultList[$basketItem->getBasketCode()]) && !$resultList[$basketItem->getBasketCode()]->isSuccess())
2307 {
2308 $hasErrors = true;
2309 break;
2310 }
2311 }
2312
2313 if (!$hasErrors)
2314 {
2316 foreach ($shipmentItemList as $shipmentItem)
2317 {
2318 $itemIndex = $shipmentItem->getInternalIndex();
2319
2321 $basketItem = $shipmentItemParentsList[$itemIndex]['BASKET_ITEM'];
2322
2323 $productId = $shipmentItem->getProductId();
2324
2325 if (isset($resultList[$basketItem->getBasketCode()]) && $resultList[$basketItem->getBasketCode()]->isSuccess())
2326 {
2328 $shipment = $shipmentItemParentsList[$itemIndex]['SHIPMENT'];
2329
2331 $order = $shipmentItemParentsList[$itemIndex]['ORDER'];
2332
2333 if (!$order)
2334 {
2336 $shipmentCollection = $shipment->getCollection();
2337 if (!$shipmentCollection)
2338 {
2339 throw new ObjectNotFoundException('Entity "ShipmentCollection" not found');
2340 }
2341
2343 $order = $shipmentCollection->getOrder();
2344 if (!$order)
2345 {
2346 throw new ObjectNotFoundException('Entity "Order" not found');
2347 }
2348
2349 $shipmentItemParentsList[$itemIndex]['SHIPMENT_COLLECTION'] = $shipmentCollection;
2350 $shipmentItemParentsList[$itemIndex]['ORDER'] = $order;
2351 }
2352
2353 $needShip = $shipment->needShip();
2354
2355 static::addQuantityPoolItem($order->getInternalId(), $basketItem, ($needShip? -1 : 1) * $shipmentItem->getQuantity());
2356
2357 if ($needShip)
2358 {
2359 $shipmentItem->setFieldNoDemand("RESERVED_QUANTITY", 0);
2360 }
2361
2362
2363 $foundItem = false;
2364 $poolItems = Internals\ItemsPool::get($order->getInternalId(), $productId);
2365 if (!empty($poolItems))
2366 {
2368 foreach ($poolItems as $poolItem)
2369 {
2370 if ($poolItem->getInternalIndex() == $shipmentItem->getInternalIndex())
2371 {
2372 $foundItem = true;
2373 break;
2374 }
2375 }
2376 }
2377
2378 if (!$foundItem)
2379 {
2380 Internals\ItemsPool::add($order->getInternalId(), $productId, $shipmentItem);
2381 }
2382
2383 }
2384 }
2385 }
2386
2387 $result->setData($resultList);
2388 }
2389
2390 return $result;
2391 }
2392
2393
2399 protected static function getBundleIndexFromShipmentItemCollection($shipmentItemList)
2400 {
2401 $bundleIndexList = array();
2403 foreach ($shipmentItemList as $shipmentItem)
2404 {
2406 if (!$basketItem = $shipmentItem->getBasketItem())
2407 {
2408 continue;
2409 }
2410
2411
2412 if ($basketItem->isBundleChild())
2413 {
2415 $parentBasketItem = $basketItem->getParentBasketItem();
2416 $parentBasketCode = $parentBasketItem->getBasketCode();
2417
2418 if (!array_key_exists($parentBasketCode, $bundleIndexList))
2419 {
2420 $bundleIndexList[$parentBasketCode] = array();
2421 }
2422
2423 $bundleIndexList[$parentBasketCode][] = $basketItem->getBasketCode();
2424 }
2425 }
2426
2427 return $bundleIndexList;
2428 }
2429
2436 protected static function getBasketFromShipmentItemCollection($shipmentItemList)
2437 {
2438
2439 $basketList = array();
2441 foreach ($shipmentItemList as $shipmentItem)
2442 {
2443
2445 if (!$basketItem = $shipmentItem->getBasketItem())
2446 {
2447 continue;
2448 }
2449
2451 $shipmentItemCollection = $shipmentItem->getCollection();
2452 if (!$shipmentItemCollection)
2453 {
2454 throw new ObjectNotFoundException('Entity "ShipmentItemCollection" not found');
2455 }
2456
2458 $shipment = $shipmentItemCollection->getShipment();
2459
2460 if (!$shipment)
2461 {
2462 throw new ObjectNotFoundException('Entity "Shipment" not found');
2463 }
2464
2465 $needShip = $shipment->needShip();
2466 if ($needShip === null)
2467 {
2468 continue;
2469 }
2470
2471 $reserved = ((($shipmentItem->getQuantity() - $shipmentItem->getReservedQuantity()) == 0)
2472 || ($shipment->getField('RESERVED') == "Y"));
2473
2474 if ($basketItem->isBundleParent()
2475 || (!$basketItem->isBundleParent() && !$basketItem->isBundleChild()))
2476 {
2477
2478 $basketList[$basketItem->getBasketCode()] = array(
2479 'BASKET_ITEM' => $basketItem,
2480 'RESERVED' => ($reserved ? "Y" : "N"),
2481 'NEED_SHIP' => $needShip,
2482 'SHIPMENT_ITEM' => $shipmentItem
2483 );
2484 }
2485
2486 if($basketItem->isBundleParent())
2487 {
2489 foreach ($shipmentItemCollection as $bundleShipmentItem)
2490 {
2492 $bundleBasketItem = $bundleShipmentItem->getBasketItem();
2493
2494 if($bundleBasketItem->isBundleChild())
2495 {
2496 $bundleParentBasketItem = $bundleBasketItem->getParentBasketItem();
2497 if ($bundleParentBasketItem->getBasketCode() == $basketItem->getBasketCode())
2498 {
2499
2500 $basketList[$bundleBasketItem->getBasketCode()] = array(
2501 'BASKET_ITEM' => $bundleBasketItem,
2502 'RESERVED' => ($reserved ? "Y" : "N"),
2503 'NEED_SHIP' => $needShip,
2504 'SHIPMENT_ITEM' => $shipmentItem
2505 );
2506 }
2507 }
2508 }
2509 }
2510
2511
2512 }
2513
2514 return $basketList;
2515 }
2516
2523 protected static function getBasketCountFromShipmentItemCollection($shipmentItemList)
2524 {
2525
2526 $basketCountList = array();
2528 foreach ($shipmentItemList as $shipmentItem)
2529 {
2530
2532 if (!$basketItem = $shipmentItem->getBasketItem())
2533 {
2534 continue;
2535 }
2536
2537 if ($basketItem->isBundleParent()
2538 || (!$basketItem->isBundleParent() && !$basketItem->isBundleChild()))
2539 {
2540 $basketCountList[$basketItem->getBasketCode()] = floatval($shipmentItem->getQuantity());
2541 }
2542
2543
2544 if($basketItem->isBundleParent())
2545 {
2547 foreach ($shipmentItemList as $bundleShipmentItem)
2548 {
2550 $bundleBasketItem = $bundleShipmentItem->getBasketItem();
2551
2552 if($bundleBasketItem->isBundleChild())
2553 {
2554 $bundleParentBasketItem = $bundleBasketItem->getParentBasketItem();
2555 if ($bundleParentBasketItem->getBasketCode() == $basketItem->getBasketCode())
2556 {
2557 $basketCountList[$bundleBasketItem->getBasketCode()] = floatval($bundleShipmentItem->getQuantity());
2558 }
2559 }
2560 }
2561 }
2562
2563 }
2564
2565 return $basketCountList;
2566 }
2567
2573 protected static function getStoreDataFromShipmentItemCollection($shipmentItemList)
2574 {
2575 $result = new Result();
2576 $list = Internals\Catalog\Provider::createMapShipmentItemCollectionStoreData($shipmentItemList);
2577 if (!empty($list))
2578 {
2579 $result->setData(array(
2580 'STORE_DATA_LIST' => $list
2581 ));
2582 }
2583 return $result;
2584 }
2585
2592 protected static function makeArrayFromBasketCollection(BasketItemCollection $basketCollection, BasketItem $refreshItem = null)
2593 {
2594 $basketList = array();
2596 foreach ($basketCollection as $basketItem)
2597 {
2598 if ($refreshItem !== null)
2599 {
2600
2601 if ($basketItem->getBasketCode() != $refreshItem->getBasketCode() && $basketItem->isBundleParent())
2602 {
2603 if ($bundleCollection = $basketItem->getBundleCollection())
2604 {
2605 $foundItem = false;
2607 foreach ($bundleCollection as $bundleBasketItem)
2608 {
2609 if ($bundleBasketItem->getBasketCode() == $refreshItem->getBasketCode())
2610 {
2611 $foundItem = true;
2612 break;
2613 }
2614 }
2615
2616 if (!$foundItem)
2617 continue;
2618
2619 $basketList[] = $bundleBasketItem;
2620 continue;
2621 }
2622 }
2623 elseif ($basketItem->getBasketCode() != $refreshItem->getBasketCode())
2624 {
2625 continue;
2626 }
2627
2628 $basketList[] = $basketItem;
2629
2630 continue;
2631 }
2632
2633 $basketList[] = $basketItem;
2634
2635 }
2636
2637 return $basketList;
2638 }
2639
2646 public static function tryReserveShipment(Shipment $shipment)
2647 {
2648 $result = new Result();
2649
2651 $shipmentItemCollection = $shipment->getShipmentItemCollection();
2652
2653 $shipmentItemList = $shipmentItemCollection->getShippableItems();
2655 foreach ($shipmentItemList as $shipmentItem)
2656 {
2657 try
2658 {
2660 $r = static::tryReserveShipmentItem($shipmentItem);
2661 if (!$r->isSuccess())
2662 {
2663 $result->addErrors($r->getErrors());
2664 }
2665 elseif ($r->hasWarnings())
2666 {
2667 $result->addWarnings($r->getWarnings());
2668 }
2669 }
2670 catch(\Exception $e)
2671 {
2673 if (!$shipment = $shipmentItemCollection->getShipment())
2674 {
2675 throw new ObjectNotFoundException('Entity "Shipment" not found');
2676 }
2677 else
2678 {
2679 throw new $e;
2680 }
2681
2682 }
2683
2684 }
2685
2686 return $result;
2687 }
2688
2695 public static function tryUnreserveShipment(Shipment $shipment)
2696 {
2697 $result = new Result();
2699 if (!$shipmentItemCollection = $shipment->getShipmentItemCollection())
2700 {
2701 throw new ObjectNotFoundException('Entity "ShipmentItemCollection" not found');
2702 }
2703
2705 if (!($shipmentCollection = $shipment->getCollection()))
2706 {
2707 throw new ObjectNotFoundException('Entity "ShipmentCollection" not found');
2708 }
2709
2711 if (!($order = $shipmentCollection->getOrder()))
2712 {
2713 throw new ObjectNotFoundException('Entity "Order" not found');
2714 }
2715
2717 foreach ($shipmentItemCollection as $shipmentItem)
2718 {
2720 $r = static::tryUnreserveShipmentItem($shipmentItem);
2721 if (!$r->isSuccess())
2722 {
2723 $result->addErrors($r->getErrors());
2724 EntityMarker::addMarker($order, $shipment, $r);
2725 if (!$shipment->isSystem())
2726 {
2727 $shipment->setField('MARKED', 'Y');
2728 }
2729 }
2730 elseif ($r->hasWarnings())
2731 {
2732 $result->addWarnings($r->getWarnings());
2733 }
2734 }
2735
2736 return $result;
2737 }
2738
2746 public static function tryReserveShipmentItem(ShipmentItem $shipmentItem)
2747 {
2748 $result = new Result();
2749
2750 if (floatval($shipmentItem->getQuantity()) == floatval($shipmentItem->getReservedQuantity()))
2751 {
2752 return $result;
2753 }
2754
2756 if (!$shipmentItemCollection = $shipmentItem->getCollection())
2757 {
2758 throw new ObjectNotFoundException('Entity "ShipmentItemCollection" not found');
2759 }
2760
2762 if (!$shipment = $shipmentItemCollection->getShipment())
2763 {
2764 throw new ObjectNotFoundException('Entity "Shipment" not found');
2765 }
2767 if (!$shipmentCollection = $shipment->getCollection())
2768 {
2769 throw new ObjectNotFoundException('Entity "ShipmentCollection" not found');
2770 }
2771
2773 if (!$order = $shipmentCollection->getOrder())
2774 {
2775 throw new ObjectNotFoundException('Entity "Order" not found');
2776 }
2777
2779 if (!$basketItem = $shipmentItem->getBasketItem())
2780 {
2781 $result->addError(new ResultError(
2782 Loc::getMessage(
2783 'SALE_PROVIDER_BASKET_ITEM_NOT_FOUND',
2784 [
2785 '#BASKET_ITEM_ID#' => $shipmentItem->getBasketId(),
2786 '#SHIPMENT_ID#' => $shipment->getId(),
2787 '#SHIPMENT_ITEM_ID#' => $shipmentItem->getId(),
2788 ]
2789 ),
2790 'PROVIDER_RESERVE_SHIPMENT_ITEM_WRONG_BASKET_ITEM')
2791 );
2792
2793 return $result;
2794 }
2795
2796 if ($basketItem->isBundleParent())
2797 {
2798 return $result;
2799 }
2800
2801 $needQuantity = ($shipmentItem->getQuantity() - $shipmentItem->getReservedQuantity());
2802 $canReserve = false;
2803
2804 $providerName = $basketItem->getProvider();
2805
2806 if (class_exists($providerName))
2807 {
2808 if (empty($context))
2809 {
2810 if ($order)
2811 {
2812 $context = array(
2813 'USER_ID' => $order->getUserId(),
2814 'SITE_ID' => $order->getSiteId(),
2815 'CURRENCY' => $order->getCurrency(),
2816 );
2817 }
2818 else
2819 {
2820 global $USER;
2821 $context = array(
2822 'USER_ID' => $USER->getId(),
2823 'SITE_ID' => SITE_ID,
2824 'CURRENCY' => Currency\CurrencyManager::getBaseCurrency(),
2825 );
2826 }
2827 }
2828
2829 $availableQuantityData = array();
2830
2831 $providerClass = new $providerName($context);
2832 if ($providerClass instanceof SaleProviderBase)
2833 {
2834 $creator = Internals\ProviderCreator::create($context);
2835 $shipmentProductData = $creator->createItemForReserveByShipmentItem($shipmentItem);
2836 $creator->addProductData($shipmentProductData);
2837
2838 $r = $creator->getAvailableQuantity();
2839 if ($r->isSuccess())
2840 {
2841 $resultData = $r->getData();
2842 if (!empty($resultData['AVAILABLE_QUANTITY_LIST']))
2843 {
2844 $productId = $basketItem->getProductId();
2845
2846 $resultAvailableQuantityList = $resultData['AVAILABLE_QUANTITY_LIST'];
2847 if (mb_substr($providerName, 0, 1) == "\\")
2848 {
2849 $providerName = mb_substr($providerName, 1);
2850 }
2851
2852 if (isset($resultAvailableQuantityList[$providerName]) && isset($resultAvailableQuantityList[$providerName][$productId]))
2853 {
2854 $availableQuantityData = array(
2855 'HAS_PROVIDER' => true,
2856 'AVAILABLE_QUANTITY' => $resultAvailableQuantityList[$providerName][$productId]
2857 );
2858 }
2859 }
2860
2861 }
2862 else
2863 {
2864 $result->addErrors($r->getErrors());
2865 return $result;
2866 }
2867 }
2868 else
2869 {
2871 $r = static::tryReserveBasketItem($basketItem, $needQuantity);
2872
2873 $availableQuantityData = $r->getData();
2874 }
2875 }
2876 else
2877 {
2879 $r = static::tryReserveBasketItem($basketItem, $needQuantity);
2880
2881 $availableQuantityData = $r->getData();
2882 }
2883
2884 if (!$r->isSuccess())
2885 {
2886 $result->addErrors($r->getErrors());
2887 return $result;
2888 }
2889 elseif ($r->hasWarnings())
2890 {
2891 $result->addWarnings($r->getWarnings());
2892 return $result;
2893 }
2894
2895 if (array_key_exists('AVAILABLE_QUANTITY', $availableQuantityData))
2896 {
2897 $availableQuantity = $availableQuantityData['AVAILABLE_QUANTITY'];
2898 }
2899 else
2900 {
2901 $result->addWarning( new ResultWarning(Loc::getMessage('SALE_PROVIDER_RESERVE_SHIPMENT_ITEM_WRONG_AVAILABLE_QUANTITY', array(
2902 '#PRODUCT_NAME#' => $basketItem->getField('NAME')
2903 )), 'SALE_PROVIDER_RESERVE_SHIPMENT_ITEM_WRONG_AVAILABLE_QUANTITY') );
2904 return $result;
2905 }
2906
2907 if (array_key_exists('HAS_PROVIDER', $availableQuantityData))
2908 {
2909 $canReserve = $availableQuantityData['HAS_PROVIDER'];
2910 }
2911
2912 if ($canReserve && array_key_exists('QUANTITY_TRACE', $availableQuantityData))
2913 {
2914 $canReserve = $availableQuantityData['QUANTITY_TRACE'];
2915 }
2916
2917 if ($canReserve)
2918 {
2919 if ($r->isSuccess() && ($needQuantity > 0) && ($needQuantity > $availableQuantity)
2920 /*|| ($needReserved < 0) && ($availableQuantity < $needReserved) */)
2921 {
2922 $result->addWarning(new ResultWarning(Loc::getMessage("SALE_PROVIDER_RESERVE_SHIPMENT_ITEM_QUANTITY_NOT_ENOUGH", array(
2923 '#PRODUCT_NAME#' => $basketItem->getField('NAME')
2924 )), "SALE_PROVIDER_RESERVE_SHIPMENT_ITEM_QUANTITY_NOT_ENOUGH"));
2925 return $result;
2926 }
2927
2928 // is not completely correct, but will be processed in real reservations while saving
2929 if (($availableQuantity < 0) && ($shipmentItem->getReservedQuantity() + $availableQuantity < 0))
2930 {
2931 $availableQuantity = -1 * $shipmentItem->getReservedQuantity();
2932 }
2933
2934 if (Configuration::getProductReservationCondition() != ReserveCondition::ON_SHIP)
2935 {
2936
2937 $reservedQuantity = ($availableQuantity >= $needQuantity ? $needQuantity : $availableQuantity);
2938
2939 static::addReservationPoolItem($order->getInternalId(), $shipmentItem->getBasketItem(), $reservedQuantity);
2940
2941 $r = $shipmentItem->setField('RESERVED_QUANTITY', $shipmentItem->getReservedQuantity() + $reservedQuantity);
2942 if (!$r->isSuccess())
2943 {
2944 $result->addErrors($r->getErrors());
2945 }
2946 }
2947 }
2948
2949 $result->addData([
2950 'CAN_RESERVE' => $canReserve,
2951 ]);
2952
2953 return $result;
2954 }
2955
2966 public static function tryUnreserveShipmentItem(ShipmentItem $shipmentItem)
2967 {
2968 $result = new Result();
2969
2971 if (!$shipmentItemCollection = $shipmentItem->getCollection())
2972 {
2973 throw new ObjectNotFoundException('Entity "ShipmentItemCollection" not found');
2974 }
2975
2977 if (!$shipment = $shipmentItemCollection->getShipment())
2978 {
2979 throw new ObjectNotFoundException('Entity "Shipment" not found');
2980 }
2981
2983 if (!$shipmentCollection = $shipment->getCollection())
2984 {
2985 throw new ObjectNotFoundException('Entity "ShipmentCollection" not found');
2986 }
2987
2989 if (!$order = $shipmentCollection->getOrder())
2990 {
2991 throw new ObjectNotFoundException('Entity "Order" not found');
2992 }
2993
2995 if (!$basketItem = $shipmentItem->getBasketItem())
2996 {
2997 $result->addError(new ResultError(
2998 Loc::getMessage(
2999 'SALE_PROVIDER_BASKET_ITEM_NOT_FOUND',
3000 [
3001 '#BASKET_ITEM_ID#' => $shipmentItem->getBasketId(),
3002 '#SHIPMENT_ID#' => $shipment->getId(),
3003 '#SHIPMENT_ITEM_ID#' => $shipmentItem->getId(),
3004 ]
3005 ),
3006 'PROVIDER_TRY_UNRESERVED_SHIPMENT_ITEM_WRONG_BASKET_ITEM')
3007 );
3008
3009 return $result;
3010 }
3011
3012 if ($basketItem->isBundleParent())
3013 {
3014 return $result;
3015 }
3016
3017 $quantity = $shipmentItem->getReservedQuantity();
3018
3019 $canReserve = false;
3020
3021 $providerName = $basketItem->getProvider();
3022
3023 $providerExists = false;
3024 $availableQuantityData = array(
3025 'HAS_PROVIDER' => true,
3026 'AVAILABLE_QUANTITY' => $quantity
3027 );
3028
3029 if (class_exists($providerName))
3030 {
3031 $providerClass = new $providerName();
3032 if ($providerClass instanceof SaleProviderBase)
3033 {
3034 $providerExists = true;
3035 }
3036 }
3037
3038 if (!$providerExists)
3039 {
3040 if (!array_key_exists("IBXSaleProductProvider", class_implements($providerName)))
3041 {
3042 $availableQuantityData['HAS_PROVIDER'] = false;
3043 }
3044 }
3045
3046 if (array_key_exists('HAS_PROVIDER', $availableQuantityData))
3047 {
3048 $canReserve = $availableQuantityData['HAS_PROVIDER'];
3049 }
3050
3051 if ($canReserve)
3052 {
3053
3054 static::addReservationPoolItem($order->getInternalId(), $shipmentItem->getBasketItem(), $quantity);
3055
3056 $reservedQuantity = ($shipmentItem->getReservedQuantity() > 0 ? $shipmentItem->getReservedQuantity() + $quantity : 0);
3057
3058 $needShip = $shipment->needShip();
3059 if ($needShip)
3060 {
3061 $shipmentItem->setFieldNoDemand('RESERVED_QUANTITY', $reservedQuantity);
3062 }
3063 else
3064 {
3065 $r = $shipmentItem->setField('RESERVED_QUANTITY', $reservedQuantity);
3066 if (!$r->isSuccess())
3067 {
3068 $result->addErrors($r->getErrors());
3069 }
3070 }
3071 }
3072
3073 $result->addData([
3074 'CAN_RESERVE' => $canReserve,
3075 ]);
3076
3077 return $result;
3078 }
3079
3086 protected static function tryReserveBasketItem(BasketItem $basketItem, $quantity)
3087 {
3088 $result = new Result();
3089
3090 $provider = $basketItem->getProvider();
3091
3092 if (!$basketItem->isBundleChild())
3093 {
3095 $basket = $basketItem->getCollection();
3096 }
3097 else
3098 {
3100 $parentBasketItem = $basketItem->getParentBasketItem();
3101
3103 $basket = $parentBasketItem->getCollection();
3104 }
3105
3106 $order = $basket->getOrder();
3107 $hasProvider = false;
3108 $quantityTrace = null;
3109
3110 $poolQuantity = static::getReservationPoolItem($order->getInternalId(), $basketItem);
3111 $tryQuantity = $quantity + $poolQuantity;
3112
3113 if ($provider && array_key_exists("IBXSaleProductProvider", class_implements($provider)))
3114 {
3115 $hasProvider = true;
3116 $r = static::checkAvailableProductQuantity($basketItem, $tryQuantity);
3117
3118 $availableQuantityData = $r->getData();
3119 if (array_key_exists('AVAILABLE_QUANTITY', $availableQuantityData))
3120 {
3121 $availableQuantity = floatval($availableQuantityData['AVAILABLE_QUANTITY']);
3122 }
3123 else
3124 {
3125 $result->addWarning(new ResultWarning(Loc::getMessage('SALE_PROVIDER_BASKET_ITEM_WRONG_AVAILABLE_QUANTITY', array(
3126 '#PRODUCT_NAME#' => $basketItem->getField('NAME')
3127 )), 'PROVIDER_BASKET_ITEM_WRONG_AVAILABLE_QUANTITY'));
3128 return $result;
3129 }
3130
3131 if (array_key_exists('QUANTITY_TRACE', $availableQuantityData))
3132 {
3133 $quantityTrace = $availableQuantityData['QUANTITY_TRACE'];
3134 }
3135
3136 if (!$r->isSuccess())
3137 {
3138 $result->addErrors($r->getErrors());
3139 }
3140 elseif ($r->hasWarnings())
3141 {
3142 $result->addWarnings($r->getWarnings());
3143 }
3144
3145 $availableQuantity -= floatval($poolQuantity);
3146 }
3147 else
3148 {
3149 $availableQuantity = $quantity;
3150 }
3151
3152 $fields = array(
3153 'AVAILABLE_QUANTITY' => $availableQuantity,
3154 'HAS_PROVIDER' => $hasProvider,
3155 );
3156
3157 if ($quantityTrace !== null)
3158 {
3159 $fields['QUANTITY_TRACE'] = $quantityTrace;
3160 }
3161
3162 $result->setData($fields);
3163 return $result;
3164 }
3165
3166
3174 private static function reserveBasketItem(BasketItem $basketItem, $quantity)
3175 {
3176 $result = new Result();
3177
3178 $provider = $basketItem->getProvider();
3179
3181 if (!$basket = $basketItem->getCollection())
3182 {
3183 throw new ObjectNotFoundException('Entity "Basket" not found');
3184 }
3185
3187 if (!$order = $basket->getOrder())
3188 {
3189 throw new ObjectNotFoundException('Entity "Order" not found');
3190 }
3191
3192 $r = static::reserveProduct($provider, $basketItem->getProductId(), $quantity);
3193
3194 if ($r->hasWarnings() || !$r->isSuccess())
3195 {
3196 if (!$r->isSuccess())
3197 {
3198 $result->addWarnings($r->getErrors());
3199 }
3200
3201 if ($r->hasWarnings())
3202 {
3203 $result->addWarnings($r->getWarnings());
3204 }
3205
3207 if (!$basket = $basketItem->getCollection())
3208 {
3209 throw new ObjectNotFoundException('Entity "Basket" not found');
3210 }
3211
3212 if ($order = $basket->getOrder())
3213 {
3215 if (!$shipmentCollection = $order->getShipmentCollection())
3216 {
3217 throw new ObjectNotFoundException('Entity "ShipmentCollection" not found');
3218 }
3219
3221 foreach ($shipmentCollection as $shipment)
3222 {
3224 if (!$shipmentItemCollection = $shipment->getShipmentItemCollection())
3225 {
3226 throw new ObjectNotFoundException('Entity "ShipmentItemCollection" not found');
3227 }
3228
3229 if($shipmentItemCollection->getItemByBasketCode($basketItem->getBasketCode()))
3230 {
3231 EntityMarker::addMarker($order, $shipment, $result);
3232 if (!$shipment->isSystem())
3233 {
3234 $shipment->setField('MARKED', 'Y');
3235 }
3236 }
3237 }
3238 }
3239 }
3240
3241 return $result;
3242 }
3243
3252 public static function reserveProduct($provider, $productId, $quantity)
3253 {
3254 global $APPLICATION;
3255
3256 $result = new Result();
3257 $fields = array();
3258
3259 if ($provider && array_key_exists("IBXSaleProductProvider", class_implements($provider)))
3260 {
3261 $hasProvider = true;
3262 $data = array("PRODUCT_ID" => $productId);
3263
3264 if ($quantity > 0)
3265 {
3266 $data["UNDO_RESERVATION"] = "N";
3267 $data["QUANTITY_ADD"] = $quantity;
3268 }
3269 else
3270 {
3271 $data["UNDO_RESERVATION"] = "Y";
3272 $data["QUANTITY_ADD"] = abs($quantity);
3273 }
3274
3275 $APPLICATION->ResetException();
3276 if (($resultReserveData = $provider::ReserveProduct($data)))
3277 {
3278 if ($resultReserveData['RESULT'])
3279 {
3280 $fields['QUANTITY'] = $resultReserveData['QUANTITY_RESERVED'];
3281
3282 if ($quantity < 0)
3283 {
3284 $fields['QUANTITY'] = $quantity;
3285 }
3286
3287 $fields['HAS_PROVIDER'] = $hasProvider;
3288 $result->setData($fields);
3289 $exception = $APPLICATION->GetException();
3290 if ($exception)
3291 {
3292 $result->addWarning(new ResultWarning($exception->GetString(), $exception->GetID()));
3293 }
3294 return $result;
3295 }
3296 else
3297 {
3298 $exception = $APPLICATION->GetException();
3299 if ($exception)
3300 {
3301 $result->addWarning(new ResultWarning($exception->GetString(), $exception->GetID()));
3302 }
3303 else
3304 {
3305 $result->addError(new ResultError(Loc::getMessage('SALE_PROVIDER_RESERVE_BASKET_ITEM_ERROR'), 'SALE_PROVIDER_RESERVE_BASKET_ITEM_ERROR')) ;
3306 }
3307 }
3308
3309 }
3310 else
3311 {
3312 $result->addError(new ResultError(Loc::getMessage('SALE_PROVIDER_RESERVE_BASKET_ITEM_ERROR'), 'SALE_PROVIDER_RESERVE_BASKET_ITEM_ERROR')) ;
3313 }
3314
3315 }
3316 else
3317 {
3318 $fields['QUANTITY'] = $quantity;
3319 $result->setData($fields);
3320 }
3321
3322 return $result;
3323 }
3324
3333 public static function reserveShipmentItem(ShipmentItem $shipmentItem, $quantity)
3334 {
3335 global $APPLICATION;
3336 $result = new Result();
3337 $fields = array();
3338
3340 $shipmentItemCollection = $shipmentItem->getCollection();
3341 if (!$shipmentItemCollection)
3342 {
3343 throw new ObjectNotFoundException('Entity "ShipmentItemCollection" not found');
3344 }
3345
3347 $shipment = $shipmentItemCollection->getShipment();
3348 if (!$shipment)
3349 {
3350 throw new ObjectNotFoundException('Entity "Shipment" not found');
3351 }
3352
3354 $basketItem = $shipmentItem->getBasketItem();
3355 if (!$basketItem)
3356 {
3357 $result->addError(new ResultError(
3358 Loc::getMessage(
3359 'SALE_PROVIDER_BASKET_ITEM_NOT_FOUND',
3360 array(
3361 '#BASKET_ITEM_ID#' => $shipmentItem->getBasketId(),
3362 '#SHIPMENT_ID#' => $shipment->getId(),
3363 '#SHIPMENT_ITEM_ID#' => $shipmentItem->getId(),
3364 )
3365 ),
3366 'PROVIDER_RESERVE_SHIPMENT_ITEM_WRONG_BASKET_ITEM')
3367 );
3368
3369 return $result;
3370 }
3371
3372 $provider = $basketItem->getProvider();
3373
3374 if ($provider && array_key_exists("IBXSaleProductProvider", class_implements($provider)))
3375 {
3376 $data = array(
3377 "PRODUCT_ID" => $basketItem->getProductId(),
3378 "UNDO_RESERVATION" => "N",
3379 "QUANTITY_ADD" => $quantity,
3380 "ORDER_DEDUCTED" => $shipment->isShipped()? "Y" : "N",
3381 );
3382
3383 $APPLICATION->ResetException();
3384 if (($resultReserveData = $provider::ReserveProduct($data)))
3385 {
3386 if ($resultReserveData['RESULT'])
3387 {
3388 $fields['QUANTITY'] = $resultReserveData['QUANTITY_RESERVED'];
3389
3390 if (isset($resultReserveData['QUANTITY_NOT_RESERVED']) && floatval($resultReserveData['QUANTITY_NOT_RESERVED']) > 0)
3391 {
3392 $fields['QUANTITY'] = $shipmentItem->getReservedQuantity() + ($shipmentItem->getQuantity() - $shipmentItem->getReservedQuantity()) - $resultReserveData['QUANTITY_NOT_RESERVED'];
3393 }
3394
3395 $result->setData($fields);
3396 return $result;
3397 }
3398 else
3399 {
3400 if ($ex = $APPLICATION->GetException())
3401 {
3402 if ($ex->GetID() != "ALREADY_FLAG")
3403 $result->addError(new ResultError($ex->GetString())) ;
3404 }
3405 else
3406 {
3407 $result->addError(new ResultError(Loc::getMessage('SALE_PROVIDER_RESERVE_BASKET_ITEM_ERROR'), 'SALE_PROVIDER_RESERVE_BASKET_ITEM_ERROR')) ;
3408 }
3409 }
3410
3411 }
3412
3413 }
3414 elseif (class_exists($provider))
3415 {
3417 $shipmentCollection = $shipment->getCollection();
3418 if (!$shipmentCollection)
3419 {
3420 throw new ObjectNotFoundException('Entity "ShipmentCollection" not found');
3421 }
3422
3424 $order = $shipmentCollection->getOrder();
3425 if (!$order)
3426 {
3427 throw new ObjectNotFoundException('Entity "Order" not found');
3428 }
3429
3430 $context = array(
3431 'SITE_ID' => $order->getSiteId(),
3432 'CURRENCY' => $order->getCurrency(),
3433 );
3434
3435 if ($order->getUserId() > 0)
3436 {
3437 $context['USER_ID'] = $order->getUserId();
3438 }
3439 else
3440 {
3441 global $USER;
3442 $context['USER_ID'] = $USER->getId();
3443 }
3444
3446 $providerClass = new $provider($context);
3447 if ($providerClass && $providerClass instanceof SaleProviderBase)
3448 {
3449
3450 $creator = Internals\ProviderCreator::create($context);
3451 $creator->addShipmentItem($shipmentItem);
3452
3453 $r = $creator->reserve();
3454 if (!$r->isSuccess())
3455 {
3456 $result->addErrors($r->getErrors());
3457 }
3458
3459 }
3460 }
3461
3462 if (!empty($fields))
3463 {
3464 $result->setData($fields);
3465 }
3466 return $result;
3467 }
3468
3476 public static function reduceProductQuantity(ShipmentCollection $shipmentCollection, array $shipmentReserveList = array())
3477 {
3479 if (!$order = $shipmentCollection->getOrder())
3480 {
3481 throw new ObjectNotFoundException('Entity "Order" not found');
3482 }
3483
3484 $options = array(
3485 'ORDER_DEDUCTED' => $order->isShipped()
3486 );
3487
3488 $shipmentReserveListKeys = array_keys($shipmentReserveList);
3489
3490 foreach ($shipmentCollection as $shipmentKey => $shipment)
3491 {
3492 if (!in_array($shipment->getId(), $shipmentReserveListKeys))
3493 {
3494 unset($shipmentCollection[$shipmentKey]);
3495 }
3496 }
3497
3498
3499 foreach ($shipmentCollection as $shipment)
3500 {
3501 $basketProviderList = static::getProviderBasketFromShipment($shipment);
3502
3503 $productList = static::getProductListFromBasketProviderList($basketProviderList);
3504
3505 if (!empty($basketProviderList))
3506 {
3507 foreach ($basketProviderList as $provider => $providerBasketItemList)
3508 {
3509 $shipmentReserveListData = array();
3510 if (!empty($shipmentReserveList)
3511 && !empty($shipmentReserveList[$shipment->getId()]) && is_array($shipmentReserveList[$shipment->getId()]))
3512 {
3513 $shipmentReserveListData = $shipmentReserveList[$shipment->getId()];
3514 }
3515
3516 $result = $provider::reduceProductQuantity($providerBasketItemList, $productList, $shipmentReserveListData, $options);
3517 }
3518 }
3519
3520 }
3521 }
3522
3530 public static function increaseProductQuantity(ShipmentCollection $shipmentCollection, array $shipmentReserveList = array())
3531 {
3533 if (!$order = $shipmentCollection->getOrder())
3534 {
3535 throw new ObjectNotFoundException('Entity "Order" not found');
3536 }
3537
3538 $options = array(
3539 'ORDER_DEDUCTED' => $order->isShipped()
3540 );
3541
3542 $shipmentReserveListKeys = array_keys($shipmentReserveList);
3543
3544 foreach ($shipmentCollection as $shipmentKey => $shipment)
3545 {
3546 if (!in_array($shipment->getId(), $shipmentReserveListKeys))
3547 {
3548 unset($shipmentCollection[$shipmentKey]);
3549 }
3550 }
3551
3552
3553 foreach ($shipmentCollection as $shipment)
3554 {
3555 $basketProviderList = static::getProviderBasketFromShipment($shipment);
3556
3557 $productList = static::getProductListFromBasketProviderList($basketProviderList);
3558
3559 if (!empty($basketProviderList))
3560 {
3561 foreach ($basketProviderList as $provider => $providerBasketItemList)
3562 {
3563 $shipmentReserveListData = array();
3564 if (!empty($shipmentReserveList)
3565 && !empty($shipmentReserveList[$shipment->getId()]) && is_array($shipmentReserveList[$shipment->getId()]))
3566 {
3567 $shipmentReserveListData = $shipmentReserveList[$shipment->getId()];
3568 }
3569
3570 $result = $provider::increaseProductQuantity($providerBasketItemList, $productList, $shipmentReserveListData, $options);
3571 }
3572 }
3573
3574 }
3575 }
3576
3583 public static function getProductStores(BasketItem $basketItem)
3584 {
3585 $result = new Result();
3586
3587 $basketItemProviderMap = static::createProviderBasketItemMap($basketItem, array('SITE_ID'));
3588
3589 if (!empty($basketItemProviderMap))
3590 {
3591 $provider = $basketItemProviderMap['PROVIDER'];
3592
3593 if (array_key_exists("IBXSaleProductProvider", class_implements($provider)))
3594 {
3595 $productId = $basketItemProviderMap["PRODUCT_ID"];
3596 $data = array(
3597 "PRODUCT_ID" => $productId,
3598 "SITE_ID" => $basketItemProviderMap["SITE_ID"],
3599 'BASKET_ID' => $basketItemProviderMap['BASKET_ID']
3600 );
3601
3602 $r = static::getStores($provider, $data);
3603 if ($r->isSuccess())
3604 {
3605 $resultProductData = $r->getData();
3606 if (array_key_exists($productId, $resultProductData))
3607 {
3608 $result->setData($resultProductData);
3609 }
3610 }
3611
3612 }
3613 elseif (class_exists($provider))
3614 {
3616 $basket = $basketItem->getCollection();
3617 if (!$basket)
3618 {
3619 throw new ObjectNotFoundException('Entity "Basket" not found');
3620 }
3621
3623 $order = $basket->getOrder();
3624 if (!$order)
3625 {
3626 throw new ObjectNotFoundException('Entity "Order" not found');
3627 }
3628
3629 $context = array(
3630 'SITE_ID' => $order->getSiteId(),
3631 'CURRENCY' => $order->getCurrency(),
3632 );
3633
3634 if ($order->getUserId() > 0)
3635 {
3636 $context['USER_ID'] = $order->getUserId();
3637 }
3638 else
3639 {
3640 global $USER;
3641 $context['USER_ID'] = $USER->getId();
3642 }
3643
3645 $providerClass = new $provider($context);
3646 if ($providerClass && $providerClass instanceof SaleProviderBase)
3647 {
3648
3649 $creator = Internals\ProviderCreator::create($context);
3650 $creator->addBasketItem($basketItem);
3651
3652 $r = $creator->getProductStores();
3653 if ($r->isSuccess())
3654 {
3655 $result->setData($r->getData());
3656 }
3657 else
3658 {
3659 $result->addErrors($r->getErrors());
3660 }
3661
3662 }
3663 }
3664 }
3665
3666 return $result;
3667 }
3668
3676 public static function getStores($provider, array $fields)
3677 {
3678 $result = new Result();
3679 $resultData = $provider::getProductStores($fields);
3680
3681 $result->setData(
3682 array(
3683 $fields['PRODUCT_ID'] => $resultData
3684 )
3685 );
3686
3687 return $result;
3688 }
3689
3697 public static function checkProductBarcode(BasketItem $basketItem, array $params = array())
3698 {
3699
3700 $provider = $basketItem->getProvider();
3701 $productId = $basketItem->getProductId();
3702 $data = array(
3703 'BARCODE' => $params['BARCODE'],
3704 'STORE_ID' => $params['STORE_ID'],
3705 'PRODUCT_ID' => $productId
3706 );
3707 $result = false;
3708
3709 if ($provider && array_key_exists("IBXSaleProductProvider", class_implements($provider)))
3710 {
3711 $r = static::checkBarcode($provider, $data);
3712 if ($r->isSuccess())
3713 {
3714 $resultData = $r->getData();
3715 if (!empty($resultData) && array_key_exists($productId, $resultData))
3716 {
3717 $result = $resultData[$productId];
3718 }
3719 }
3720 }
3721 elseif (class_exists($provider))
3722 {
3724 $basket = $basketItem->getCollection();
3725 if (!$basket)
3726 {
3727 throw new ObjectNotFoundException('Entity "Basket" not found');
3728 }
3729
3730 $order = $basket->getOrder();
3731
3732 if ($order)
3733 {
3734 $context = array(
3735 'USER_ID' => $order->getUserId(),
3736 'SITE_ID' => $order->getSiteId(),
3737 'CURRENCY' => $order->getCurrency(),
3738 );
3739 }
3740 else
3741 {
3742 global $USER;
3743 $context = array(
3744 'USER_ID' => $USER->getId(),
3745 'SITE_ID' => SITE_ID,
3746 'CURRENCY' => Currency\CurrencyManager::getBaseCurrency(),
3747 );
3748 }
3749
3750 $creator = Internals\ProviderCreator::create($context);
3751
3752 $providerClass = $basketItem->getProviderEntity();
3753 if ($providerClass instanceof SaleProviderBase)
3754 {
3755 $creator->addBasketItemBarcodeData($basketItem, $data);
3756 }
3757
3758 $r = $creator->checkBarcode();
3759 if ($r->isSuccess())
3760 {
3761 if (!empty($providerClass))
3762 {
3763 $reflect = new \ReflectionClass($provider);
3764 $providerName = $reflect->getName();
3765 }
3766 else
3767 {
3768 $providerName = $basketItem->getCallbackFunction();
3769 }
3770
3771 $resultData = $r->getData();
3772 if (!empty($resultData) && array_key_exists('BARCODE_CHECK_LIST', $resultData))
3773 {
3774 $resultList = $resultData['BARCODE_CHECK_LIST'];
3775 if (isset($resultList[$providerName]) && isset($resultList[$providerName][$data['BARCODE']]))
3776 {
3777 $result = $resultList[$providerName][$data['BARCODE']];
3778 }
3779 }
3780 }
3781 }
3782 return $result;
3783 }
3784
3792 public static function checkBarcode($provider, array $barcodeParams)
3793 {
3794 $result = new Result();
3795 if (!array_key_exists("IBXSaleProductProvider", class_implements($provider)))
3796 {
3797 return $result;
3798 }
3799
3800 $resultData = $provider::checkProductBarcode($barcodeParams);
3801
3802 $result->setData(
3803 array(
3804 $barcodeParams["PRODUCT_ID"] => $resultData
3805 )
3806 );
3807
3808 return $result;
3809 }
3810
3817 public static function viewProduct(BasketItem $basketItem)
3818 {
3819 $result = new Result();
3820 $basketProviderData = static::createProviderBasketItemMap($basketItem, array('SITE_ID', 'USER_ID'));
3821 $provider = $basketProviderData['PROVIDER'];
3822 if (!empty($provider))
3823 {
3824 if (array_key_exists("IBXSaleProductProvider", class_implements($provider)))
3825 {
3826 $productId = $basketProviderData['PRODUCT_ID'];
3827 $data = array(
3828 'PRODUCT_ID' => $productId,
3829 'USER_ID' => $basketProviderData['USER_ID'],
3830 'SITE_ID' => $basketProviderData['SITE_ID'],
3831 );
3832
3833 $r = static::getViewProduct($provider, $data);
3834 if ($r->isSuccess())
3835 {
3836 $resultProductData = $r->getData();
3837 if (array_key_exists($productId, $resultProductData))
3838 {
3839 $result->setData($resultProductData);
3840 }
3841 }
3842
3843 }
3844 elseif (class_exists($provider))
3845 {
3847 $basket = $basketItem->getCollection();
3848 if (!$basket)
3849 {
3850 throw new ObjectNotFoundException('Entity "Basket" not found');
3851 }
3852
3853 $order = $basket->getOrder();
3854
3855 if ($order)
3856 {
3857 $context = array(
3858 'USER_ID' => $order->getUserId(),
3859 'SITE_ID' => $order->getSiteId(),
3860 'CURRENCY' => $order->getCurrency(),
3861 );
3862 }
3863 else
3864 {
3865 global $USER;
3866 $context = array(
3867 'USER_ID' => $USER->getId(),
3868 'SITE_ID' => SITE_ID,
3869 'CURRENCY' => Currency\CurrencyManager::getBaseCurrency(),
3870 );
3871 }
3872
3873 $creator = Internals\ProviderCreator::create($context);
3874
3875 $providerClass = $basketItem->getProviderEntity();
3876 if ($providerClass instanceof SaleProviderBase)
3877 {
3878 $creator->addBasketItem($basketItem);
3879 }
3880
3881 $r = $creator->viewProduct();
3882 if ($r->isSuccess())
3883 {
3884 $data = $r->getData();
3885 if (array_key_exists('VIEW_PRODUCTS_LIST', $data))
3886 {
3887 $resultList = $data['VIEW_PRODUCTS_LIST'];
3888
3889 if (!empty($resultList))
3890 {
3891 $productId = $basketItem->getProductId();
3892 $result = reset($resultList);
3893
3894 $result->setData(
3895 array(
3896 $productId => reset($resultList)
3897 )
3898 );
3899 }
3900 }
3901 }
3902 }
3903 }
3904
3905 return $result;
3906 }
3907
3916 public static function getViewProduct($provider, array $fields)
3917 {
3918 $result = new Result();
3919
3920 if (!array_key_exists("IBXSaleProductProvider", class_implements($provider)))
3921 {
3922 throw new ArgumentTypeException('provider');
3923 }
3924
3925 $resultData = $provider::viewProduct($fields);
3926 $result->setData(
3927 array(
3928 $fields['PRODUCT_ID'] => $resultData
3929 )
3930 );
3931 return $result;
3932 }
3933
3940 public static function recurringOrderProduct(BasketItem $basketItem)
3941 {
3942 $result = new Result();
3943 $basketProviderData = static::createProviderBasketItemMap($basketItem, array('SITE_ID', 'USER_ID'));
3944 $provider = $basketProviderData['PROVIDER'];
3945 if (!empty($provider))
3946 {
3947 if (array_key_exists("IBXSaleProductProvider", class_implements($provider)))
3948 {
3949 $data = array(
3950 'PRODUCT_ID' => $basketProviderData['PRODUCT_ID'],
3951 'USER_ID' => $basketProviderData['USER_ID'],
3952 );
3953
3954 $r = static::recurringProduct($provider, $data);
3955 if ($r->isSuccess())
3956 {
3957 $resultProductData = $r->getData();
3958 if (array_key_exists($basketProviderData['PRODUCT_ID'], $resultProductData))
3959 {
3960 $result->setData($resultProductData);
3961 }
3962
3963 }
3964
3965 }
3966 elseif (class_exists($provider))
3967 {
3969 $basket = $basketItem->getCollection();
3970 if (!$basket)
3971 {
3972 throw new ObjectNotFoundException('Entity "Basket" not found');
3973 }
3974
3975 $order = $basket->getOrder();
3976
3977 if ($order)
3978 {
3979 $context = array(
3980 'USER_ID' => $order->getUserId(),
3981 'SITE_ID' => $order->getSiteId(),
3982 'CURRENCY' => $order->getCurrency(),
3983 );
3984 }
3985 else
3986 {
3987 global $USER;
3988 $context = array(
3989 'USER_ID' => $USER->getId(),
3990 'SITE_ID' => SITE_ID,
3991 'CURRENCY' => Currency\CurrencyManager::getBaseCurrency(),
3992 );
3993 }
3994
3995 $creator = Internals\ProviderCreator::create($context);
3996
3997 $providerClass = $basketItem->getProviderEntity();
3998 if ($providerClass instanceof SaleProviderBase)
3999 {
4000 $creator->addBasketItem($basketItem);
4001 }
4002
4003 $r = $creator->recurring();
4004 if ($r->isSuccess())
4005 {
4006 $data = $r->getData();
4007 if (array_key_exists('RECURRING_PRODUCTS_LIST', $data))
4008 {
4009 $resultList = $data['RECURRING_PRODUCTS_LIST'];
4010
4011 if (!empty($resultList))
4012 {
4013 $productId = $basketItem->getProductId();
4014 $result = reset($resultList);
4015
4016 $result->setData(
4017 array(
4018 $productId => reset($resultList)
4019 )
4020 );
4021 }
4022 }
4023 }
4024 }
4025 }
4026
4027 return $result;
4028 }
4029
4037 public static function recurringProduct($provider, array $fields)
4038 {
4039 $result = new Result();
4040 if (!array_key_exists("IBXSaleProductProvider", class_implements($provider)))
4041 {
4042 throw new ArgumentTypeException('provider');
4043 }
4044
4045 $resultData = $provider::recurringOrderProduct($fields);
4046 $result->setData(
4047 array(
4048 $fields['PRODUCT_ID'] => $resultData
4049 )
4050 );
4051 return $result;
4052 }
4053
4060 public static function getSetItems(BasketItemBase $basketItem)
4061 {
4062 $bundleChildList = array();
4063 $provider = $basketItem->getProvider();
4064 if ($provider)
4065 {
4066 if (array_key_exists("IBXSaleProductProvider", class_implements($provider)))
4067 {
4068 $bundleChildList = $provider::GetSetItems($basketItem->getProductId(), BasketItem::TYPE_SET, array('BASKET_ID' => $basketItem->getId()));
4069 }
4070 elseif (class_exists($provider))
4071 {
4073 $collection = $basketItem->getCollection();
4074
4076 $basket = $collection->getBasket();
4077 if (!$basket)
4078 {
4079 throw new ObjectNotFoundException('Entity "Basket" not found');
4080 }
4081
4082 $order = $basket->getOrder();
4083
4084 if ($order)
4085 {
4086 $context = array(
4087 'SITE_ID' => $order->getSiteId(),
4088 'USER_ID' => $order->getUserId(),
4089 'CURRENCY' => $order->getCurrency(),
4090 );
4091 }
4092 else
4093 {
4094 global $USER;
4095 $context = array(
4096 'SITE_ID' => SITE_ID,
4097 'USER_ID' => $USER && $USER->GetID() > 0 ? $USER->GetID() : 0,
4098 'CURRENCY' => Currency\CurrencyManager::getBaseCurrency(),
4099 );
4100 }
4101 $creator = Internals\ProviderCreator::create($context);
4102
4103 $creator->addBasketItem($basketItem);
4104
4105 $r = $creator->getBundleItems();
4106 if ($r->isSuccess())
4107 {
4108 $resultProductListData = $r->getData();
4109 if (!empty($resultProductListData['BUNDLE_LIST']))
4110 {
4111 $bundleChildList = $resultProductListData['BUNDLE_LIST'];
4112 }
4113 }
4114
4115 $order = $basket->getOrder();
4116
4117 if ($order)
4118 {
4119 $context = array(
4120 'SITE_ID' => $order->getSiteId(),
4121 'USER_ID' => $order->getUserId(),
4122 'CURRENCY' => $order->getCurrency(),
4123 );
4124 }
4125 else
4126 {
4127 global $USER;
4128 $context = array(
4129 'SITE_ID' => SITE_ID,
4130 'USER_ID' => $USER && $USER->GetID() > 0 ? $USER->GetID() : 0,
4131 'CURRENCY' => Currency\CurrencyManager::getBaseCurrency(),
4132 );
4133 }
4134 $creator = Internals\ProviderCreator::create($context);
4135
4136 $creator->addBasketItem($basketItem);
4137
4138 $r = $creator->getBundleItems();
4139 if ($r->isSuccess())
4140 {
4141 $resultProductListData = $r->getData();
4142 if (!empty($resultProductListData['BUNDLE_LIST']))
4143 {
4144 $bundleChildList = $resultProductListData['BUNDLE_LIST'];
4145 }
4146 }
4147 }
4148 else
4149 {
4150 $bundleChildList = \CSaleBasket::executeCallbackFunction(
4151 $basketItem->getField('CALLBACK_FUNC'),
4152 $basketItem->getField('MODULE'),
4153 $basketItem->getField('PRODUCT_ID'),
4154 $basketItem->getField('QUANTITY')
4155 );
4156 }
4157
4158 return $bundleChildList;
4159 }
4160
4161 return false;
4162 }
4163
4170 private static function getBundleChildItemsByProductData($providerName, array $productData)
4171 {
4172 if (array_key_exists("IBXSaleProductProvider", class_implements($providerName)))
4173 {
4174 $bundleChildList = $providerName::GetSetItems($productData['PRODUCT_ID'], BasketItem::TYPE_SET, array('BASKET_ID' => $productData['BASKET_ID']));
4175 }
4176 else
4177 {
4178 $bundleChildList = \CSaleBasket::executeCallbackFunction(
4179 $productData['CALLBACK_FUNC'],
4180 $productData['MODULE'],
4181 $productData['PRODUCT_ID'],
4182 $productData['QUANTITY']
4183 );
4184 }
4185
4186 if (is_array($bundleChildList))
4187 {
4188 $bundleChildList = reset($bundleChildList);
4189 }
4190
4191 return $bundleChildList;
4192 }
4193
4194
4201 public static function getBundleChildItems($providerName, array $products)
4202 {
4203 $result = new Result();
4204 $resultList = array();
4205
4206 foreach ($products as $productId => $productData)
4207 {
4208 $resultList[$productId] = static::getBundleChildItemsByProductData($providerName, $productData);
4209 }
4210
4211 if (!empty($resultList))
4212 {
4213 $result->setData(
4214 array(
4215 'BUNDLE_LIST' => $resultList,
4216 )
4217 );
4218 }
4219
4220 return $result;
4221 }
4222
4223
4229 protected static function getProductListFromBasketProviderList($basketProviderList, array $productList = array())
4230 {
4231 $select = array(
4232 'ID',
4233 'CAN_BUY_ZERO',
4234 'NEGATIVE_AMOUNT_TRACE',
4235 'QUANTITY_TRACE',
4236 'QUANTITY',
4237 'QUANTITY_RESERVED'
4238 );
4239
4240 $providerProductList = array();
4241
4242 if (!empty($basketProviderList))
4243 {
4244 foreach ($basketProviderList as $provider => $providerBasketItemList)
4245 {
4246 $providerProductList = $provider::getProductList($providerBasketItemList, $productList, $select) + $providerProductList;
4247 }
4248 }
4249
4250 return (!empty($providerProductList) && is_array($providerProductList) ? $providerProductList : false);
4251 }
4252
4261 public static function checkAvailableProductQuantity(BasketItemBase $basketItem, $deltaQuantity)
4262 {
4263 global $APPLICATION;
4264
4265 $result = new Result();
4266
4267 $resultProductData = array();
4268
4269 $orderId = null;
4270 $userId = null;
4271 $siteId = null;
4272
4274 $collection = $basketItem->getCollection();
4275
4277 if (!$basket = $collection->getBasket())
4278 {
4279 throw new ObjectNotFoundException('Entity "Basket" not found');
4280 }
4281
4282
4283 if (($order = $basket->getOrder()) !== null)
4284 {
4285 $userId = $order->getUserId();
4286 $siteId = $order->getSiteId();
4287 }
4288
4289 if ($siteId === null)
4290 {
4291 $siteId = $basket->getSiteId();
4292 }
4293
4294 $provider = $basketItem->getProvider();
4295
4296 if (!empty($provider))
4297 {
4298 if (array_key_exists("IBXSaleProductProvider", class_implements($provider)))
4299 {
4300 $needQuantity = $basketItem->getQuantity();
4301 if ($order && $order->getId() > 0)
4302 {
4303 $needQuantity = $deltaQuantity;
4304 }
4305
4306 $poolQuantity = 0;
4307
4308 if ($order)
4309 {
4310 $poolQuantity = static::getQuantityPoolItem($order->getInternalId(), $basketItem);
4311 }
4312
4313 $checkQuantity = $needQuantity - floatval($poolQuantity);
4314
4315 $data = array(
4316 "PRODUCT_ID" => $basketItem->getProductId(),
4317 "QUANTITY" => $checkQuantity,
4318 "USER_ID" => $userId,
4319 "SITE_ID" => $siteId,
4320 "BASKET_ID" => $basketItem->getId(),
4321 "CHECK_QUANTITY" => "Y",
4322 "AVAILABLE_QUANTITY" => "Y",
4323 'CHECK_PRICE' => 'N',
4324 'CHECK_COUPONS' => 'N',
4325 "SELECT_QUANTITY_TRACE" => "Y",
4326 );
4327
4328 // TODO: !
4329 if ($deltaQuantity <= 0 || $checkQuantity == 0)
4330 {
4331 $result->setData(array('AVAILABLE_QUANTITY' => $deltaQuantity));
4332 return $result;
4333 }
4334
4335 $hasTrustData = false;
4336
4337 $trustData = static::getTrustData($siteId, $basketItem->getField('MODULE'), $basketItem->getField('PRODUCT_ID'));
4338
4339 if (static::isReadTrustData() === true
4340 && !empty($trustData) && is_array($trustData))
4341 {
4342 $hasTrustData = true;
4343 $resultProductData = $trustData;
4344 $productDataRequiredFields = array_merge(static::getProductDataRequiredFields(), array('AVAILABLE_QUANTITY'));
4345 foreach ($productDataRequiredFields as $requiredField)
4346 {
4347 if (!array_key_exists($requiredField, $resultProductData))
4348 {
4349 $hasTrustData = false;
4350 break;
4351 }
4352 }
4353
4354 if ($hasTrustData
4355 && roundEx($checkQuantity, SALE_VALUE_PRECISION) > roundEx($resultProductData["AVAILABLE_QUANTITY"], SALE_VALUE_PRECISION))
4356 {
4357 $hasTrustData = false;
4358 }
4359
4360 }
4361
4362 if(!$hasTrustData)
4363 {
4364 $APPLICATION->ResetException();
4365 $resultProductData = $provider::GetProductData($data);
4366 $ex = $APPLICATION->GetException();
4367 if ($ex)
4368 {
4369 $result->addWarning( new ResultWarning($ex->GetString(), $ex->GetID()) );
4370 }
4371 }
4372
4373 }
4374 elseif (class_exists($provider))
4375 {
4377 $providerClass = new $provider();
4378 if ($providerClass && $providerClass instanceof SaleProviderBase)
4379 {
4380 $productId = $basketItem->getProductId();
4381 $products = array(
4382 $productId => array(
4383 'ITEM_CODE' => $productId,
4384 'BASKET_CODE' => $basketItem->getBasketCode(),
4385 'QUANTITY' => $deltaQuantity,
4386 )
4387 );
4388 $r = $providerClass->getAvailableQuantity($products);
4389 if ($r->isSuccess())
4390 {
4391 $resultData = $r->getData();
4392 if (!empty($resultData['AVAILABLE_QUANTITY_LIST']))
4393 {
4394 $resultProductData = array(
4395 'AVAILABLE_QUANTITY' => reset($resultData['AVAILABLE_QUANTITY_LIST'])
4396 );
4397 }
4398 }
4399 }
4400 }
4401 else
4402 {
4403 $APPLICATION->ResetException();
4404 $resultProductData = \CSaleBasket::ExecuteCallbackFunction(
4405 $basketItem->getField('CALLBACK_FUNC'),
4406 $basketItem->getField('MODULE'),
4407 $basketItem->getProductId(),
4408 $basketItem->getQuantity()
4409 );
4410
4411 if ($ex = $APPLICATION->GetException())
4412 {
4413 $result->addWarning( new ResultWarning($ex->GetString(), $ex->GetID()) );
4414 }
4415 }
4416 }
4417 else
4418 {
4419 $availableQuantity = $basketItem->getQuantity();
4420 if ($deltaQuantity <= 0)
4421 {
4422 $availableQuantity = $deltaQuantity;
4423 }
4424 $result->setData([
4425 'AVAILABLE_QUANTITY' => $availableQuantity,
4426 ]);
4427
4428 return $result;
4429 }
4430
4431 $fields = array();
4432
4433 if (array_key_exists('AVAILABLE_QUANTITY', $resultProductData))
4434 {
4435 $fields['AVAILABLE_QUANTITY'] = $resultProductData['AVAILABLE_QUANTITY'];
4436 }
4437
4438 if (array_key_exists('QUANTITY_TRACE', $resultProductData))
4439 {
4440 $fields['QUANTITY_TRACE'] = ($resultProductData['QUANTITY_TRACE'] == "Y");
4441 }
4442
4443 if (!empty($fields))
4444 {
4445 $result->setData($fields);
4446 }
4447
4448 return $result;
4449 }
4450
4459 private static function getAvailableQuantityByProductData($providerClass, $productData, array $context)
4460 {
4461 global $APPLICATION;
4462
4463 $result = new Result();
4464
4465 $callbackFunction = null;
4466 $basketItem = null;
4467 if (!empty($productData['BASKET_ITEM']))
4468 {
4469 $basketItem = $productData['BASKET_ITEM'];
4470 }
4471
4472 if (!empty($productData['CALLBACK_FUNC']))
4473 {
4474 $callbackFunction = $productData['CALLBACK_FUNC'];
4475 }
4476
4477 $resultProductData = array();
4478
4479 $userId = $context['USER_ID'];
4480 $siteId = $context['SITE_ID'];
4481
4482 $productId = $productData['PRODUCT_ID'];
4483
4484 $productQuantity = 0;
4485 if (array_key_exists('QUANTITY', $productData))
4486 {
4487 $productQuantity = $productData['QUANTITY'];
4488 }
4489 elseif (!empty($productData['QUANTITY_LIST']))
4490 {
4491 foreach ($productData['QUANTITY_LIST'] as $basketCode => $quantity)
4492 {
4493 $productQuantity += $quantity;
4494 }
4495 }
4496
4497 if (!empty($providerClass) && array_key_exists("IBXSaleProductProvider", class_implements($providerClass)))
4498 {
4499 if ($productQuantity <= 0)
4500 {
4501 $result->setData(
4502 array(
4503 'AVAILABLE_QUANTITY' => $productQuantity
4504 )
4505 );
4506 return $result;
4507 }
4508
4509 $basketId = null;
4510 if ($basketItem)
4511 {
4512 $basketId = $basketItem->getId();
4513 }
4514
4515 $data = array(
4516 "PRODUCT_ID" => $productId,
4517 "QUANTITY" => $productQuantity,
4518 "USER_ID" => $userId,
4519 "SITE_ID" => $siteId,
4520 "BASKET_ID" => $basketId,
4521 "CHECK_QUANTITY" => "Y",
4522 "AVAILABLE_QUANTITY" => "Y",
4523 'CHECK_PRICE' => 'N',
4524 'CHECK_COUPONS' => 'N',
4525 "SELECT_QUANTITY_TRACE" => "Y",
4526 );
4527
4528 // TODO: !
4529// if ($deltaQuantity <= 0 || $checkQuantity == 0)
4530// {
4531// $result->setData(array('AVAILABLE_QUANTITY' => $deltaQuantity));
4532// return $result;
4533// }
4534
4535 $hasTrustData = false;
4536
4537 $trustData = static::getTrustData($siteId, $productData['MODULE'], $productId);
4538
4539 if (static::isReadTrustData() === true
4540 && !empty($trustData) && is_array($trustData))
4541 {
4542 $hasTrustData = true;
4543 $resultProductData = $trustData;
4544 $productDataRequiredFields = array_merge(static::getProductDataRequiredFields(), array('AVAILABLE_QUANTITY'));
4545 foreach ($productDataRequiredFields as $requiredField)
4546 {
4547 if (!array_key_exists($requiredField, $resultProductData))
4548 {
4549 $hasTrustData = false;
4550 break;
4551 }
4552 }
4553
4554 if ($hasTrustData
4555 && roundEx($productQuantity, SALE_VALUE_PRECISION) > roundEx($resultProductData["AVAILABLE_QUANTITY"], SALE_VALUE_PRECISION))
4556 {
4557 $hasTrustData = false;
4558 }
4559
4560 }
4561
4562 if(!$hasTrustData)
4563 {
4564 $APPLICATION->ResetException();
4565 $resultProductData = $providerClass::GetProductData($data);
4566 if ($ex = $APPLICATION->GetException())
4567 {
4568 $result->addWarning( new ResultWarning($ex->GetString(), $ex->GetID()) );
4569 }
4570 }
4571
4572 }
4573 elseif (!empty($callbackFunction))
4574 {
4575 $APPLICATION->ResetException();
4576 $resultProductData = \CSaleBasket::ExecuteCallbackFunction(
4577 $callbackFunction,
4578 $productData['MODULE'],
4579 $productId,
4580 $productQuantity
4581 );
4582
4583 if ($ex = $APPLICATION->GetException())
4584 {
4585 $result->addWarning( new ResultWarning($ex->GetString(), $ex->GetID()) );
4586 }
4587 }
4588 else
4589 {
4590 $result->setData(
4591 array(
4592 'AVAILABLE_QUANTITY' => $productQuantity
4593 )
4594 );
4595 return $result;
4596 }
4597
4598 $fields = array();
4599
4600 if (!empty($resultProductData))
4601 {
4602 if (array_key_exists('AVAILABLE_QUANTITY', $resultProductData))
4603 {
4604 $fields['AVAILABLE_QUANTITY'] = $resultProductData['AVAILABLE_QUANTITY'];
4605 }
4606
4607 if (array_key_exists('QUANTITY_TRACE', $resultProductData))
4608 {
4609 $fields['QUANTITY_TRACE'] = ($resultProductData['QUANTITY_TRACE'] == "Y");
4610 }
4611 }
4612
4613 if (!empty($fields))
4614 {
4615 $result->setData($fields);
4616 }
4617
4618 return $result;
4619 }
4620
4629 private static function getProviderDataByProductData($providerClass, $productData, array $context)
4630 {
4631 $result = new Result();
4632
4633 $providerName = null;
4634 if (!empty($providerClass))
4635 {
4636 $reflect = new \ReflectionClass($providerClass);
4637 $providerName = $reflect->getName();
4638 }
4639
4640 $productId = $productData['PRODUCT_ID'];
4641
4642 $items = array( $productId => $productData );
4643
4644 $r = static::getProductDataByList($items, $providerName, array('PRICE', 'COUPONS', 'AVAILABLE_QUANTITY', 'QUANTITY'), $context);
4645
4646 if ($r->isSuccess())
4647 {
4648 $resultData = $r->getData();
4649 $isExistsProductDataList = isset($resultData['PRODUCT_DATA_LIST']) && !empty($resultData['PRODUCT_DATA_LIST']);
4650 $isExistsProductData = isset($resultData['PRODUCT_DATA_LIST'][$productId]);
4651
4652 if ($isExistsProductDataList && $isExistsProductData)
4653 {
4654 $result->setData($resultData['PRODUCT_DATA_LIST'][$productId]);
4655 }
4656 }
4657
4658 return $result;
4659 }
4660
4668 public static function deliverShipment(Shipment $shipment)
4669 {
4670
4671 $result = new Result();
4672
4673 $needDeliver = null;
4674 if ($shipment->getFields()->isChanged('ALLOW_DELIVERY'))
4675 {
4676 $needDeliver = $shipment->getField('ALLOW_DELIVERY') === "Y";
4677 }
4678
4679 if ($needDeliver === null || ($needDeliver === false && $shipment->getId() <= 0))
4680 return $result;
4681
4682 $resultList = array();
4683
4685 if (!$shipmentItemCollection = $shipment->getShipmentItemCollection())
4686 {
4687 throw new ObjectNotFoundException('Entity "ShipmentItemCollection" not found');
4688 }
4689
4691 if (!$shipmentCollection = $shipment->getCollection())
4692 {
4693 throw new ObjectNotFoundException('Entity "ShipmentCollection" not found');
4694 }
4695
4697 if (!$order = $shipmentCollection->getOrder())
4698 {
4699 throw new ObjectNotFoundException('Entity "Order" not found');
4700 }
4701
4703 if (!$basket = $order->getBasket())
4704 {
4705 return $result;
4706 }
4707
4708 $basketList = static::getBasketFromShipmentItemCollection($shipmentItemCollection);
4709
4710 $basketProviderMap = static::createProviderBasketMap($basketList, array('ORDER_ID', 'USER_ID', 'QUANTITY', 'ALLOW_DELIVERY', 'PAY_CALLBACK', 'PAID'));
4711 $basketProviderList = static::redistributeToProviders($basketProviderMap);
4712
4713 if (!empty($basketProviderList))
4714 {
4715 foreach ($basketProviderList as $provider => $providerBasketItemList)
4716 {
4717 if (array_key_exists("IBXSaleProductProvider", class_implements($provider)))
4718 {
4719
4720 foreach ($providerBasketItemList as $providerBasketItem)
4721 {
4722
4723 if ($providerBasketItem['BASKET_ITEM']->isBundleParent())
4724 {
4725 continue;
4726 }
4727
4728 if ($providerBasketItem['BASKET_ITEM']->getField('MODULE') != '')
4729 {
4730 $data = array(
4731 "PRODUCT_ID" => $providerBasketItem["PRODUCT_ID"],
4732 "USER_ID" => $providerBasketItem["USER_ID"],
4733 "PAID" => $providerBasketItem["PAID"],
4734 "ORDER_ID" => $providerBasketItem["ORDER_ID"],
4735 "BASKET_ID" => $providerBasketItem['BASKET_ID']
4736 );
4737
4738 $r = static::deliverProductData($provider, $data);
4739 if ($r->isSuccess())
4740 {
4741 $resultData = $r->getData();
4742
4743 if (array_key_exists($providerBasketItem["PRODUCT_ID"], $resultData))
4744 {
4745 $resultProductData = $resultData[$providerBasketItem["PRODUCT_ID"]];
4746 }
4747 }
4748 else
4749 {
4750 $result->addErrors($r->getErrors());
4751 }
4752
4753 if (!empty($resultProductData) && is_array($resultProductData))
4754 {
4755 $resultProductData['ORDER_ID'] = $providerBasketItem['ORDER_ID'];
4756 }
4757 }
4758 else
4759 {
4760 $resultProductData = true;
4761 }
4762
4763 $resultList[$providerBasketItem['BASKET_CODE']] = $resultProductData;
4764
4765 }
4766
4767 }
4768 elseif (class_exists($provider))
4769 {
4770 $context = array(
4771 'SITE_ID' => $order->getSiteId(),
4772 'CURRENCY' => $order->getCurrency(),
4773 );
4774
4775 if ($order->getUserId() > 0)
4776 {
4777 $context['USER_ID'] = $order->getUserId();
4778 }
4779 else
4780 {
4781 global $USER;
4782 $context['USER_ID'] = $USER->getId();
4783 }
4784
4785 $creator = Internals\ProviderCreator::create($context);
4786
4788 foreach ($shipmentItemCollection as $shipmentItem)
4789 {
4790 $basketItem = $shipmentItem->getBasketItem();
4791 $providerClass = $basketItem->getProviderEntity();
4792
4793 if ($providerClass instanceof SaleProviderBase)
4794 {
4795 $creator->addShipmentItem($shipmentItem);
4796 }
4797 }
4798
4799 $r = $creator->deliver();
4800 if ($r->isSuccess())
4801 {
4802 $r = $creator->createItemsResultAfterDeliver($r);
4803 if ($r->isSuccess())
4804 {
4805 $data = $r->getData();
4806 if (array_key_exists('RESULT_AFTER_DELIVER_LIST', $data))
4807 {
4808 $resultList = $data['RESULT_AFTER_DELIVER_LIST'] + $resultList;
4809 }
4810 }
4811 }
4812 else
4813 {
4814 $result->addErrors($r->getErrors());
4815 }
4816 }
4817 else
4818 {
4819 foreach ($providerBasketItemList as $providerBasketItem)
4820 {
4821 $resultProductData = \CSaleBasket::ExecuteCallbackFunction(
4822 $providerBasketItem['CALLBACK_FUNC'],
4823 $providerBasketItem['MODULE'],
4824 $providerBasketItem['PRODUCT_ID'],
4825 $providerBasketItem['USER_ID'],
4826 $providerBasketItem["ALLOW_DELIVERY"],
4827 $providerBasketItem['ORDER_ID'],
4828 $providerBasketItem["QUANTITY"]
4829 );
4830
4831 $basketCode = $providerBasketItem['BASKET_ITEM']->getBasketCode();
4832
4833 if (!empty($resultProductData) && is_array($resultProductData))
4834 {
4835 $resultProductData['ORDER_ID'] = $providerBasketItem['ORDER_ID'];
4836 }
4837
4838 $resultList[$basketCode] = $resultProductData;
4839 }
4840 }
4841 }
4842
4843 if (!empty($resultList) && is_array($resultList))
4844 {
4845 $recurringID = intval($order->getField("RECURRING_ID"));
4846 foreach ($resultList as $basketCode => $resultData)
4847 {
4848 if ($order->isPaid())
4849 {
4850 if (!empty($resultData) && is_array($resultData))
4851 {
4852 if (empty($resultData['ORDER_ID']) || intval($resultData['ORDER_ID']) < 0)
4853 $resultData["ORDER_ID"] = $order->getId();
4854
4855 $resultData["REMAINING_ATTEMPTS"] = (defined("SALE_PROC_REC_ATTEMPTS") ? SALE_PROC_REC_ATTEMPTS : 3);
4856 $resultData["SUCCESS_PAYMENT"] = "Y";
4857
4858 if ($recurringID > 0)
4859 \CSaleRecurring::Update($recurringID, $resultData);
4860 else
4861 \CSaleRecurring::Add($resultData);
4862 }
4863 elseif ($recurringID > 0)
4864 {
4865 \CSaleRecurring::Delete($recurringID);
4866 }
4867 }
4868 else
4869 {
4871 if (!$basketItem = $basket->getItemByBasketCode($basketCode))
4872 {
4873 throw new ObjectNotFoundException('Entity "BasketItem" not found');
4874 }
4875
4876 $resRecurring = \CSaleRecurring::GetList(
4877 array(),
4878 array(
4879 "USER_ID" => $order->getUserId(),
4880 "PRODUCT_ID" => $basketItem->getProductId(),
4881 "MODULE" => $basketItem->getField("MODULE")
4882 )
4883 );
4884 while ($recurringData = $resRecurring->Fetch())
4885 {
4886 \CSaleRecurring::Delete($recurringData["ID"]);
4887 }
4888 }
4889 }
4890 }
4891 }
4892
4893 if (!empty($resultList))
4894 {
4895 $result->setData($resultList);
4896 }
4897
4898 return $result;
4899 }
4900
4908 {
4909 global $APPLICATION;
4910
4911 $result = new Result();
4912 $APPLICATION->ResetException();
4913 $resultProductData = false;
4914
4915 if ($provider && array_key_exists("IBXSaleProductProvider", class_implements($provider)))
4916 {
4917 $resultProductData = $provider::DeliverProduct($fields);
4918 }
4919 else
4920 {
4921 $resultProductData = \CSaleBasket::ExecuteCallbackFunction(
4922 $fields['CALLBACK_FUNC'],
4923 $fields['MODULE'],
4924 $fields['PRODUCT_ID'],
4925 $fields['USER_ID'],
4926 $fields["ALLOW_DELIVERY"],
4927 $fields['ORDER_ID'],
4928 $fields["QUANTITY"]
4929 );
4930
4931 if (!empty($resultProductData) && is_array($resultProductData))
4932 {
4933 $resultProductData['ORDER_ID'] = $fields['ORDER_ID'];
4934 }
4935
4936 }
4937
4938 $ex = $APPLICATION->GetException();
4939 if (!empty($ex))
4940 {
4941 $result->addError( new ResultError($ex->GetString(), $ex->GetID()) );
4942 }
4943 else
4944 {
4945 $resultList[$fields['PRODUCT_ID']] = $resultProductData;
4946 }
4947
4948 if (!empty($resultList) && is_array($resultList))
4949 {
4950 $result->setData($resultList);
4951 }
4952
4953 return $result;
4954 }
4955
4956
4963 protected static function createProviderBasketMap(array $basketList, array $select = array())
4964 {
4965 $basketProviderMap = array();
4966
4971 foreach($basketList as $basketIndex => $basketItemDat)
4972 {
4973 if (is_array($basketItemDat) && isset($basketItemDat['BASKET_ITEM']))
4974 {
4975 $basketItem = $basketItemDat['BASKET_ITEM'];
4976 }
4977 else
4978 {
4979 $basketItem = $basketItemDat;
4980 }
4981
4982 $basketProviderData = static::createProviderBasketItemMap($basketItem, $select);
4983 if (!$basketProviderData)
4984 {
4985 continue;
4986 }
4987
4988 $basketProviderMap[$basketIndex] = $basketProviderData;
4989
4990 }
4991
4992 return $basketProviderMap;
4993 }
4994
4995
4996 protected static function createProviderBasketItemMap(BasketItem $basketItem, array $select = array())
4997 {
4998
4999 $basketProviderData = array(
5000 'BASKET_ITEM' => $basketItem,
5001 'BASKET_ID' => $basketItem->getId(),
5002 'BASKET_CODE' => $basketItem->getBasketCode(),
5003 'PRODUCT_ID' => $basketItem->getProductId(),
5004 'MODULE' => $basketItem->getField('MODULE'),
5005 );
5006
5007 $provider = $basketItem->getProvider();
5008 $providerClass = $basketItem->getProviderEntity();
5009 if ($provider)
5010 {
5011 if (array_key_exists("IBXSaleProductProvider", class_implements($provider))
5012 || $providerClass instanceof SaleProviderBase)
5013 {
5014 $basketProviderData['PROVIDER'] = $provider;
5015 }
5016 }
5017 elseif (strval($basketItem->getField('CALLBACK_FUNC')) != '')
5018 {
5019 $basketProviderData['CALLBACK_FUNC'] = $basketItem->getField('CALLBACK_FUNC');
5020 }
5021 elseif (strval($basketItem->getField('PAY_CALLBACK_FUNC')) != '' && in_array('PAY_CALLBACK', $select))
5022 {
5023 $basketProviderData['CALLBACK_FUNC'] = $basketItem->getField('PAY_CALLBACK_FUNC');
5024 }
5025
5026 if (in_array('QUANTITY', $select))
5027 {
5028 $basketProviderData['QUANTITY'] = $basketItem->getQuantity(); // ????
5029 }
5030
5031 if (in_array('RENEWAL', $select))
5032 {
5033 $basketProviderData['RENEWAL'] = $basketItem->getField('RENEWAL')!== null && $basketItem->getField('RENEWAL') != 'N'? 'Y' : 'N';
5034 }
5035
5036 if (in_array('RESERVED', $select))
5037 {
5038 $basketProviderData['RESERVED'] = $basketItem->getField('RESERVED');
5039 }
5040
5041 if (in_array('SITE_ID', $select))
5042 {
5043 $basketProviderData['SITE_ID'] = $basketItem->getField('LID');
5044 }
5045
5046 if (in_array('ORDER_ID', $select))
5047 {
5049 if (!$basket = $basketItem->getCollection())
5050 {
5051 throw new ObjectNotFoundException('Entity "Basket" not found');
5052 }
5053
5054 if ($basket->getOrder() && $basket->getOrderId() > 0)
5055 {
5056 $basketProviderData['ORDER_ID'] = $basket->getOrderId();
5057 }
5058
5059 }
5060
5061 if (in_array('USER_ID', $select))
5062 {
5064 if (!$basket = $basketItem->getCollection())
5065 {
5066 throw new ObjectNotFoundException('Entity "Basket" not found');
5067 }
5068
5069 if ($order = $basket->getOrder())
5070 {
5071 $userId = $order->getUserId();
5072
5073 if ($userId === null)
5074 {
5075 $userId = Sale\Fuser::getUserIdById($basket->getFUserId());
5076 }
5077
5078 if ($userId > 0)
5079 {
5080 $basketProviderData['USER_ID'] = $userId;
5081 }
5082 }
5083
5084 }
5085
5086 if (in_array('PAID', $select))
5087 {
5089 if (!$basket = $basketItem->getCollection())
5090 {
5091 throw new ObjectNotFoundException('Entity "Basket" not found');
5092 }
5093
5094 if ($basket->getOrder() && $basket->getOrderId() > 0)
5095 {
5096 $order = $basket->getOrder();
5097 $basketProviderData['PAID'] = $order->isPaid();
5098 }
5099
5100 }
5101
5102 if (in_array('ALLOW_DELIVERY', $select))
5103 {
5105 if (!$basket = $basketItem->getCollection())
5106 {
5107 throw new ObjectNotFoundException('Entity "Basket" not found');
5108 }
5109
5110 if ($basket->getOrder() && $basket->getOrderId() > 0)
5111 {
5113 $order = $basket->getOrder();
5114
5116 if ($shipmentCollection = $order->getShipmentCollection())
5117 {
5118 $basketProviderData['ALLOW_DELIVERY'] = $shipmentCollection->isAllowDelivery();
5119 }
5120 }
5121
5122 }
5123
5124 return $basketProviderData;
5125 }
5130 private static function getProviderBasketFromShipment(Shipment $shipment)
5131 {
5132 $shipmentItemCollection = $shipment->getShipmentItemCollection();
5133
5134 $basketList = static::getBasketFromShipmentItemCollection($shipmentItemCollection);
5135
5136 $basketProviderMap = static::createProviderBasketMap($basketList, array('QUANTITY', 'PRODUCT_ID'));
5137
5138 $basketProviderList = static::redistributeToProviders($basketProviderMap);
5139
5140 return $basketProviderList;
5141 }
5142
5147 protected static function redistributeToProviders(array $basketProviderMap)
5148 {
5149
5150 $basketProviderList = array();
5151 foreach($basketProviderMap as $basketProviderItem)
5152 {
5153 $providerName = $basketProviderItem['PROVIDER'] ?? '';
5154 $productId = $basketProviderItem['BASKET_ITEM']->getProductId();
5155 $quantity = floatval($basketProviderItem['QUANTITY']);
5156 unset($basketProviderItem['QUANTITY']);
5157
5158 $basketCode = $basketProviderItem['BASKET_CODE'];
5159
5160 if (!isset($basketProviderList[$providerName][$productId]))
5161 {
5162 $basketProviderList[$providerName][$productId] = $basketProviderItem;
5163 }
5164
5165 if (isset($basketProviderList[$providerName][$productId]['QUANTITY_LIST'][$basketCode]))
5166 {
5167 $basketProviderList[$providerName][$productId]['QUANTITY_LIST'][$basketCode] += $quantity;
5168 }
5169 else
5170 {
5171 $basketProviderList[$providerName][$productId]['QUANTITY_LIST'][$basketCode] = $quantity;
5172 }
5173
5174
5175
5176 }
5177
5178 return $basketProviderList;
5179 }
5180
5185 public static function setUsingTrustData($value)
5186 {
5187 static::$useReadTrustData = (bool)$value;
5188 }
5189
5194 public static function isReadTrustData()
5195 {
5196 return (bool)static::$useReadTrustData;
5197 }
5198
5199
5208 public static function isExistsTrustData($siteId, $module, $productId)
5209 {
5210 return (!empty(static::$trustData[$siteId][$module][$productId]) && is_array(static::$trustData[$siteId][$module][$productId]));
5211 }
5212
5213
5221 public static function setTrustData($siteId, $module, $productId, array $fields)
5222 {
5223 static::$trustData[$siteId][$module][$productId] = $fields;
5224 }
5225
5226
5235 public static function getTrustData($siteId, $module, $productId)
5236 {
5237 if (static::isExistsTrustData($siteId, $module, $productId))
5238 return static::$trustData[$siteId][$module][$productId];
5239
5240 return null;
5241 }
5242
5249 public static function resetTrustData($siteId = null, $module = null, $productId = null)
5250 {
5251 if (strval($siteId) != '')
5252 {
5253 if (!empty(static::$trustData[$siteId]))
5254 {
5255 if (intval($productId) > 0 )
5256 {
5257 if (strval($module) == '')
5258 {
5259 foreach (static::$trustData[$siteId] as $moduleName => $data)
5260 {
5261 if (isset(static::$trustData[$siteId][$moduleName][$productId]))
5262 unset(static::$trustData[$siteId][$moduleName][$productId]);
5263 }
5264 }
5265 else
5266 {
5267 if (isset(static::$trustData[$siteId][$module][$productId]))
5268 unset(static::$trustData[$siteId][$module][$productId]);
5269 }
5270 }
5271 elseif (strval($module) != '')
5272 {
5273 if (isset(static::$trustData[$siteId][$module]))
5274 unset(static::$trustData[$siteId][$module]);
5275 }
5276 else
5277 {
5278 if (isset(static::$trustData[$siteId]))
5279 unset(static::$trustData[$siteId]);
5280 }
5281 }
5282 }
5283 else
5284 {
5285 static::$trustData = array();
5286 }
5287
5288 }
5289
5301 protected static function refreshMarkers(Order $order)
5302 {
5303 if ($order->getId() == 0)
5304 {
5305 return;
5306 }
5307
5308 if (!$shipmentCollection = $order->getShipmentCollection())
5309 {
5310 throw new ObjectNotFoundException('Entity "ShipmentCollection" not found');
5311 }
5312
5313 if (!$paymentCollection = $order->getPaymentCollection())
5314 {
5315 throw new ObjectNotFoundException('Entity "PaymentCollection" not found');
5316 }
5317
5318 if (!$basket = $order->getBasket())
5319 {
5320 throw new ObjectNotFoundException('Entity "Basket" not found');
5321 }
5322
5323 $markList = array();
5324
5325 $markerEntityList = array();
5326
5327 $filter = array(
5328 'filter' => array(
5329 '=ORDER_ID' => $order->getId(),
5331 ),
5332 'select' => array('ID', 'ENTITY_TYPE', 'ENTITY_ID', 'CODE', 'SUCCESS'),
5333 'order' => array('ID' => 'DESC')
5334 );
5336 while($markerData = $res->fetch())
5337 {
5338 if (!empty($markList[$markerData['ENTITY_TYPE']])
5339 && !empty($markList[$markerData['ENTITY_TYPE']][$markerData['ENTITY_ID']])
5340 && $markerData['CODE'] == $markList[$markerData['ENTITY_TYPE']][$markerData['ENTITY_ID']]
5341 )
5342 {
5343 continue;
5344 }
5345
5346 if ($markerData['SUCCESS'] != EntityMarker::ENTITY_SUCCESS_CODE_DONE)
5347 {
5348 $markList[$markerData['ENTITY_TYPE']][$markerData['ENTITY_ID']][] = $markerData['CODE'];
5349 }
5350
5351 if ($poolItemSuccess = EntityMarker::getPoolItemSuccess($order, $markerData['ID'], $markerData['ENTITY_TYPE'], $markerData['ENTITY_ID'], $markerData['CODE']))
5352 {
5353 if ($poolItemSuccess == EntityMarker::ENTITY_SUCCESS_CODE_DONE)
5354 {
5355 foreach ($markList[$markerData['ENTITY_TYPE']][$markerData['ENTITY_ID']] as $markerIndex => $markerCode)
5356 {
5357 if ($markerData['CODE'] == $markerCode)
5358 {
5359 unset($markList[$markerData['ENTITY_TYPE']][$markerData['ENTITY_ID']][$markerIndex]);
5360 }
5361 }
5362
5363 if (empty($markList[$markerData['ENTITY_TYPE']][$markerData['ENTITY_ID']]))
5364 {
5365 unset($markList[$markerData['ENTITY_TYPE']][$markerData['ENTITY_ID']]);
5366 }
5367 }
5368 }
5369
5370 if (empty($markList[$markerData['ENTITY_TYPE']]))
5371 {
5372 unset($markList[$markerData['ENTITY_TYPE']]);
5373 }
5374 }
5375
5376 if (!empty($markList))
5377 {
5378 foreach ($markList as $markEntityType => $markEntityList)
5379 {
5380 foreach ($markEntityList as $markEntityId => $markEntityCodeList)
5381 {
5382 if (empty($markEntityCodeList))
5383 {
5384 if (($entity = EntityMarker::getEntity($order, $markEntityType, $markEntityId)) && ($entity instanceof \IEntityMarker))
5385 {
5386 if ($entity->canMarked())
5387 {
5388 $markedField = $entity->getMarkField();
5389 $entity->setField($markedField, 'N');
5390 }
5391 }
5392 }
5393 }
5394 }
5395 }
5396
5397 if (empty($markList) && !EntityMarker::hasErrors($order))
5398 {
5399 if ($shipmentCollection->isMarked())
5400 {
5402 foreach ($shipmentCollection as $shipment)
5403 {
5404 if ($shipment->isMarked())
5405 {
5406 $shipment->setField('MARKED', 'N');
5407 }
5408 }
5409 }
5410 if ($paymentCollection->isMarked())
5411 {
5413 foreach ($paymentCollection as $payment)
5414 {
5415 if ($payment->isMarked())
5416 {
5417 $payment->setField('MARKED', 'N');
5418 }
5419 }
5420 }
5421
5422 $order->setField('MARKED', 'N');
5423 }
5424 }
5425
5426
5427
5431 protected static function getPrimaryFields()
5432 {
5433 return array_merge(
5434 array(
5435 'NAME',
5436 'CATALOG_XML_ID',
5437 'PRODUCT_XML_ID',
5438 'WEIGHT',
5439 'DETAIL_PAGE_URL',
5440 'BARCODE_MULTI',
5441 'DIMENSIONS',
5442 'TYPE',
5443 'SET_PARENT_ID',
5444 'MEASURE_CODE',
5445 'MEASURE_NAME',
5446 ),
5447 static::getUpdatableFields()
5448 );
5449 }
5450
5455 public static function getUpdatableFields()
5456 {
5457 return array(
5458 'CAN_BUY',
5459
5460 'VAT_RATE',
5461 'VAT_INCLUDED',
5462
5463 'PRODUCT_PRICE_ID',
5464 'PRICE',
5465 'CURRENCY',
5466 'BASE_PRICE',
5467 'DISCOUNT_PRICE',
5468
5469 'QUANTITY',
5470 'QUANTITY_RESERVED',
5471 );
5472 }
5473
5478 protected static function getProductDataRequiredFields()
5479 {
5480 return array(
5481 'NAME',
5482 'CAN_BUY',
5483 'BARCODE_MULTI',
5484 'WEIGHT',
5485 'TYPE',
5486 'QUANTITY',
5487 );
5488 }
5489
5494 protected static function getProductDataRequiredPriceFields()
5495 {
5496 return array(
5497 'PRODUCT_PRICE_ID',
5498 'NOTES',
5499 'VAT_RATE',
5500 'BASE_PRICE',
5501 'PRICE',
5502 'CURRENCY',
5503 'DISCOUNT_PRICE',
5504 );
5505 }
5506
5515 public static function getAvailableQuantity($providerClass, array $products, array $context)
5516 {
5517 $result = new Result();
5518 $resultList = array();
5519
5520 foreach ($products as $productId => $productData)
5521 {
5522 $r = static::getAvailableQuantityByProductData($providerClass, $productData, $context);
5523 if (!$r->isSuccess())
5524 {
5525 $result->addErrors($r->getErrors());
5526 }
5527 elseif ($r->hasWarnings())
5528 {
5529 $result->addWarnings($r->getWarnings());
5530 }
5531
5532 $availableQuantityData = $r->getData();
5533 if (array_key_exists('AVAILABLE_QUANTITY', $availableQuantityData))
5534 {
5535 $resultList[$productId] ??= 0;
5536
5537 $resultList[$productId] += floatval($availableQuantityData['AVAILABLE_QUANTITY']);
5538 }
5539 else
5540 {
5541 $result->addWarning(new ResultWarning(Loc::getMessage('SALE_PROVIDER_BASKET_ITEM_WRONG_AVAILABLE_QUANTITY', array(
5542 '#PRODUCT_ID#' => $productId
5543 )), 'PROVIDER_BASKET_ITEM_WRONG_AVAILABLE_QUANTITY'));
5544
5545 }
5546 }
5547
5548 if (!empty($resultList))
5549 {
5550 $result->setData(
5551 array(
5552 'AVAILABLE_QUANTITY_LIST' => $resultList,
5553 )
5554 );
5555 }
5556
5557 return $result;
5558 }
5559
5569 public static function getAvailableQuantityAndPrice($providerClass, array $products, array $context)
5570 {
5571 $result = new Result();
5572 $availableQuantityList = array();
5573 $priceData = array();
5574 $providerName = null;
5575
5576 foreach ($products as $productId => $productData)
5577 {
5579 $basketItem = $productData['BASKET_ITEM'];
5580 if (!$basketItem)
5581 {
5582 throw new ObjectNotFoundException('Entity "BasketItem" not found');
5583 }
5584
5585 $callbackFunction = null;
5586 if (!empty($productData['CALLBACK_FUNC']))
5587 {
5588 $callbackFunction = $productData['CALLBACK_FUNC'];
5589 }
5590
5591 $isCustomItem = !($providerClass || $callbackFunction);
5592
5593 if ($isCustomItem)
5594 {
5595 $providerData = $basketItem->getFieldValues();
5596 $providerData['AVAILABLE_QUANTITY'] = $basketItem->getQuantity();
5597 }
5598 else
5599 {
5600 $r = static::getProviderDataByProductData($providerClass, $productData, $context);
5601 if (!$r->isSuccess())
5602 {
5603 $result->addErrors($r->getErrors());
5604 }
5605 elseif ($r->hasWarnings())
5606 {
5607 $result->addWarnings($r->getWarnings());
5608 }
5609 $providerData = $r->getData();
5610 }
5611
5612 if (!empty($providerData))
5613 {
5614 if (isset($providerData['AVAILABLE_QUANTITY']))
5615 {
5616 $availableQuantityList[$productId] ??= 0;
5617 $availableQuantityList[$productId] += (float)$providerData['AVAILABLE_QUANTITY'];
5618 }
5619 else
5620 {
5621 $result->addWarning(new ResultWarning(Loc::getMessage('SALE_PROVIDER_BASKET_ITEM_WRONG_AVAILABLE_QUANTITY', array(
5622 '#PRODUCT_ID#' => $productId
5623 )), 'PROVIDER_BASKET_ITEM_WRONG_AVAILABLE_QUANTITY'));
5624
5625 }
5626
5627 if (!$isCustomItem)
5628 {
5629 $priceFields = static::getPriceFields();
5630
5631 foreach ($priceFields as $fieldName)
5632 {
5633 if (array_key_exists($fieldName, $providerData))
5634 {
5635 $priceData[$productId][$basketItem->getBasketCode()][$fieldName] = $providerData[$fieldName];
5636 }
5637
5638 }
5639 }
5640 }
5641 }
5642
5643 $result->setData(
5644 array(
5645 'PRODUCT_DATA_LIST' => array(
5646 'PRICE_LIST' => $priceData,
5647 'AVAILABLE_QUANTITY_LIST' => $availableQuantityList
5648 )
5649 )
5650 );
5651
5652 return $result;
5653 }
5654
5655
5662 public static function isNeedShip($shipmentItemList)
5663 {
5664 $result = new Result();
5665
5666 $resultList = array();
5667
5669 foreach ($shipmentItemList as $shipmentItem)
5670 {
5671 $basketItem = $shipmentItem->getBasketItem();
5672 $providerName = $basketItem->getProviderName();
5673
5674 if ($providerName && array_key_exists("IBXSaleProductProvider", class_implements($providerName)))
5675 {
5676
5677 $isNeedShip = false;
5678
5679 if (method_exists($providerName, 'isNeedShip'))
5680 {
5681 $isNeedShip = $providerName::isNeedShip();
5682 }
5683
5684 $resultList[$providerName] = $isNeedShip;
5685
5686 }
5687 }
5688
5689 if (!empty($resultList))
5690 {
5691 $result->setData($resultList);
5692 }
5693
5694 return $result;
5695 }
5696
5700 protected static function getPriceFields()
5701 {
5702 return array(
5703 'PRODUCT_PRICE_ID',
5704 'NOTES',
5705 'VAT_RATE',
5706 'DISCOUNT_NAME',
5707 'DISCOUNT_COUPON',
5708 'DISCOUNT_VALUE',
5709 'RESULT_PRICE',
5710 'PRICE_TYPE_ID',
5711 'BASE_PRICE',
5712 'PRICE',
5713 'CURRENCY',
5714 'DISCOUNT_PRICE',
5715 'CUSTOM_PRICE',
5716 );
5717 }
5718
5719
5720}
if(!Loader::includeModule('messageservice')) $provider
Определения callback_ednaruimhpx.php:21
global $APPLICATION
Определения include.php:80
if($strVal !='') $priceFields
Определения options.php:1817
if(!is_object($USER)||! $USER->IsAuthorized()) $userId
Определения check_mail.php:18
getField($name)
Определения basketitembase.php:478
const TYPE_SET
Определения basketitem.php:28
static isEnableAutomaticReservation()
Определения configuration.php:86
static useStoreControl()
Определения configuration.php:260
static getProductReservationCondition()
Определения configuration.php:78
const ENTITY_SUCCESS_CODE_DONE
Определения entitymarker.php:25
static hasErrors(Order $order)
Определения entitymarker.php:983
static getPoolItemSuccess(Order $order, $id, $entityType, $entityId, $code)
Определения entitymarker.php:947
static getList(array $parameters=array())
Определения entitymarker.php:906
const ACTION_ENTITY_SHIPMENT_COLLECTION_RESERVED_QUANTITY
Определения actionentity.php:11
static save(Sale\Order $order, array $context=array())
Определения provider.php:1299
static getInstance($key)
Определения poolquantity.php:26
static getSiteCurrency($siteId)
Определения sitecurrency.php:96
static getUpdatableFields()
Определения providerbase.php:5455
static getBundleChildItems($providerName, array $products)
Определения providerbase.php:4201
static getProductListFromBasketProviderList($basketProviderList, array $productList=array())
Определения providerbase.php:4229
static reserveProduct($provider, $productId, $quantity)
Определения providerbase.php:3252
static setUsingTrustData($value)
Определения providerbase.php:5185
static getStores($provider, array $fields)
Определения providerbase.php:3676
static getProductData(BasketItemCollection $basketCollection, array $select=array(), BasketItem $refreshItem=null)
Определения providerbase.php:983
static $reservationPool
Определения providerbase.php:32
static getPriceFields()
Определения providerbase.php:5700
static getQuantityPoolItem($key, BasketItem $item)
Определения providerbase.php:133
static getStoreDataFromShipmentItemCollection($shipmentItemList)
Определения providerbase.php:2573
static addQuantityPoolItem($key, BasketItem $item, $value)
Определения providerbase.php:161
static getQuantityPool($key)
Определения providerbase.php:113
static $hitCache
Определения providerbase.php:35
static addReservationPoolItem($key, BasketItem $item, $value)
Определения providerbase.php:103
static setReservationPoolItem($key, BasketItem $item, $value)
Определения providerbase.php:88
static getReservationPool($key)
Определения providerbase.php:55
static recurringProduct($provider, array $fields)
Определения providerbase.php:4037
static getAvailableQuantity($providerClass, array $products, array $context)
Определения providerbase.php:5515
static $productData
Определения providerbase.php:46
static resetTrustData($siteId=null, $module=null, $productId=null)
Определения providerbase.php:5249
static getProductDataByList(array $products, $providerClassName, array $select, array $context, array $options=array())
Определения providerbase.php:1066
static redistributeToProviders(array $basketProviderMap)
Определения providerbase.php:5147
static checkBarcode($provider, array $barcodeParams)
Определения providerbase.php:3792
static getViewProduct($provider, array $fields)
Определения providerbase.php:3916
static getTrustData($siteId, $module, $productId)
Определения providerbase.php:5235
static isExistsTrustData($siteId, $module, $productId)
Определения providerbase.php:5208
static setQuantityPoolItem($key, BasketItem $item, $value)
Определения providerbase.php:144
static setTrustData($siteId, $module, $productId, array $fields)
Определения providerbase.php:5221
static resetQuantityPool($key)
Определения providerbase.php:122
static $trustData
Определения providerbase.php:38
const POOL_ACTION_SHIP
Определения providerbase.php:49
static getProductDataRequiredFields()
Определения providerbase.php:5478
static getPrimaryFields()
Определения providerbase.php:5431
static getReservationPoolItem($key, BasketItem $item)
Определения providerbase.php:77
static resetReservationPool($key)
Определения providerbase.php:66
static $useReadTrustData
Определения providerbase.php:41
static $quantityPool
Определения providerbase.php:44
const POOL_ACTION_RESERVATION
Определения providerbase.php:48
static deliverProductData($provider, array $fields)
Определения providerbase.php:4907
static isReadTrustData()
Определения providerbase.php:5194
static getProductDataRequiredPriceFields()
Определения providerbase.php:5494
getReservedQuantity()
Определения shipmentitem.php:537
static ExecuteCallbackFunction($callbackFunc="", $module="", $productID=0)
Определения basket.php:1822
$options
Определения commerceml2.php:49
$data['IS_AVAILABLE']
Определения .description.php:13
$orderId
Определения payment.php:5
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
Определения file_new.php:804
$res
Определения filter_act.php:7
$result
Определения get_property_values.php:14
$entity
$select
Определения iblock_catalog_list.php:194
$filter
Определения iblock_catalog_list.php:54
global $USER
Определения csv_new_run.php:40
$context
Определения csv_new_setup.php:223
if(!is_null($config))($config as $configItem)(! $configItem->isVisible()) $code
Определения options.php:195
$siteId
Определения ajax.php:8
roundEx($value, $prec=0)
Определения tools.php:4635
$payment
Определения payment.php:14
$order
Определения payment.php:8
$paymentCollection
Определения payment.php:11
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)
Определения prolog_main_admin.php:393
if(empty($signedUserToken)) $key
Определения quickway.php:257
$currency
Определения template.php:266
if($inWords) echo htmlspecialcharsbx(Number2Word_Rus(roundEx($totalVatSum $params['CURRENCY']
Определения template.php:799
$items
Определения template.php:224
const SALE_VALUE_PRECISION
Определения include.php:46
const SALE_PROC_REC_ATTEMPTS
Определения include.php:25
const SITE_ID
Определения sonet_set_content_view.php:12
$fields
Определения yandex_run.php:501