Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
providerbase.php
1<?php
9namespace Bitrix\Sale;
10
18use Bitrix\Sale;
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 {
57 $pool = Internals\PoolQuantity::getInstance($key);
58 return $pool->getByType(Internals\PoolQuantity::POOL_RESERVE_TYPE);
59 }
60
66 protected static function resetReservationPool($key)
67 {
68 $pool = Internals\PoolQuantity::getInstance($key);
69 $pool->reset(Internals\PoolQuantity::POOL_RESERVE_TYPE);
70 }
71
77 public static function getReservationPoolItem($key, BasketItem $item)
78 {
79 $pool = Internals\PoolQuantity::getInstance($key);
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 {
90 $poolInstance = Internals\PoolQuantity::getInstance($key);
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 {
105 $pool = Internals\PoolQuantity::getInstance($key);
106 $pool->add(Internals\PoolQuantity::POOL_RESERVE_TYPE, $item->getField('PRODUCT_ID'), $value);
107 }
108
113 protected static function getQuantityPool($key)
114 {
115 $pool = Internals\PoolQuantity::getInstance($key);
116 return $pool->getByType(Internals\PoolQuantity::POOL_QUANTITY_TYPE);
117 }
118
122 protected static function resetQuantityPool($key)
123 {
124 $pool = Internals\PoolQuantity::getInstance($key);
125 $pool->reset(Internals\PoolQuantity::POOL_QUANTITY_TYPE);
126 }
127
133 public static function getQuantityPoolItem($key, BasketItem $item)
134 {
135 $pool = Internals\PoolQuantity::getInstance($key);
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');
147 $poolInstance = Internals\PoolQuantity::getInstance($key);
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 {
163 $pool = Internals\PoolQuantity::getInstance($key);
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
180 $r = Internals\Catalog\Provider::save($order);
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(
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 {
1010 $currency = Internals\SiteCurrencyTable::getSiteCurrency($siteId);
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
1069 $result = new Result();
1070 $resultList = array();
1071
1072 $needPrice = in_array('PRICE', $select);
1073 $needBasePrice = in_array('BASE_PRICE', $select);
1074 $needCoupons = in_array('COUPONS', $select);
1075 $data = array(
1076 'USER_ID' => $context['USER_ID'],
1077 'SITE_ID' => $context['SITE_ID'],
1078 'CURRENCY' => $context['CURRENCY'],
1079 'CHECK_QUANTITY' => (in_array('QUANTITY', $select) ? 'Y' : 'N'),
1080 'AVAILABLE_QUANTITY' => (in_array('AVAILABLE_QUANTITY', $select) ? 'Y' : 'N'),
1081 'CHECK_PRICE' => ($needPrice ? 'Y' : 'N'),
1082 'CHECK_COUPONS' => ($needCoupons ? 'Y' : 'N'),
1083 'RENEWAL' => (in_array('RENEWAL', $select) ? 'Y' : 'N')
1084 );
1085
1086 if ($needBasePrice)
1087 $data['CHECK_DISCOUNT'] = 'N';
1088
1089 $useOrderProduct = false;
1090 if ($needPrice)
1091 $useOrderProduct = true;
1092
1093 if ($needCoupons)
1094 $useOrderProduct = false;
1095
1096 $data['USE_ORDER_PRODUCT'] = $useOrderProduct;
1097
1098 unset($needCoupons, $needPrice);
1099
1100
1101 if ($providerClassName)
1102 {
1103 if (array_key_exists("IBXSaleProductProvider", class_implements($providerClassName)))
1104 {
1105 $resultProductList = static::getProductProviderData($products, $providerClassName, $data, $select);
1106 if (in_array('RETURN_BASKET_ID', $options))
1107 {
1108 $basketList = array();
1109 foreach ($products as $productId => $productData)
1110 {
1111 $basketItem = $productData['BASKET_ITEM'];
1112 $basketList[] = $basketItem;
1113 }
1114
1115 $resultProductList = static::createItemsAfterGetProductData($basketList, $resultProductList, $select);
1116 }
1117 }
1118 elseif (class_exists($providerClassName))
1119 {
1120 $basketList = array();
1121 foreach ($products as $productId => $productData)
1122 {
1123 $basketList[] = $productData['BASKET_ITEM'];
1124 }
1125
1126 $r = Internals\Catalog\Provider::getProductData($basketList, $context);
1127 if ($r->isSuccess())
1128 {
1129 $resultProductData = $r->getData();
1130 if (!empty($resultProductData['PRODUCT_DATA_LIST']))
1131 {
1132 $itemsList = $resultProductData['PRODUCT_DATA_LIST'];
1133 $resultItemsList = array();
1134 $resultProductList = array();
1135
1136 foreach ($itemsList as $providerName => $products)
1137 {
1138 $resultItemsList = static::createItemsAfterGetProductData($basketList, $products, $select);
1139 }
1140
1141 $resultProductList = $resultProductList + $resultItemsList;
1142
1143 }
1144 }
1145 }
1146
1147 if (!empty($resultProductList))
1148 {
1149 if (!empty($resultList) && is_array($resultList))
1150 {
1151 $resultList = $resultList + $resultProductList;
1152 }
1153 else
1154 {
1155 $resultList = $resultProductList;
1156 }
1157 }
1158 }
1159 else
1160 {
1161 $priceFields = static::getPriceFields();
1162
1163 foreach ($products as $productId => $productData)
1164 {
1165 $callbackFunction = null;
1166 if (!empty($productData['CALLBACK_FUNC']))
1167 {
1168 $callbackFunction = $productData['CALLBACK_FUNC'];
1169 }
1170
1171 $quantityList = array();
1172
1173 if (array_key_exists('QUANTITY', $productData))
1174 {
1175 $quantityList = array($productData['BASKET_CODE'] => $productData['QUANTITY']);
1176
1177 }
1178 elseif (!empty($productData['QUANTITY_LIST']))
1179 {
1180 $quantityList = $productData['QUANTITY_LIST'];
1181 }
1182
1183 foreach($quantityList as $basketCode => $quantity)
1184 {
1185 if (!empty($callbackFunction))
1186 {
1187 $resultProductData = \CSaleBasket::executeCallbackFunction(
1188 $callbackFunction,
1189 $productData['MODULE'],
1190 $productId,
1191 $quantity
1192 );
1193 }
1194 else
1195 {
1196 $resultProductData = array(
1197 'QUANTITY' => $quantity,
1198 'AVAILABLE_QUANTITY' => $quantity,
1199 );
1200 }
1201
1202 $itemCode = $productId;
1203 if (in_array('RETURN_BASKET_ID', $options))
1204 {
1205 $itemCode = $basketCode;
1206 }
1207
1208 if (empty($resultList[$itemCode]))
1209 {
1210 $resultList[$itemCode] = $resultProductData;
1211 }
1212
1213 if (!empty($resultProductData))
1214 {
1215 $resultList[$itemCode]['PRICE_LIST'][$basketCode] = array(
1216 'QUANTITY' => $resultProductData['QUANTITY'],
1217 'AVAILABLE_QUANTITY' => $resultProductData['AVAILABLE_QUANTITY'],
1218 "ITEM_CODE" => $productId,
1219 "BASKET_CODE" => $basketCode,
1220 );
1221
1222 foreach ($priceFields as $fieldName)
1223 {
1224 if (isset($resultProductData[$fieldName]))
1225 {
1226 $resultList[$itemCode]['PRICE_LIST'][$basketCode][$fieldName] = $resultProductData[$fieldName];
1227 }
1228 }
1229 }
1230 }
1231
1232 }
1233 }
1234
1235
1236 if (!empty($resultList))
1237 {
1238 $result->setData(
1239 array(
1240 'PRODUCT_DATA_LIST' => $resultList
1241 )
1242 );
1243 }
1244
1245 return $result;
1246 }
1247
1256 private static function createItemsAfterGetProductData($basketList, array $productDataList, array $select = array())
1257 {
1258 $resultList = array();
1259 $basketIndexList = array();
1260 $basketMap = array();
1261
1262 if (!is_array($basketList) && !($basketList instanceof BasketBase))
1263 {
1264 throw new ArgumentTypeException('basketList');
1265 }
1266
1268 foreach ($basketList as $basketItem)
1269 {
1270 $basketCode = $basketItem->getBasketCode();
1271 $productId = $basketItem->getProductId();
1272
1273 $basketIndexList[$productId][] = $basketCode;
1274 $basketMap[$basketCode] = $basketItem;
1275 }
1276
1277 if (empty($productDataList))
1278 {
1279 return $resultList;
1280 }
1281
1282 foreach ($productDataList as $productId => $productData)
1283 {
1284 if (empty($basketIndexList[$productId]))
1285 continue;
1286
1287 if (empty($productData))
1288 continue;
1289
1290 foreach ($basketIndexList[$productId] as $basketCode)
1291 {
1292 if (!empty($productData['PRICE_LIST']) && !empty($productData['PRICE_LIST'][$basketCode]))
1293 {
1294 $priceData = $productData['PRICE_LIST'][$basketCode];
1295
1296 if (array_key_exists('AVAILABLE_QUANTITY', $priceData)
1297 && !array_key_exists('QUANTITY', $priceData))
1298 {
1299 $priceData['QUANTITY'] = $priceData['AVAILABLE_QUANTITY'];
1300 }
1301
1303 $basketItem = $basketMap[$basketCode];
1304
1305 if (in_array('PRICE', $select) || $basketItem->getId() == 0)
1306 {
1307 $productData = $priceData + $productData;
1308 }
1309 else
1310 {
1311 if (isset($priceData['QUANTITY']))
1312 {
1313 $productData['QUANTITY'] = $priceData['QUANTITY'];
1314 }
1315
1316 if (isset($priceData['AVAILABLE_QUANTITY']))
1317 {
1318 $productData['AVAILABLE_QUANTITY'] = $priceData['AVAILABLE_QUANTITY'];
1319 }
1320
1321 unset($productData['PRICE_LIST']);
1322 }
1323 }
1324
1325 if (in_array('AVAILABLE_QUANTITY', $select) && isset($productData['AVAILABLE_QUANTITY']))
1326 {
1327 $productData['QUANTITY'] = $productData['AVAILABLE_QUANTITY'];
1328 }
1329
1330 $resultList[$basketCode] = $productData;
1331 }
1332 }
1333
1334 return $resultList;
1335 }
1336
1346 public static function getProductProviderData(array $products, $provider, array $data, array $select = array())
1347 {
1348 $result = array();
1349
1350 foreach ($products as $productData)
1351 {
1352 $productSelect = array_fill_keys($select, true);
1353 $productId = $productData['PRODUCT_ID'];
1354
1355 $currentUseOrderProduct = $data['USE_ORDER_PRODUCT'];
1356 if (isset($productData['IS_NEW']) && $productData['IS_NEW'])
1357 {
1358 $currentUseOrderProduct = false;
1359 }
1360
1361 $fields = $data;
1362
1363 if (isset($productData['IS_ORDERABLE']) && $productData['IS_ORDERABLE'])
1364 {
1365 $fields['CHECK_COUPONS'] = 'Y';
1366 }
1367 else
1368 {
1369 $fields['CHECK_COUPONS'] = 'N';
1370 }
1371
1372 if (isset($productData['IS_BUNDLE_CHILD']) && $productData['IS_BUNDLE_CHILD'])
1373 {
1374 $fields['CHECK_DISCOUNT'] = 'N';
1375 $fields['CHECK_COUPONS'] = 'N';
1376 }
1377
1378 $fields['PRODUCT_ID'] = $productId;
1379
1380 if (isset($productData['SUBSCRIBE']) && $productData['SUBSCRIBE'] === true)
1381 {
1382 unset($productSelect['QUANTITY'], $productSelect['AVAILABLE_QUANTITY']);
1383
1384 $fields['CHECK_QUANTITY'] = 'N';
1385 $fields['AVAILABLE_QUANTITY'] = 'N';
1386 }
1387
1388 $quantityList = array();
1389
1390 if (!empty($productData['QUANTITY_LIST']))
1391 {
1392 $quantityList = $productData['QUANTITY_LIST'];
1393 }
1394 else
1395 {
1396 $quantityList[$productData['BASKET_CODE']] = $productData['QUANTITY'];
1397 }
1398
1399 $basketId = null;
1400
1401 if (!empty($productData['BASKET_ID']))
1402 {
1403 $basketId = $productData['BASKET_ID'];
1404 }
1405
1406
1407 if (intval($basketId) == 0)
1408 {
1410 $basketItem = $productData['BASKET_ITEM'];
1411 if ($basketItem)
1412 {
1413 $basketId = $basketItem->getId();
1414 }
1415 }
1416//
1417 if (intval($basketId) > 0)
1418 {
1419 $fields['BASKET_ID'] = $basketId;
1420 }
1421
1422 $hasTrustData = false;
1423
1424 $trustData = static::getTrustData($data['SITE_ID'], $productData['MODULE'], $productData['PRODUCT_ID']);
1425 $resultProductData = array();
1426
1427 if (static::isReadTrustData() === true
1428 && !empty($trustData) && is_array($trustData))
1429 {
1430 $hasTrustData = true;
1431 $resultProductData = $trustData;
1432
1433 foreach (static::getProductDataRequiredFields() as $requiredField)
1434 {
1435 if (!array_key_exists($requiredField, $resultProductData))
1436 {
1437 $hasTrustData = false;
1438 break;
1439 }
1440 }
1441
1442
1443 if ($hasTrustData && isset($productSelect['PRICE']))
1444 {
1445 foreach (static::getProductDataRequiredPriceFields() as $requiredField)
1446 {
1447 if (!array_key_exists($requiredField, $resultProductData))
1448 {
1449 $hasTrustData = false;
1450 break;
1451 }
1452 }
1453 }
1454 }
1455
1456 $itemCode = $productData['PRODUCT_ID'];
1457
1458 $resultProviderDataList = array();
1459
1460 if(!$hasTrustData)
1461 {
1462 foreach($quantityList as $basketCode => $quantity)
1463 {
1464 if (!empty($resultProviderDataList[$quantity]))
1465 {
1466 $resultProviderDataList[$quantity]['BASKET_CODE'][] = $basketCode;
1467 continue;
1468 }
1469
1470 $requestFields = $fields;
1471 $requestFields['QUANTITY'] = $quantity;
1472
1473 $resultProviderDataList[$quantity] = array(
1474 'BASKET_CODE' => array($basketCode),
1475 'DATA' => ($currentUseOrderProduct ? $provider::OrderProduct(
1476 $requestFields
1477 ) : $provider::GetProductData($requestFields))
1478 );
1479
1480 }
1481
1482 }
1483 else
1484 {
1485
1486 if (!isset($productSelect['AVAILABLE_QUANTITY']) && array_key_exists("AVAILABLE_QUANTITY", $resultProductData))
1487 {
1488 unset($resultProductData['AVAILABLE_QUANTITY']);
1489 }
1490
1491 $productQuantity = floatval($resultProductData['QUANTITY']);
1492
1493 $resultProviderDataList[$productQuantity] = array(
1494 'BASKET_CODE' => array($productData['BASKET_CODE']),
1495 'DATA' => $resultProductData
1496 );
1497
1498 }
1499
1500 $priceFields = static::getPriceFields();
1501
1502 foreach ($resultProviderDataList as $quantity => $providerData)
1503 {
1504 if (empty($result[$itemCode]))
1505 {
1506 $result[$itemCode] = $providerData['DATA'];
1507 }
1508
1509 $basketCodeList = $providerData['BASKET_CODE'];
1510
1511 foreach ($basketCodeList as $basketCode)
1512 {
1513 $result[$itemCode]['PRICE_LIST'][$basketCode] = array(
1514 "ITEM_CODE" => $itemCode,
1515 "BASKET_CODE" => $basketCode,
1516 );
1517
1518 if (isset($providerData['DATA']['QUANTITY']) && $providerData['DATA']['QUANTITY'] > 0)
1519 {
1520 $result[$itemCode]['PRICE_LIST'][$basketCode]['QUANTITY'] = $providerData['DATA']['QUANTITY'];
1521 }
1522
1523 if (isset($providerData['DATA']['AVAILABLE_QUANTITY']))
1524 {
1525 $result[$itemCode]['PRICE_LIST'][$basketCode]['AVAILABLE_QUANTITY'] = $providerData['DATA']['AVAILABLE_QUANTITY'];
1526 }
1527 }
1528
1529 foreach ($priceFields as $fieldName)
1530 {
1531 if (isset($providerData['DATA'][$fieldName]))
1532 {
1533 foreach ($basketCodeList as $basketCode)
1534 {
1535 $result[$itemCode]['PRICE_LIST'][$basketCode][$fieldName] = $providerData['DATA'][$fieldName];
1536 }
1537 }
1538 }
1539 }
1540
1541// $result[$itemCode]['ITEM_CODE'] = $productData['ITEM_CODE'];
1542
1543 if (isset($productData['IS_BUNDLE_PARENT']) && $productData['IS_BUNDLE_PARENT'])
1544 {
1545 $result[$itemCode]["BUNDLE_ITEMS"] = array();
1547 $bundleChildDataList = static::getBundleChildItemsByProductData($provider, $productData);
1548 if (!empty($bundleChildDataList) && is_array($bundleChildDataList))
1549 {
1550 $quantity = $productData['QUANTITY'] ?? $productData['QUANTITY_LIST'][$basketCode] ?? 0;
1551
1552 foreach ($bundleChildDataList["ITEMS"] as &$itemData)
1553 {
1554 $itemData['QUANTITY'] = $itemData['QUANTITY'] * $quantity;
1555 }
1556 unset($itemData);
1557 $result[$itemCode]["BUNDLE_ITEMS"] = $bundleChildDataList["ITEMS"];
1558 }
1559 }
1560 }
1561
1562 return $result;
1563 }
1564
1572 public static function getCatalogData(array $basketProviderList, array $context, array $select = array())
1573 {
1574 $needPrice = in_array('PRICE', $select);
1575 $needBasePrice = in_array('BASE_PRICE', $select);
1576 $needCoupons = in_array('COUPONS', $select);
1577
1578 $result = array();
1579// $orderId = null;
1580 $userId = null;
1581 $siteId = null;
1582 $currency = null;
1583
1584 if (!empty($context['USER_ID']) && intval($context['USER_ID']) > 0)
1585 {
1586 $userId = $context['USER_ID'];
1587 }
1588
1589 if (array_key_exists('SITE_ID', $context))
1590 {
1591 $siteId = $context['SITE_ID'];
1592 }
1593
1594 if (array_key_exists('CURRENCY', $context))
1595 {
1596 $currency = $context['CURRENCY'];
1597 }
1598
1599 $data = array(
1600 'USER_ID' => $userId,
1601 'SITE_ID' => $siteId,
1602 'CURRENCY' => $currency,
1603 'CHECK_QUANTITY' => (in_array('QUANTITY', $select) ? 'Y' : 'N'),
1604 'AVAILABLE_QUANTITY' => (in_array('AVAILABLE_QUANTITY', $select) ? 'Y' : 'N'),
1605 'CHECK_PRICE' => ($needPrice ? 'Y' : 'N'),
1606 'CHECK_COUPONS' => ($needCoupons ? 'Y' : 'N'),
1607 'RENEWAL' => (in_array('RENEWAL', $select) ? 'Y' : 'N')
1608 );
1609
1610 if ($needBasePrice)
1611 $data['CHECK_DISCOUNT'] = 'N';
1612
1613 $useOrderProduct = false;
1614 if ($needPrice)
1615 $useOrderProduct = true;
1616
1617 if ($needCoupons)
1618 $useOrderProduct = false;
1619
1620 unset($needCoupons, $needPrice);
1621
1622 foreach ($basketProviderList as $provider => $providerBasketItemList)
1623 {
1624 if ($provider && array_key_exists("IBXSaleProductProvider", class_implements($provider)))
1625 {
1626 foreach ($providerBasketItemList as $providerBasketItem)
1627 {
1628 $currentUseOrderProduct = $useOrderProduct;
1629 if (!isset($providerBasketItem['BASKET_ID']) || (int)$providerBasketItem['BASKET_ID'] <= 0)
1630 $currentUseOrderProduct = false;
1631
1632 $providerFields = $data;
1633
1634 if ($providerBasketItem['BASKET_ITEM']->isBundleChild())
1635 {
1636 $providerFields['CHECK_DISCOUNT'] = 'N';
1637 }
1638
1639 if ($providerBasketItem['BASKET_ITEM']->getField("CAN_BUY") == "N"
1640 || $providerBasketItem['BASKET_ITEM']->getField("DELAY") == "Y"
1641 || $providerBasketItem['BASKET_ITEM']->getField("SUBSCRIBE") == "Y"
1642 )
1643 {
1644 $providerFields['CHECK_COUPONS'] = 'N';
1645 }
1646 else
1647 {
1648 $providerFields['CHECK_COUPONS'] = 'Y';
1649 }
1650
1651 $providerFields['PRODUCT_ID'] = $providerBasketItem['PRODUCT_ID'];
1652 $providerFields['QUANTITY'] = $providerBasketItem['QUANTITY'];
1653
1654 if (intval($providerBasketItem['BASKET_ID']) > 0)
1655 {
1656 $providerFields['BASKET_ID'] = $providerBasketItem['BASKET_ID'];
1657 }
1658
1659 $hasTrustData = false;
1660
1661 $trustData = static::getTrustData($siteId, $providerBasketItem['MODULE'], $providerBasketItem['PRODUCT_ID']);
1662
1663 if (static::isReadTrustData() === true
1664 && !empty($trustData) && is_array($trustData))
1665 {
1666 $hasTrustData = true;
1667 $resultProductData = $trustData;
1668
1669 foreach (static::getProductDataRequiredFields() as $requiredField)
1670 {
1671 if (!array_key_exists($requiredField, $resultProductData))
1672 {
1673 $hasTrustData = false;
1674 break;
1675 }
1676 }
1677
1678
1679 if ($hasTrustData && in_array('PRICE', $select))
1680 {
1681 foreach (static::getProductDataRequiredPriceFields() as $requiredField)
1682 {
1683 if (!array_key_exists($requiredField, $resultProductData))
1684 {
1685 $hasTrustData = false;
1686 break;
1687 }
1688 }
1689 }
1690 }
1691
1692
1693 if(!$hasTrustData)
1694 {
1695 $resultProductData = ($currentUseOrderProduct ? $provider::OrderProduct($providerFields) : $provider::GetProductData($providerFields));
1696 }
1697 else
1698 {
1699 if (!in_array('AVAILABLE_QUANTITY', $select) && array_key_exists("AVAILABLE_QUANTITY", $resultProductData))
1700 {
1701 unset($resultProductData['AVAILABLE_QUANTITY']);
1702 }
1703 }
1704
1705 $basketCode = $providerBasketItem['BASKET_ITEM']->getBasketCode();
1706 $result[$basketCode] = $resultProductData;
1707
1708 if ($providerBasketItem['BASKET_ITEM']->isBundleParent())
1709 {
1710
1711 $result[$basketCode]["BUNDLE_ITEMS"] = array();
1713 $bundleChildDataList = static::getSetItems($providerBasketItem['BASKET_ITEM']);
1714 if (!empty($bundleChildDataList) && is_array($bundleChildDataList))
1715 {
1716 $bundleChildList = reset($bundleChildDataList);
1717
1718 foreach ($bundleChildList["ITEMS"] as &$itemData)
1719 {
1720 $itemData['QUANTITY'] = $itemData['QUANTITY'] * $providerBasketItem['BASKET_ITEM']->getQuantity();
1721 }
1722 unset($itemData);
1723 $result[$basketCode]["BUNDLE_ITEMS"] = $bundleChildList["ITEMS"];
1724 }
1725
1726 }
1727 }
1728 }
1729 else
1730 {
1731 foreach ($providerBasketItemList as $providerBasketItem)
1732 {
1733 $resultProductData = \CSaleBasket::executeCallbackFunction(
1734 $providerBasketItem['CALLBACK_FUNC'],
1735 $providerBasketItem['MODULE'],
1736 $providerBasketItem['PRODUCT_ID'],
1737 $providerBasketItem['QUANTITY']
1738 );
1739
1740 $basketCode = $providerBasketItem['BASKET_ITEM']->getBasketCode();
1741 $result[$basketCode] = $resultProductData;
1742 }
1743 }
1744 }
1745
1746 return $result;
1747 }
1748
1757 public static function tryShipment(Shipment $shipment)
1758 {
1759 $result = new Result();
1760 $needShip = $shipment->needShip();
1761 if ($needShip === null)
1762 return $result;
1763
1764 $resultList = array();
1765 $storeData = array();
1766
1768 $shipmentItemCollection = $shipment->getShipmentItemCollection();
1769 if (!$shipmentItemCollection)
1770 {
1771 throw new ObjectNotFoundException('Entity "ShipmentItemCollection" not found');
1772 }
1773
1775 $shipment = $shipmentItemCollection->getShipment();
1776 if (!$shipment)
1777 {
1778 throw new ObjectNotFoundException('Entity "ShipmentCollection" not found');
1779 }
1780
1782 $shipmentCollection = $shipment->getCollection();
1783 if (!$shipmentCollection)
1784 {
1785 throw new ObjectNotFoundException('Entity "ShipmentCollection" not found');
1786 }
1787
1788 $r = static::tryShipmentItemList($shipmentItemCollection);
1789
1790 $basketList = static::getBasketFromShipmentItemCollection($shipmentItemCollection);
1791
1792 $bundleIndexList = static::getBundleIndexFromShipmentItemCollection($shipmentItemCollection);
1793
1794 $basketCountList = static::getBasketCountFromShipmentItemCollection($shipmentItemCollection);
1795
1796 $basketProviderMap = static::createProviderBasketMap($basketList, array('RESERVED', 'SITE_ID'));
1797 $basketProviderList = static::redistributeToProviders($basketProviderMap);
1798
1800 {
1802 $r = static::getStoreDataFromShipmentItemCollection($shipmentItemCollection);
1803 if ($r->isSuccess())
1804 {
1805 $resultStoreData = $r->getData();
1806 if (!empty($resultStoreData['STORE_DATA_LIST']))
1807 {
1808 $storeDataList = $resultStoreData['STORE_DATA_LIST'];
1809 }
1810 }
1811 else
1812 {
1813 $result->addErrors($r->getErrors());
1814 }
1815
1816 }
1817
1818 if (!empty($basketProviderList))
1819 {
1820 foreach ($basketProviderList as $provider => $providerBasketItemList)
1821 {
1822 if ($provider && array_key_exists("IBXSaleProductProvider", class_implements($provider)))
1823 {
1824 foreach ($providerBasketItemList as $providerBasketItem)
1825 {
1826 if ($providerBasketItem['BASKET_ITEM']->isBundleParent())
1827 {
1828 continue;
1829 }
1830
1831 $resultProduct = new Result();
1832
1833
1834 $quantity = 0;
1835 $basketStoreData = array();
1836
1837 $basketCode = $providerBasketItem['BASKET_CODE'];
1838
1840 if (!$basketItem = $providerBasketItem['BASKET_ITEM'])
1841 {
1842 throw new ObjectNotFoundException('Entity "BasketItem" not found');
1843 }
1844
1846 {
1847 $quantity = $basketCountList[$basketCode];
1848
1849 if (!empty($storeDataList) && is_array($storeDataList)
1850 && isset($storeDataList[$basketCode]))
1851 {
1852 $basketStoreData = $storeDataList[$basketCode];
1853 }
1854
1855 if (!empty($basketStoreData))
1856 {
1857 $allBarcodeQuantity = 0;
1858 foreach($basketStoreData as $basketShipmentItemStore)
1859 {
1860 $allBarcodeQuantity += $basketShipmentItemStore['QUANTITY'];
1861 }
1862
1863 if ($quantity > $allBarcodeQuantity)
1864 {
1865 $resultProduct->addError(new ResultError(Loc::getMessage('SALE_PROVIDER_SHIPMENT_SHIPPED_LESS_QUANTITY', array(
1866 '#PRODUCT_NAME#' => $basketItem->getField('NAME')
1867 )), 'SALE_PROVIDER_SHIPMENT_SHIPPED_LESS_QUANTITY'));
1868 }
1869 elseif ($quantity < $allBarcodeQuantity)
1870 {
1871 $resultProduct->addError(new ResultError(Loc::getMessage('SALE_PROVIDER_SHIPMENT_SHIPPED_MORE_QUANTITY', array(
1872 '#PRODUCT_NAME#' => $basketItem->getField('NAME')
1873 )), 'SALE_PROVIDER_SHIPMENT_SHIPPED_MORE_QUANTITY'));
1874 }
1875 }
1876
1877 }
1878
1879 if ($resultProduct->isSuccess())
1880 {
1881
1882 if ($needShip === true)
1883 {
1884 if (method_exists($provider, 'tryShipmentProduct'))
1885 {
1887 $resultProduct = $provider::tryShipmentProduct($basketItem, $providerBasketItem['RESERVED'], $basketStoreData, $quantity);
1888 }
1889 }
1890 else
1891 {
1892 if (method_exists($provider, 'tryUnshipmentProduct'))
1893 {
1895 $resultProduct = $provider::tryUnshipmentProduct($providerBasketItem['PRODUCT_ID']);
1896 }
1897 }
1898 }
1899
1900 $resultList[$basketCode] = $resultProduct;
1901
1902 }
1903 }
1904 elseif (class_exists($provider))
1905 {
1906
1908 if (!$shipmentCollection = $shipment->getCollection())
1909 {
1910 throw new ObjectNotFoundException('Entity "ShipmentCollection" not found');
1911 }
1912
1914 if (!$order = $shipmentCollection->getOrder())
1915 {
1916 throw new ObjectNotFoundException('Entity "Order" not found');
1917 }
1918
1919 $pool = Internals\PoolQuantity::getInstance($order->getInternalId());
1920
1921 $context = array(
1922 'SITE_ID' => $order->getSiteId(),
1923 'CURRENCY' => $order->getCurrency(),
1924 );
1925
1926 if ($order->getUserId() > 0)
1927 {
1928 $context['USER_ID'] = $order->getUserId();
1929 }
1930 else
1931 {
1932 global $USER;
1933 $context['USER_ID'] = $USER->getId();
1934 }
1935
1936 $creator = Internals\ProviderCreator::create($context);
1937
1938 $tryShipProductList = array();
1940 foreach ($shipmentItemCollection as $shipmentItem)
1941 {
1942 $basketItem = $shipmentItem->getBasketItem();
1943 $providerClass = $basketItem->getProviderEntity();
1944
1945 if ($providerClass instanceof SaleProviderBase)
1946 {
1947 $shipmentProductData = $creator->createItemForShip($shipmentItem);
1948 $creator->addProductData($shipmentProductData);
1949 }
1950 }
1951
1952 $r = $creator->tryShip();
1953 if ($r->isSuccess())
1954 {
1955 if ($r->hasWarnings())
1956 {
1957 $result->addWarnings($r->getWarnings());
1958 }
1959 else
1960 {
1961 $data = $r->getData();
1962 if (array_key_exists('TRY_SHIP_PRODUCTS_LIST', $data))
1963 {
1964 $tryShipProductList = $data['TRY_SHIP_PRODUCTS_LIST'] + $tryShipProductList;
1965
1966 $creator->setItemsResultAfterTryShip($pool, $tryShipProductList);
1967
1968 }
1969 }
1970 }
1971 else
1972 {
1973 $result->addWarnings($r->getErrors());
1974 }
1975 }
1976 }
1977 }
1978
1979 if (!empty($resultList)
1980 && !empty($bundleIndexList) && is_array($bundleIndexList))
1981 {
1982
1983 foreach ($bundleIndexList as $bundleParentBasketCode => $bundleChildList)
1984 {
1985// $tryShipmentBundle = false;
1986 foreach($bundleChildList as $bundleChildBasketCode)
1987 {
1988 if (!isset($resultList[$bundleChildBasketCode]))
1989 {
1990 if (!isset($resultList[$bundleParentBasketCode]))
1991 {
1992 $resultList[$bundleParentBasketCode] = new Result();
1993 }
1994
1995 $resultList[$bundleParentBasketCode]->addError(new ResultError('Bundle child item not found', 'SALE_PROVIDER_SHIPMENT_SHIPPED_BUNDLE_CHILD_ITEM_NOT_FOUND'));
1996 }
1997
1998 }
1999 }
2000
2001 }
2002
2003 if (!empty($resultList))
2004 {
2006 if (!$shipmentCollection = $shipment->getCollection())
2007 {
2008 throw new ObjectNotFoundException('Entity "ShipmentCollection" not found');
2009 }
2010
2012 if (!$order = $shipmentCollection->getOrder())
2013 {
2014 throw new ObjectNotFoundException('Entity "Order" not found');
2015 }
2016
2017 $hasErrors = false;
2018
2020 foreach ($shipmentItemCollection as $shipmentItem)
2021 {
2023 if(!$basketItem = $shipmentItem->getBasketItem())
2024 {
2025 throw new ObjectNotFoundException('Entity "BasketItem" not found');
2026 }
2027
2028 if (isset($resultList[$basketItem->getBasketCode()]) && !$resultList[$basketItem->getBasketCode()]->isSuccess())
2029 {
2030 $hasErrors = true;
2031 break;
2032 }
2033 }
2034
2035 if (!$hasErrors)
2036 {
2038 foreach ($shipmentItemCollection as $shipmentItem)
2039 {
2041 if(!$basketItem = $shipmentItem->getBasketItem())
2042 {
2043 throw new ObjectNotFoundException('Entity "BasketItem" not found');
2044 }
2045
2046 if (isset($resultList[$basketItem->getBasketCode()]) && $resultList[$basketItem->getBasketCode()]->isSuccess())
2047 {
2048 static::addQuantityPoolItem($order->getInternalId(), $basketItem, ($needShip? -1 : 1) * $shipmentItem->getQuantity());
2049
2050 if ($needShip)
2051 $shipmentItem->setFieldNoDemand("RESERVED_QUANTITY", 0);
2052
2053 }
2054 }
2055 }
2056
2057 $result->setData($resultList);
2058 }
2059
2060 return $result;
2061 }
2062
2069 public static function tryShipmentItemList($shipmentItemList)
2070 {
2071 $result = new Result();
2072
2073 $resultList = array();
2074 $bundleIndexList = static::getBundleIndexFromShipmentItemCollection($shipmentItemList);
2075
2077 {
2079 $r = static::getStoreDataFromShipmentItemCollection($shipmentItemList);
2080 if ($r->isSuccess())
2081 {
2082 $resultStoreData = $r->getData();
2083 if (!empty($resultStoreData['STORE_DATA_LIST']))
2084 {
2085 $storeDataList = $resultStoreData['STORE_DATA_LIST'];
2086 }
2087 }
2088 else
2089 {
2090 $result->addErrors($r->getErrors());
2091 }
2092
2093 }
2094
2095 $shipmentItemParentsList = array();
2096
2097 $tryShipProductList = array();
2098
2100 foreach ($shipmentItemList as $shipmentItem)
2101 {
2102 $itemIndex = $shipmentItem->getInternalIndex();
2103 $basketItem = $shipmentItem->getBasketItem();
2104 $providerName = $basketItem->getProviderName();
2105
2107 $shipmentItemCollection = $shipmentItem->getCollection();
2108 if (!$shipmentItemCollection)
2109 {
2110 throw new ObjectNotFoundException('Entity "ShipmentItemCollection" not found');
2111 }
2112
2114 $shipment = $shipmentItemCollection->getShipment();
2115 if (!$shipment)
2116 {
2117 throw new ObjectNotFoundException('Entity "Shipment" not found');
2118 }
2119
2120 $shipmentItemParentsList[$itemIndex] = array(
2121 'BASKET_ITEM' => $basketItem,
2122 'SHIPMENT' => $shipment,
2123 'SHIPMENT_ITEM_COLLECTION' => $shipmentItemCollection,
2124 );
2125
2126 $needShip = $shipment->needShip();
2127 if ($needShip === null)
2128 continue;
2129
2130
2131 if ($providerName && array_key_exists("IBXSaleProductProvider", class_implements($providerName)))
2132 {
2133 $basketItem = $shipmentItem->getBasketItem();
2134 if (!$basketItem)
2135 {
2136 throw new ObjectNotFoundException('Entity "BasketItem" not found');
2137 }
2138
2139 if ($basketItem->isBundleParent())
2140 {
2141 continue;
2142 }
2143
2144 $basketCode = $basketItem->getBasketCode();
2145 $quantity = $shipmentItem->getQuantity();
2146 $basketStoreData = array();
2147
2148 $resultProduct = new Result();
2149
2151 {
2152 if (!empty($storeDataList) && is_array($storeDataList)
2153 && isset($storeDataList[$basketCode]))
2154 {
2155 $basketStoreData = $storeDataList[$basketCode];
2156 }
2157
2158 if (!empty($basketStoreData))
2159 {
2160 $allBarcodeQuantity = 0;
2161 foreach($basketStoreData as $basketShipmentItemStore)
2162 {
2163 $allBarcodeQuantity += $basketShipmentItemStore['QUANTITY'];
2164 }
2165
2166 if ($quantity > $allBarcodeQuantity)
2167 {
2168 $resultProduct->addError(new ResultError(Loc::getMessage('SALE_PROVIDER_SHIPMENT_SHIPPED_LESS_QUANTITY', array(
2169 '#PRODUCT_NAME#' => $basketItem->getField('NAME')
2170 )), 'SALE_PROVIDER_SHIPMENT_SHIPPED_LESS_QUANTITY'));
2171 }
2172 elseif ($quantity < $allBarcodeQuantity)
2173 {
2174 $resultProduct->addError(new ResultError(Loc::getMessage('SALE_PROVIDER_SHIPMENT_SHIPPED_MORE_QUANTITY', array(
2175 '#PRODUCT_NAME#' => $basketItem->getField('NAME')
2176 )), 'SALE_PROVIDER_SHIPMENT_SHIPPED_MORE_QUANTITY'));
2177 }
2178 }
2179
2180 }
2181
2182 if ($resultProduct->isSuccess())
2183 {
2184
2185 if ($needShip === true)
2186 {
2187 if (method_exists($providerName, 'tryShipmentProduct'))
2188 {
2190 $resultProduct = $providerName::tryShipmentProduct($basketItem, $basketItem->getField('RESERVED'), $basketStoreData, $quantity);
2191 }
2192 }
2193 else
2194 {
2195 if (method_exists($providerName, 'tryUnshipmentProduct'))
2196 {
2198 $resultProduct = $providerName::tryUnshipmentProduct($basketItem->getProductId());
2199 }
2200 }
2201 }
2202
2203 $resultList[$basketCode] = $resultProduct;
2204
2205 }
2206 elseif ($providerName && class_exists($providerName))
2207 {
2209 $shipmentCollection = $shipment->getCollection();
2210 if (!$shipmentCollection)
2211 {
2212 throw new ObjectNotFoundException('Entity "ShipmentCollection" not found');
2213 }
2214
2216 $order = $shipmentCollection->getOrder();
2217 if (!$order)
2218 {
2219 throw new ObjectNotFoundException('Entity "Order" not found');
2220 }
2221
2222 $shipmentItemParentsList[$itemIndex]['SHIPMENT_COLLECTION'] = $shipmentCollection;
2223 $shipmentItemParentsList[$itemIndex]['ORDER'] = $order;
2224
2225 $pool = Internals\PoolQuantity::getInstance($order->getInternalId());
2226
2227 $context = array(
2228 'SITE_ID' => $order->getSiteId(),
2229 'CURRENCY' => $order->getCurrency(),
2230 );
2231
2232 if ($order->getUserId() > 0)
2233 {
2234 $context['USER_ID'] = $order->getUserId();
2235 }
2236 else
2237 {
2238 global $USER;
2239 $context['USER_ID'] = $USER->getId();
2240 }
2241
2242 $creator = Internals\ProviderCreator::create($context);
2243
2244 $shipmentProductData = $creator->createItemForShip($shipmentItem);
2245 $creator->addProductData($shipmentProductData);
2246
2247 $r = $creator->tryShip();
2248 if ($r->isSuccess())
2249 {
2250 if ($r->hasWarnings())
2251 {
2252 $result->addWarnings($r->getWarnings());
2253 }
2254 else
2255 {
2256 $data = $r->getData();
2257 if (array_key_exists('TRY_SHIP_PRODUCTS_LIST', $data))
2258 {
2259 $tryShipProductList = $data['TRY_SHIP_PRODUCTS_LIST'] + $tryShipProductList;
2260 $creator->setItemsResultAfterTryShip($pool, $tryShipProductList);
2261 }
2262 }
2263 }
2264 else
2265 {
2266 $result->addWarnings($r->getErrors());
2267 }
2268 }
2269 }
2270
2271 if (!empty($resultList)
2272 && !empty($bundleIndexList) && is_array($bundleIndexList))
2273 {
2274
2275 foreach ($bundleIndexList as $bundleParentBasketCode => $bundleChildList)
2276 {
2277 foreach($bundleChildList as $bundleChildBasketCode)
2278 {
2279 if (!isset($resultList[$bundleChildBasketCode]))
2280 {
2281 if (!isset($resultList[$bundleParentBasketCode]))
2282 {
2283 $resultList[$bundleParentBasketCode] = new Result();
2284 }
2285
2286 $resultList[$bundleParentBasketCode]->addError(new ResultError('Bundle child item not found', 'SALE_PROVIDER_SHIPMENT_SHIPPED_BUNDLE_CHILD_ITEM_NOT_FOUND'));
2287 }
2288
2289 }
2290 }
2291
2292 }
2293
2294 if (!empty($resultList))
2295 {
2296
2297 $hasErrors = false;
2298
2300 foreach ($shipmentItemList as $shipmentItem)
2301 {
2302 $itemIndex = $shipmentItem->getInternalIndex();
2303
2305 $basketItem = $shipmentItemParentsList[$itemIndex]['BASKET_ITEM'];
2306
2307 if (isset($resultList[$basketItem->getBasketCode()]) && !$resultList[$basketItem->getBasketCode()]->isSuccess())
2308 {
2309 $hasErrors = true;
2310 break;
2311 }
2312 }
2313
2314 if (!$hasErrors)
2315 {
2317 foreach ($shipmentItemList as $shipmentItem)
2318 {
2319 $itemIndex = $shipmentItem->getInternalIndex();
2320
2322 $basketItem = $shipmentItemParentsList[$itemIndex]['BASKET_ITEM'];
2323
2324 $productId = $shipmentItem->getProductId();
2325
2326 if (isset($resultList[$basketItem->getBasketCode()]) && $resultList[$basketItem->getBasketCode()]->isSuccess())
2327 {
2329 $shipment = $shipmentItemParentsList[$itemIndex]['SHIPMENT'];
2330
2332 $order = $shipmentItemParentsList[$itemIndex]['ORDER'];
2333
2334 if (!$order)
2335 {
2337 $shipmentCollection = $shipment->getCollection();
2338 if (!$shipmentCollection)
2339 {
2340 throw new ObjectNotFoundException('Entity "ShipmentCollection" not found');
2341 }
2342
2344 $order = $shipmentCollection->getOrder();
2345 if (!$order)
2346 {
2347 throw new ObjectNotFoundException('Entity "Order" not found');
2348 }
2349
2350 $shipmentItemParentsList[$itemIndex]['SHIPMENT_COLLECTION'] = $shipmentCollection;
2351 $shipmentItemParentsList[$itemIndex]['ORDER'] = $order;
2352 }
2353
2354 $needShip = $shipment->needShip();
2355
2356 static::addQuantityPoolItem($order->getInternalId(), $basketItem, ($needShip? -1 : 1) * $shipmentItem->getQuantity());
2357
2358 if ($needShip)
2359 {
2360 $shipmentItem->setFieldNoDemand("RESERVED_QUANTITY", 0);
2361 }
2362
2363
2364 $foundItem = false;
2365 $poolItems = Internals\ItemsPool::get($order->getInternalId(), $productId);
2366 if (!empty($poolItems))
2367 {
2369 foreach ($poolItems as $poolItem)
2370 {
2371 if ($poolItem->getInternalIndex() == $shipmentItem->getInternalIndex())
2372 {
2373 $foundItem = true;
2374 break;
2375 }
2376 }
2377 }
2378
2379 if (!$foundItem)
2380 {
2381 Internals\ItemsPool::add($order->getInternalId(), $productId, $shipmentItem);
2382 }
2383
2384 }
2385 }
2386 }
2387
2388 $result->setData($resultList);
2389 }
2390
2391 return $result;
2392 }
2393
2394
2400 protected static function getBundleIndexFromShipmentItemCollection($shipmentItemList)
2401 {
2402 $bundleIndexList = array();
2404 foreach ($shipmentItemList as $shipmentItem)
2405 {
2407 if (!$basketItem = $shipmentItem->getBasketItem())
2408 {
2409 continue;
2410 }
2411
2412
2413 if ($basketItem->isBundleChild())
2414 {
2416 $parentBasketItem = $basketItem->getParentBasketItem();
2417 $parentBasketCode = $parentBasketItem->getBasketCode();
2418
2419 if (!array_key_exists($parentBasketCode, $bundleIndexList))
2420 {
2421 $bundleIndexList[$parentBasketCode] = array();
2422 }
2423
2424 $bundleIndexList[$parentBasketCode][] = $basketItem->getBasketCode();
2425 }
2426 }
2427
2428 return $bundleIndexList;
2429 }
2430
2437 protected static function getBasketFromShipmentItemCollection($shipmentItemList)
2438 {
2439
2440 $basketList = array();
2442 foreach ($shipmentItemList as $shipmentItem)
2443 {
2444
2446 if (!$basketItem = $shipmentItem->getBasketItem())
2447 {
2448 continue;
2449 }
2450
2452 $shipmentItemCollection = $shipmentItem->getCollection();
2453 if (!$shipmentItemCollection)
2454 {
2455 throw new ObjectNotFoundException('Entity "ShipmentItemCollection" not found');
2456 }
2457
2459 $shipment = $shipmentItemCollection->getShipment();
2460
2461 if (!$shipment)
2462 {
2463 throw new ObjectNotFoundException('Entity "Shipment" not found');
2464 }
2465
2466 $needShip = $shipment->needShip();
2467 if ($needShip === null)
2468 {
2469 continue;
2470 }
2471
2472 $reserved = ((($shipmentItem->getQuantity() - $shipmentItem->getReservedQuantity()) == 0)
2473 || ($shipment->getField('RESERVED') == "Y"));
2474
2475 if ($basketItem->isBundleParent()
2476 || (!$basketItem->isBundleParent() && !$basketItem->isBundleChild()))
2477 {
2478
2479 $basketList[$basketItem->getBasketCode()] = array(
2480 'BASKET_ITEM' => $basketItem,
2481 'RESERVED' => ($reserved ? "Y" : "N"),
2482 'NEED_SHIP' => $needShip,
2483 'SHIPMENT_ITEM' => $shipmentItem
2484 );
2485 }
2486
2487 if($basketItem->isBundleParent())
2488 {
2490 foreach ($shipmentItemCollection as $bundleShipmentItem)
2491 {
2493 $bundleBasketItem = $bundleShipmentItem->getBasketItem();
2494
2495 if($bundleBasketItem->isBundleChild())
2496 {
2497 $bundleParentBasketItem = $bundleBasketItem->getParentBasketItem();
2498 if ($bundleParentBasketItem->getBasketCode() == $basketItem->getBasketCode())
2499 {
2500
2501 $basketList[$bundleBasketItem->getBasketCode()] = array(
2502 'BASKET_ITEM' => $bundleBasketItem,
2503 'RESERVED' => ($reserved ? "Y" : "N"),
2504 'NEED_SHIP' => $needShip,
2505 'SHIPMENT_ITEM' => $shipmentItem
2506 );
2507 }
2508 }
2509 }
2510 }
2511
2512
2513 }
2514
2515 return $basketList;
2516 }
2517
2524 protected static function getBasketCountFromShipmentItemCollection($shipmentItemList)
2525 {
2526
2527 $basketCountList = array();
2529 foreach ($shipmentItemList as $shipmentItem)
2530 {
2531
2533 if (!$basketItem = $shipmentItem->getBasketItem())
2534 {
2535 continue;
2536 }
2537
2538 if ($basketItem->isBundleParent()
2539 || (!$basketItem->isBundleParent() && !$basketItem->isBundleChild()))
2540 {
2541 $basketCountList[$basketItem->getBasketCode()] = floatval($shipmentItem->getQuantity());
2542 }
2543
2544
2545 if($basketItem->isBundleParent())
2546 {
2548 foreach ($shipmentItemList as $bundleShipmentItem)
2549 {
2551 $bundleBasketItem = $bundleShipmentItem->getBasketItem();
2552
2553 if($bundleBasketItem->isBundleChild())
2554 {
2555 $bundleParentBasketItem = $bundleBasketItem->getParentBasketItem();
2556 if ($bundleParentBasketItem->getBasketCode() == $basketItem->getBasketCode())
2557 {
2558 $basketCountList[$bundleBasketItem->getBasketCode()] = floatval($bundleShipmentItem->getQuantity());
2559 }
2560 }
2561 }
2562 }
2563
2564 }
2565
2566 return $basketCountList;
2567 }
2568
2574 protected static function getStoreDataFromShipmentItemCollection($shipmentItemList)
2575 {
2576 $result = new Result();
2577 $list = Internals\Catalog\Provider::createMapShipmentItemCollectionStoreData($shipmentItemList);
2578 if (!empty($list))
2579 {
2580 $result->setData(array(
2581 'STORE_DATA_LIST' => $list
2582 ));
2583 }
2584 return $result;
2585 }
2586
2593 protected static function makeArrayFromBasketCollection(BasketItemCollection $basketCollection, BasketItem $refreshItem = null)
2594 {
2595 $basketList = array();
2597 foreach ($basketCollection as $basketItem)
2598 {
2599 if ($refreshItem !== null)
2600 {
2601
2602 if ($basketItem->getBasketCode() != $refreshItem->getBasketCode() && $basketItem->isBundleParent())
2603 {
2604 if ($bundleCollection = $basketItem->getBundleCollection())
2605 {
2606 $foundItem = false;
2608 foreach ($bundleCollection as $bundleBasketItem)
2609 {
2610 if ($bundleBasketItem->getBasketCode() == $refreshItem->getBasketCode())
2611 {
2612 $foundItem = true;
2613 break;
2614 }
2615 }
2616
2617 if (!$foundItem)
2618 continue;
2619
2620 $basketList[] = $bundleBasketItem;
2621 continue;
2622 }
2623 }
2624 elseif ($basketItem->getBasketCode() != $refreshItem->getBasketCode())
2625 {
2626 continue;
2627 }
2628
2629 $basketList[] = $basketItem;
2630
2631 continue;
2632 }
2633
2634 $basketList[] = $basketItem;
2635
2636 }
2637
2638 return $basketList;
2639 }
2640
2647 public static function tryReserveShipment(Shipment $shipment)
2648 {
2649 $result = new Result();
2650
2652 $shipmentItemCollection = $shipment->getShipmentItemCollection();
2653
2654 $shipmentItemList = $shipmentItemCollection->getShippableItems();
2656 foreach ($shipmentItemList as $shipmentItem)
2657 {
2658 try
2659 {
2661 $r = static::tryReserveShipmentItem($shipmentItem);
2662 if (!$r->isSuccess())
2663 {
2664 $result->addErrors($r->getErrors());
2665 }
2666 elseif ($r->hasWarnings())
2667 {
2668 $result->addWarnings($r->getWarnings());
2669 }
2670 }
2671 catch(\Exception $e)
2672 {
2674 if (!$shipment = $shipmentItemCollection->getShipment())
2675 {
2676 throw new ObjectNotFoundException('Entity "Shipment" not found');
2677 }
2678 else
2679 {
2680 throw new $e;
2681 }
2682
2683 }
2684
2685 }
2686
2687 return $result;
2688 }
2689
2696 public static function tryUnreserveShipment(Shipment $shipment)
2697 {
2698 $result = new Result();
2700 if (!$shipmentItemCollection = $shipment->getShipmentItemCollection())
2701 {
2702 throw new ObjectNotFoundException('Entity "ShipmentItemCollection" not found');
2703 }
2704
2706 if (!($shipmentCollection = $shipment->getCollection()))
2707 {
2708 throw new ObjectNotFoundException('Entity "ShipmentCollection" not found');
2709 }
2710
2712 if (!($order = $shipmentCollection->getOrder()))
2713 {
2714 throw new ObjectNotFoundException('Entity "Order" not found');
2715 }
2716
2718 foreach ($shipmentItemCollection as $shipmentItem)
2719 {
2721 $r = static::tryUnreserveShipmentItem($shipmentItem);
2722 if (!$r->isSuccess())
2723 {
2724 $result->addErrors($r->getErrors());
2725 EntityMarker::addMarker($order, $shipment, $r);
2726 if (!$shipment->isSystem())
2727 {
2728 $shipment->setField('MARKED', 'Y');
2729 }
2730 }
2731 elseif ($r->hasWarnings())
2732 {
2733 $result->addWarnings($r->getWarnings());
2734 }
2735 }
2736
2737 return $result;
2738 }
2739
2747 public static function tryReserveShipmentItem(ShipmentItem $shipmentItem)
2748 {
2749 $result = new Result();
2750
2751 if (floatval($shipmentItem->getQuantity()) == floatval($shipmentItem->getReservedQuantity()))
2752 {
2753 return $result;
2754 }
2755
2757 if (!$shipmentItemCollection = $shipmentItem->getCollection())
2758 {
2759 throw new ObjectNotFoundException('Entity "ShipmentItemCollection" not found');
2760 }
2761
2763 if (!$shipment = $shipmentItemCollection->getShipment())
2764 {
2765 throw new ObjectNotFoundException('Entity "Shipment" not found');
2766 }
2768 if (!$shipmentCollection = $shipment->getCollection())
2769 {
2770 throw new ObjectNotFoundException('Entity "ShipmentCollection" not found');
2771 }
2772
2774 if (!$order = $shipmentCollection->getOrder())
2775 {
2776 throw new ObjectNotFoundException('Entity "Order" not found');
2777 }
2778
2780 if (!$basketItem = $shipmentItem->getBasketItem())
2781 {
2782 $result->addError(new ResultError(
2784 'SALE_PROVIDER_BASKET_ITEM_NOT_FOUND',
2785 [
2786 '#BASKET_ITEM_ID#' => $shipmentItem->getBasketId(),
2787 '#SHIPMENT_ID#' => $shipment->getId(),
2788 '#SHIPMENT_ITEM_ID#' => $shipmentItem->getId(),
2789 ]
2790 ),
2791 'PROVIDER_RESERVE_SHIPMENT_ITEM_WRONG_BASKET_ITEM')
2792 );
2793
2794 return $result;
2795 }
2796
2797 if ($basketItem->isBundleParent())
2798 {
2799 return $result;
2800 }
2801
2802 $needQuantity = ($shipmentItem->getQuantity() - $shipmentItem->getReservedQuantity());
2803 $canReserve = false;
2804
2805 $providerName = $basketItem->getProvider();
2806
2807 if (class_exists($providerName))
2808 {
2809 if (empty($context))
2810 {
2811 if ($order)
2812 {
2813 $context = array(
2814 'USER_ID' => $order->getUserId(),
2815 'SITE_ID' => $order->getSiteId(),
2816 'CURRENCY' => $order->getCurrency(),
2817 );
2818 }
2819 else
2820 {
2821 global $USER;
2822 $context = array(
2823 'USER_ID' => $USER->getId(),
2824 'SITE_ID' => SITE_ID,
2825 'CURRENCY' => Currency\CurrencyManager::getBaseCurrency(),
2826 );
2827 }
2828 }
2829
2830 $availableQuantityData = array();
2831
2832 $providerClass = new $providerName($context);
2833 if ($providerClass instanceof SaleProviderBase)
2834 {
2835 $creator = Internals\ProviderCreator::create($context);
2836 $shipmentProductData = $creator->createItemForReserveByShipmentItem($shipmentItem);
2837 $creator->addProductData($shipmentProductData);
2838
2839 $r = $creator->getAvailableQuantity();
2840 if ($r->isSuccess())
2841 {
2842 $resultData = $r->getData();
2843 if (!empty($resultData['AVAILABLE_QUANTITY_LIST']))
2844 {
2845 $productId = $basketItem->getProductId();
2846
2847 $resultAvailableQuantityList = $resultData['AVAILABLE_QUANTITY_LIST'];
2848 if (mb_substr($providerName, 0, 1) == "\\")
2849 {
2850 $providerName = mb_substr($providerName, 1);
2851 }
2852
2853 if (isset($resultAvailableQuantityList[$providerName]) && isset($resultAvailableQuantityList[$providerName][$productId]))
2854 {
2855 $availableQuantityData = array(
2856 'HAS_PROVIDER' => true,
2857 'AVAILABLE_QUANTITY' => $resultAvailableQuantityList[$providerName][$productId]
2858 );
2859 }
2860 }
2861
2862 }
2863 else
2864 {
2865 $result->addErrors($r->getErrors());
2866 return $result;
2867 }
2868 }
2869 else
2870 {
2872 $r = static::tryReserveBasketItem($basketItem, $needQuantity);
2873
2874 $availableQuantityData = $r->getData();
2875 }
2876 }
2877 else
2878 {
2880 $r = static::tryReserveBasketItem($basketItem, $needQuantity);
2881
2882 $availableQuantityData = $r->getData();
2883 }
2884
2885 if (!$r->isSuccess())
2886 {
2887 $result->addErrors($r->getErrors());
2888 return $result;
2889 }
2890 elseif ($r->hasWarnings())
2891 {
2892 $result->addWarnings($r->getWarnings());
2893 return $result;
2894 }
2895
2896 if (array_key_exists('AVAILABLE_QUANTITY', $availableQuantityData))
2897 {
2898 $availableQuantity = $availableQuantityData['AVAILABLE_QUANTITY'];
2899 }
2900 else
2901 {
2902 $result->addWarning( new ResultWarning(Loc::getMessage('SALE_PROVIDER_RESERVE_SHIPMENT_ITEM_WRONG_AVAILABLE_QUANTITY', array(
2903 '#PRODUCT_NAME#' => $basketItem->getField('NAME')
2904 )), 'SALE_PROVIDER_RESERVE_SHIPMENT_ITEM_WRONG_AVAILABLE_QUANTITY') );
2905 return $result;
2906 }
2907
2908 if (array_key_exists('HAS_PROVIDER', $availableQuantityData))
2909 {
2910 $canReserve = $availableQuantityData['HAS_PROVIDER'];
2911 }
2912
2913 if ($canReserve && array_key_exists('QUANTITY_TRACE', $availableQuantityData))
2914 {
2915 $canReserve = $availableQuantityData['QUANTITY_TRACE'];
2916 }
2917
2918 if ($canReserve)
2919 {
2920 if ($r->isSuccess() && ($needQuantity > 0) && ($needQuantity > $availableQuantity)
2921 /*|| ($needReserved < 0) && ($availableQuantity < $needReserved) */)
2922 {
2923 $result->addWarning(new ResultWarning(Loc::getMessage("SALE_PROVIDER_RESERVE_SHIPMENT_ITEM_QUANTITY_NOT_ENOUGH", array(
2924 '#PRODUCT_NAME#' => $basketItem->getField('NAME')
2925 )), "SALE_PROVIDER_RESERVE_SHIPMENT_ITEM_QUANTITY_NOT_ENOUGH"));
2926 return $result;
2927 }
2928
2929 // is not completely correct, but will be processed in real reservations while saving
2930 if (($availableQuantity < 0) && ($shipmentItem->getReservedQuantity() + $availableQuantity < 0))
2931 {
2932 $availableQuantity = -1 * $shipmentItem->getReservedQuantity();
2933 }
2934
2935 if (Configuration::getProductReservationCondition() != ReserveCondition::ON_SHIP)
2936 {
2937
2938 $reservedQuantity = ($availableQuantity >= $needQuantity ? $needQuantity : $availableQuantity);
2939
2940 static::addReservationPoolItem($order->getInternalId(), $shipmentItem->getBasketItem(), $reservedQuantity);
2941
2942 $r = $shipmentItem->setField('RESERVED_QUANTITY', $shipmentItem->getReservedQuantity() + $reservedQuantity);
2943 if (!$r->isSuccess())
2944 {
2945 $result->addErrors($r->getErrors());
2946 }
2947 }
2948 }
2949
2950 $result->addData([
2951 'CAN_RESERVE' => $canReserve,
2952 ]);
2953
2954 return $result;
2955 }
2956
2967 public static function tryUnreserveShipmentItem(ShipmentItem $shipmentItem)
2968 {
2969 $result = new Result();
2970
2972 if (!$shipmentItemCollection = $shipmentItem->getCollection())
2973 {
2974 throw new ObjectNotFoundException('Entity "ShipmentItemCollection" not found');
2975 }
2976
2978 if (!$shipment = $shipmentItemCollection->getShipment())
2979 {
2980 throw new ObjectNotFoundException('Entity "Shipment" not found');
2981 }
2982
2984 if (!$shipmentCollection = $shipment->getCollection())
2985 {
2986 throw new ObjectNotFoundException('Entity "ShipmentCollection" not found');
2987 }
2988
2990 if (!$order = $shipmentCollection->getOrder())
2991 {
2992 throw new ObjectNotFoundException('Entity "Order" not found');
2993 }
2994
2996 if (!$basketItem = $shipmentItem->getBasketItem())
2997 {
2998 $result->addError(new ResultError(
3000 'SALE_PROVIDER_BASKET_ITEM_NOT_FOUND',
3001 [
3002 '#BASKET_ITEM_ID#' => $shipmentItem->getBasketId(),
3003 '#SHIPMENT_ID#' => $shipment->getId(),
3004 '#SHIPMENT_ITEM_ID#' => $shipmentItem->getId(),
3005 ]
3006 ),
3007 'PROVIDER_TRY_UNRESERVED_SHIPMENT_ITEM_WRONG_BASKET_ITEM')
3008 );
3009
3010 return $result;
3011 }
3012
3013 if ($basketItem->isBundleParent())
3014 {
3015 return $result;
3016 }
3017
3018 $quantity = $shipmentItem->getReservedQuantity();
3019
3020 $canReserve = false;
3021
3022 $providerName = $basketItem->getProvider();
3023
3024 $providerExists = false;
3025 $availableQuantityData = array(
3026 'HAS_PROVIDER' => true,
3027 'AVAILABLE_QUANTITY' => $quantity
3028 );
3029
3030 if (class_exists($providerName))
3031 {
3032 $providerClass = new $providerName();
3033 if ($providerClass instanceof SaleProviderBase)
3034 {
3035 $providerExists = true;
3036 }
3037 }
3038
3039 if (!$providerExists)
3040 {
3041 if (!array_key_exists("IBXSaleProductProvider", class_implements($providerName)))
3042 {
3043 $availableQuantityData['HAS_PROVIDER'] = false;
3044 }
3045 }
3046
3047 if (array_key_exists('HAS_PROVIDER', $availableQuantityData))
3048 {
3049 $canReserve = $availableQuantityData['HAS_PROVIDER'];
3050 }
3051
3052 if ($canReserve)
3053 {
3054
3055 static::addReservationPoolItem($order->getInternalId(), $shipmentItem->getBasketItem(), $quantity);
3056
3057 $reservedQuantity = ($shipmentItem->getReservedQuantity() > 0 ? $shipmentItem->getReservedQuantity() + $quantity : 0);
3058
3059 $needShip = $shipment->needShip();
3060 if ($needShip)
3061 {
3062 $shipmentItem->setFieldNoDemand('RESERVED_QUANTITY', $reservedQuantity);
3063 }
3064 else
3065 {
3066 $r = $shipmentItem->setField('RESERVED_QUANTITY', $reservedQuantity);
3067 if (!$r->isSuccess())
3068 {
3069 $result->addErrors($r->getErrors());
3070 }
3071 }
3072 }
3073
3074 $result->addData([
3075 'CAN_RESERVE' => $canReserve,
3076 ]);
3077
3078 return $result;
3079 }
3080
3087 protected static function tryReserveBasketItem(BasketItem $basketItem, $quantity)
3088 {
3089 $result = new Result();
3090
3091 $provider = $basketItem->getProvider();
3092
3093 if (!$basketItem->isBundleChild())
3094 {
3096 $basket = $basketItem->getCollection();
3097 }
3098 else
3099 {
3101 $parentBasketItem = $basketItem->getParentBasketItem();
3102
3104 $basket = $parentBasketItem->getCollection();
3105 }
3106
3107 $order = $basket->getOrder();
3108 $hasProvider = false;
3109 $quantityTrace = null;
3110
3111 $poolQuantity = static::getReservationPoolItem($order->getInternalId(), $basketItem);
3112 $tryQuantity = $quantity + $poolQuantity;
3113
3114 if ($provider && array_key_exists("IBXSaleProductProvider", class_implements($provider)))
3115 {
3116 $hasProvider = true;
3117 $r = static::checkAvailableProductQuantity($basketItem, $tryQuantity);
3118
3119 $availableQuantityData = $r->getData();
3120 if (array_key_exists('AVAILABLE_QUANTITY', $availableQuantityData))
3121 {
3122 $availableQuantity = floatval($availableQuantityData['AVAILABLE_QUANTITY']);
3123 }
3124 else
3125 {
3126 $result->addWarning(new ResultWarning(Loc::getMessage('SALE_PROVIDER_BASKET_ITEM_WRONG_AVAILABLE_QUANTITY', array(
3127 '#PRODUCT_NAME#' => $basketItem->getField('NAME')
3128 )), 'PROVIDER_BASKET_ITEM_WRONG_AVAILABLE_QUANTITY'));
3129 return $result;
3130 }
3131
3132 if (array_key_exists('QUANTITY_TRACE', $availableQuantityData))
3133 {
3134 $quantityTrace = $availableQuantityData['QUANTITY_TRACE'];
3135 }
3136
3137 if (!$r->isSuccess())
3138 {
3139 $result->addErrors($r->getErrors());
3140 }
3141 elseif ($r->hasWarnings())
3142 {
3143 $result->addWarnings($r->getWarnings());
3144 }
3145
3146 $availableQuantity -= floatval($poolQuantity);
3147 }
3148 else
3149 {
3150 $availableQuantity = $quantity;
3151 }
3152
3153 $fields = array(
3154 'AVAILABLE_QUANTITY' => $availableQuantity,
3155 'HAS_PROVIDER' => $hasProvider,
3156 );
3157
3158 if ($quantityTrace !== null)
3159 {
3160 $fields['QUANTITY_TRACE'] = $quantityTrace;
3161 }
3162
3163 $result->setData($fields);
3164 return $result;
3165 }
3166
3167
3175 private static function reserveBasketItem(BasketItem $basketItem, $quantity)
3176 {
3177 $result = new Result();
3178
3179 $provider = $basketItem->getProvider();
3180
3182 if (!$basket = $basketItem->getCollection())
3183 {
3184 throw new ObjectNotFoundException('Entity "Basket" not found');
3185 }
3186
3188 if (!$order = $basket->getOrder())
3189 {
3190 throw new ObjectNotFoundException('Entity "Order" not found');
3191 }
3192
3193 $r = static::reserveProduct($provider, $basketItem->getProductId(), $quantity);
3194
3195 if ($r->hasWarnings() || !$r->isSuccess())
3196 {
3197 if (!$r->isSuccess())
3198 {
3199 $result->addWarnings($r->getErrors());
3200 }
3201
3202 if ($r->hasWarnings())
3203 {
3204 $result->addWarnings($r->getWarnings());
3205 }
3206
3208 if (!$basket = $basketItem->getCollection())
3209 {
3210 throw new ObjectNotFoundException('Entity "Basket" not found');
3211 }
3212
3213 if ($order = $basket->getOrder())
3214 {
3216 if (!$shipmentCollection = $order->getShipmentCollection())
3217 {
3218 throw new ObjectNotFoundException('Entity "ShipmentCollection" not found');
3219 }
3220
3222 foreach ($shipmentCollection as $shipment)
3223 {
3225 if (!$shipmentItemCollection = $shipment->getShipmentItemCollection())
3226 {
3227 throw new ObjectNotFoundException('Entity "ShipmentItemCollection" not found');
3228 }
3229
3230 if($shipmentItemCollection->getItemByBasketCode($basketItem->getBasketCode()))
3231 {
3232 EntityMarker::addMarker($order, $shipment, $result);
3233 if (!$shipment->isSystem())
3234 {
3235 $shipment->setField('MARKED', 'Y');
3236 }
3237 }
3238 }
3239 }
3240 }
3241
3242 return $result;
3243 }
3244
3253 public static function reserveProduct($provider, $productId, $quantity)
3254 {
3255 global $APPLICATION;
3256
3257 $result = new Result();
3258 $fields = array();
3259
3260 if ($provider && array_key_exists("IBXSaleProductProvider", class_implements($provider)))
3261 {
3262 $hasProvider = true;
3263 $data = array("PRODUCT_ID" => $productId);
3264
3265 if ($quantity > 0)
3266 {
3267 $data["UNDO_RESERVATION"] = "N";
3268 $data["QUANTITY_ADD"] = $quantity;
3269 }
3270 else
3271 {
3272 $data["UNDO_RESERVATION"] = "Y";
3273 $data["QUANTITY_ADD"] = abs($quantity);
3274 }
3275
3276 $APPLICATION->ResetException();
3277 if (($resultReserveData = $provider::ReserveProduct($data)))
3278 {
3279 if ($resultReserveData['RESULT'])
3280 {
3281 $fields['QUANTITY'] = $resultReserveData['QUANTITY_RESERVED'];
3282
3283 if ($quantity < 0)
3284 {
3285 $fields['QUANTITY'] = $quantity;
3286 }
3287
3288 $fields['HAS_PROVIDER'] = $hasProvider;
3289 $result->setData($fields);
3290 $exception = $APPLICATION->GetException();
3291 if ($exception)
3292 {
3293 $result->addWarning(new ResultWarning($exception->GetString(), $exception->GetID()));
3294 }
3295 return $result;
3296 }
3297 else
3298 {
3299 $exception = $APPLICATION->GetException();
3300 if ($exception)
3301 {
3302 $result->addWarning(new ResultWarning($exception->GetString(), $exception->GetID()));
3303 }
3304 else
3305 {
3306 $result->addError(new ResultError(Loc::getMessage('SALE_PROVIDER_RESERVE_BASKET_ITEM_ERROR'), 'SALE_PROVIDER_RESERVE_BASKET_ITEM_ERROR')) ;
3307 }
3308 }
3309
3310 }
3311 else
3312 {
3313 $result->addError(new ResultError(Loc::getMessage('SALE_PROVIDER_RESERVE_BASKET_ITEM_ERROR'), 'SALE_PROVIDER_RESERVE_BASKET_ITEM_ERROR')) ;
3314 }
3315
3316 }
3317 else
3318 {
3319 $fields['QUANTITY'] = $quantity;
3320 $result->setData($fields);
3321 }
3322
3323 return $result;
3324 }
3325
3334 public static function reserveShipmentItem(ShipmentItem $shipmentItem, $quantity)
3335 {
3336 global $APPLICATION;
3337 $result = new Result();
3338 $fields = array();
3339
3341 $shipmentItemCollection = $shipmentItem->getCollection();
3342 if (!$shipmentItemCollection)
3343 {
3344 throw new ObjectNotFoundException('Entity "ShipmentItemCollection" not found');
3345 }
3346
3348 $shipment = $shipmentItemCollection->getShipment();
3349 if (!$shipment)
3350 {
3351 throw new ObjectNotFoundException('Entity "Shipment" not found');
3352 }
3353
3355 $basketItem = $shipmentItem->getBasketItem();
3356 if (!$basketItem)
3357 {
3358 $result->addError(new ResultError(
3360 'SALE_PROVIDER_BASKET_ITEM_NOT_FOUND',
3361 array(
3362 '#BASKET_ITEM_ID#' => $shipmentItem->getBasketId(),
3363 '#SHIPMENT_ID#' => $shipment->getId(),
3364 '#SHIPMENT_ITEM_ID#' => $shipmentItem->getId(),
3365 )
3366 ),
3367 'PROVIDER_RESERVE_SHIPMENT_ITEM_WRONG_BASKET_ITEM')
3368 );
3369
3370 return $result;
3371 }
3372
3373 $provider = $basketItem->getProvider();
3374
3375 if ($provider && array_key_exists("IBXSaleProductProvider", class_implements($provider)))
3376 {
3377 $data = array(
3378 "PRODUCT_ID" => $basketItem->getProductId(),
3379 "UNDO_RESERVATION" => "N",
3380 "QUANTITY_ADD" => $quantity,
3381 "ORDER_DEDUCTED" => $shipment->isShipped()? "Y" : "N",
3382 );
3383
3384 $APPLICATION->ResetException();
3385 if (($resultReserveData = $provider::ReserveProduct($data)))
3386 {
3387 if ($resultReserveData['RESULT'])
3388 {
3389 $fields['QUANTITY'] = $resultReserveData['QUANTITY_RESERVED'];
3390
3391 if (isset($resultReserveData['QUANTITY_NOT_RESERVED']) && floatval($resultReserveData['QUANTITY_NOT_RESERVED']) > 0)
3392 {
3393 $fields['QUANTITY'] = $shipmentItem->getReservedQuantity() + ($shipmentItem->getQuantity() - $shipmentItem->getReservedQuantity()) - $resultReserveData['QUANTITY_NOT_RESERVED'];
3394 }
3395
3396 $result->setData($fields);
3397 return $result;
3398 }
3399 else
3400 {
3401 if ($ex = $APPLICATION->GetException())
3402 {
3403 if ($ex->GetID() != "ALREADY_FLAG")
3404 $result->addError(new ResultError($ex->GetString())) ;
3405 }
3406 else
3407 {
3408 $result->addError(new ResultError(Loc::getMessage('SALE_PROVIDER_RESERVE_BASKET_ITEM_ERROR'), 'SALE_PROVIDER_RESERVE_BASKET_ITEM_ERROR')) ;
3409 }
3410 }
3411
3412 }
3413
3414 }
3415 elseif (class_exists($provider))
3416 {
3418 $shipmentCollection = $shipment->getCollection();
3419 if (!$shipmentCollection)
3420 {
3421 throw new ObjectNotFoundException('Entity "ShipmentCollection" not found');
3422 }
3423
3425 $order = $shipmentCollection->getOrder();
3426 if (!$order)
3427 {
3428 throw new ObjectNotFoundException('Entity "Order" not found');
3429 }
3430
3431 $context = array(
3432 'SITE_ID' => $order->getSiteId(),
3433 'CURRENCY' => $order->getCurrency(),
3434 );
3435
3436 if ($order->getUserId() > 0)
3437 {
3438 $context['USER_ID'] = $order->getUserId();
3439 }
3440 else
3441 {
3442 global $USER;
3443 $context['USER_ID'] = $USER->getId();
3444 }
3445
3447 $providerClass = new $provider($context);
3448 if ($providerClass && $providerClass instanceof SaleProviderBase)
3449 {
3450
3451 $creator = Internals\ProviderCreator::create($context);
3452 $creator->addShipmentItem($shipmentItem);
3453
3454 $r = $creator->reserve();
3455 if (!$r->isSuccess())
3456 {
3457 $result->addErrors($r->getErrors());
3458 }
3459
3460 }
3461 }
3462
3463 if (!empty($fields))
3464 {
3465 $result->setData($fields);
3466 }
3467 return $result;
3468 }
3469
3477 public static function reduceProductQuantity(ShipmentCollection $shipmentCollection, array $shipmentReserveList = array())
3478 {
3480 if (!$order = $shipmentCollection->getOrder())
3481 {
3482 throw new ObjectNotFoundException('Entity "Order" not found');
3483 }
3484
3485 $options = array(
3486 'ORDER_DEDUCTED' => $order->isShipped()
3487 );
3488
3489 $shipmentReserveListKeys = array_keys($shipmentReserveList);
3490
3491 foreach ($shipmentCollection as $shipmentKey => $shipment)
3492 {
3493 if (!in_array($shipment->getId(), $shipmentReserveListKeys))
3494 {
3495 unset($shipmentCollection[$shipmentKey]);
3496 }
3497 }
3498
3499
3500 foreach ($shipmentCollection as $shipment)
3501 {
3502 $basketProviderList = static::getProviderBasketFromShipment($shipment);
3503
3504 $productList = static::getProductListFromBasketProviderList($basketProviderList);
3505
3506 if (!empty($basketProviderList))
3507 {
3508 foreach ($basketProviderList as $provider => $providerBasketItemList)
3509 {
3510 $shipmentReserveListData = array();
3511 if (!empty($shipmentReserveList)
3512 && !empty($shipmentReserveList[$shipment->getId()]) && is_array($shipmentReserveList[$shipment->getId()]))
3513 {
3514 $shipmentReserveListData = $shipmentReserveList[$shipment->getId()];
3515 }
3516
3517 $result = $provider::reduceProductQuantity($providerBasketItemList, $productList, $shipmentReserveListData, $options);
3518 }
3519 }
3520
3521 }
3522 }
3523
3531 public static function increaseProductQuantity(ShipmentCollection $shipmentCollection, array $shipmentReserveList = array())
3532 {
3534 if (!$order = $shipmentCollection->getOrder())
3535 {
3536 throw new ObjectNotFoundException('Entity "Order" not found');
3537 }
3538
3539 $options = array(
3540 'ORDER_DEDUCTED' => $order->isShipped()
3541 );
3542
3543 $shipmentReserveListKeys = array_keys($shipmentReserveList);
3544
3545 foreach ($shipmentCollection as $shipmentKey => $shipment)
3546 {
3547 if (!in_array($shipment->getId(), $shipmentReserveListKeys))
3548 {
3549 unset($shipmentCollection[$shipmentKey]);
3550 }
3551 }
3552
3553
3554 foreach ($shipmentCollection as $shipment)
3555 {
3556 $basketProviderList = static::getProviderBasketFromShipment($shipment);
3557
3558 $productList = static::getProductListFromBasketProviderList($basketProviderList);
3559
3560 if (!empty($basketProviderList))
3561 {
3562 foreach ($basketProviderList as $provider => $providerBasketItemList)
3563 {
3564 $shipmentReserveListData = array();
3565 if (!empty($shipmentReserveList)
3566 && !empty($shipmentReserveList[$shipment->getId()]) && is_array($shipmentReserveList[$shipment->getId()]))
3567 {
3568 $shipmentReserveListData = $shipmentReserveList[$shipment->getId()];
3569 }
3570
3571 $result = $provider::increaseProductQuantity($providerBasketItemList, $productList, $shipmentReserveListData, $options);
3572 }
3573 }
3574
3575 }
3576 }
3577
3584 public static function getProductStores(BasketItem $basketItem)
3585 {
3586 $result = new Result();
3587
3588 $basketItemProviderMap = static::createProviderBasketItemMap($basketItem, array('SITE_ID'));
3589
3590 if (!empty($basketItemProviderMap))
3591 {
3592 $provider = $basketItemProviderMap['PROVIDER'];
3593
3594 if (array_key_exists("IBXSaleProductProvider", class_implements($provider)))
3595 {
3596 $productId = $basketItemProviderMap["PRODUCT_ID"];
3597 $data = array(
3598 "PRODUCT_ID" => $productId,
3599 "SITE_ID" => $basketItemProviderMap["SITE_ID"],
3600 'BASKET_ID' => $basketItemProviderMap['BASKET_ID']
3601 );
3602
3603 $r = static::getStores($provider, $data);
3604 if ($r->isSuccess())
3605 {
3606 $resultProductData = $r->getData();
3607 if (array_key_exists($productId, $resultProductData))
3608 {
3609 $result->setData($resultProductData);
3610 }
3611 }
3612
3613 }
3614 elseif (class_exists($provider))
3615 {
3617 $basket = $basketItem->getCollection();
3618 if (!$basket)
3619 {
3620 throw new ObjectNotFoundException('Entity "Basket" not found');
3621 }
3622
3624 $order = $basket->getOrder();
3625 if (!$order)
3626 {
3627 throw new ObjectNotFoundException('Entity "Order" not found');
3628 }
3629
3630 $context = array(
3631 'SITE_ID' => $order->getSiteId(),
3632 'CURRENCY' => $order->getCurrency(),
3633 );
3634
3635 if ($order->getUserId() > 0)
3636 {
3637 $context['USER_ID'] = $order->getUserId();
3638 }
3639 else
3640 {
3641 global $USER;
3642 $context['USER_ID'] = $USER->getId();
3643 }
3644
3646 $providerClass = new $provider($context);
3647 if ($providerClass && $providerClass instanceof SaleProviderBase)
3648 {
3649
3650 $creator = Internals\ProviderCreator::create($context);
3651 $creator->addBasketItem($basketItem);
3652
3653 $r = $creator->getProductStores();
3654 if ($r->isSuccess())
3655 {
3656 $result->setData($r->getData());
3657 }
3658 else
3659 {
3660 $result->addErrors($r->getErrors());
3661 }
3662
3663 }
3664 }
3665 }
3666
3667 return $result;
3668 }
3669
3677 public static function getStores($provider, array $fields)
3678 {
3679 $result = new Result();
3680 $resultData = $provider::getProductStores($fields);
3681
3682 $result->setData(
3683 array(
3684 $fields['PRODUCT_ID'] => $resultData
3685 )
3686 );
3687
3688 return $result;
3689 }
3690
3698 public static function checkProductBarcode(BasketItem $basketItem, array $params = array())
3699 {
3700
3701 $provider = $basketItem->getProvider();
3702 $productId = $basketItem->getProductId();
3703 $data = array(
3704 'BARCODE' => $params['BARCODE'],
3705 'STORE_ID' => $params['STORE_ID'],
3706 'PRODUCT_ID' => $productId
3707 );
3708 $result = false;
3709
3710 if ($provider && array_key_exists("IBXSaleProductProvider", class_implements($provider)))
3711 {
3712 $r = static::checkBarcode($provider, $data);
3713 if ($r->isSuccess())
3714 {
3715 $resultData = $r->getData();
3716 if (!empty($resultData) && array_key_exists($productId, $resultData))
3717 {
3718 $result = $resultData[$productId];
3719 }
3720 }
3721 }
3722 elseif (class_exists($provider))
3723 {
3725 $basket = $basketItem->getCollection();
3726 if (!$basket)
3727 {
3728 throw new ObjectNotFoundException('Entity "Basket" not found');
3729 }
3730
3731 $order = $basket->getOrder();
3732
3733 if ($order)
3734 {
3735 $context = array(
3736 'USER_ID' => $order->getUserId(),
3737 'SITE_ID' => $order->getSiteId(),
3738 'CURRENCY' => $order->getCurrency(),
3739 );
3740 }
3741 else
3742 {
3743 global $USER;
3744 $context = array(
3745 'USER_ID' => $USER->getId(),
3746 'SITE_ID' => SITE_ID,
3747 'CURRENCY' => Currency\CurrencyManager::getBaseCurrency(),
3748 );
3749 }
3750
3751 $creator = Internals\ProviderCreator::create($context);
3752
3753 $providerClass = $basketItem->getProviderEntity();
3754 if ($providerClass instanceof SaleProviderBase)
3755 {
3756 $creator->addBasketItemBarcodeData($basketItem, $data);
3757 }
3758
3759 $r = $creator->checkBarcode();
3760 if ($r->isSuccess())
3761 {
3762 if (!empty($providerClass))
3763 {
3764 $reflect = new \ReflectionClass($provider);
3765 $providerName = $reflect->getName();
3766 }
3767 else
3768 {
3769 $providerName = $basketItem->getCallbackFunction();
3770 }
3771
3772 $resultData = $r->getData();
3773 if (!empty($resultData) && array_key_exists('BARCODE_CHECK_LIST', $resultData))
3774 {
3775 $resultList = $resultData['BARCODE_CHECK_LIST'];
3776 if (isset($resultList[$providerName]) && isset($resultList[$providerName][$data['BARCODE']]))
3777 {
3778 $result = $resultList[$providerName][$data['BARCODE']];
3779 }
3780 }
3781 }
3782 }
3783 return $result;
3784 }
3785
3793 public static function checkBarcode($provider, array $barcodeParams)
3794 {
3795 $result = new Result();
3796 if (!array_key_exists("IBXSaleProductProvider", class_implements($provider)))
3797 {
3798 return $result;
3799 }
3800
3801 $resultData = $provider::checkProductBarcode($barcodeParams);
3802
3803 $result->setData(
3804 array(
3805 $barcodeParams["PRODUCT_ID"] => $resultData
3806 )
3807 );
3808
3809 return $result;
3810 }
3811
3818 public static function viewProduct(BasketItem $basketItem)
3819 {
3820 $result = new Result();
3821 $basketProviderData = static::createProviderBasketItemMap($basketItem, array('SITE_ID', 'USER_ID'));
3822 $provider = $basketProviderData['PROVIDER'];
3823 if (!empty($provider))
3824 {
3825 if (array_key_exists("IBXSaleProductProvider", class_implements($provider)))
3826 {
3827 $productId = $basketProviderData['PRODUCT_ID'];
3828 $data = array(
3829 'PRODUCT_ID' => $productId,
3830 'USER_ID' => $basketProviderData['USER_ID'],
3831 'SITE_ID' => $basketProviderData['SITE_ID'],
3832 );
3833
3834 $r = static::getViewProduct($provider, $data);
3835 if ($r->isSuccess())
3836 {
3837 $resultProductData = $r->getData();
3838 if (array_key_exists($productId, $resultProductData))
3839 {
3840 $result->setData($resultProductData);
3841 }
3842 }
3843
3844 }
3845 elseif (class_exists($provider))
3846 {
3848 $basket = $basketItem->getCollection();
3849 if (!$basket)
3850 {
3851 throw new ObjectNotFoundException('Entity "Basket" not found');
3852 }
3853
3854 $order = $basket->getOrder();
3855
3856 if ($order)
3857 {
3858 $context = array(
3859 'USER_ID' => $order->getUserId(),
3860 'SITE_ID' => $order->getSiteId(),
3861 'CURRENCY' => $order->getCurrency(),
3862 );
3863 }
3864 else
3865 {
3866 global $USER;
3867 $context = array(
3868 'USER_ID' => $USER->getId(),
3869 'SITE_ID' => SITE_ID,
3870 'CURRENCY' => Currency\CurrencyManager::getBaseCurrency(),
3871 );
3872 }
3873
3874 $creator = Internals\ProviderCreator::create($context);
3875
3876 $providerClass = $basketItem->getProviderEntity();
3877 if ($providerClass instanceof SaleProviderBase)
3878 {
3879 $creator->addBasketItem($basketItem);
3880 }
3881
3882 $r = $creator->viewProduct();
3883 if ($r->isSuccess())
3884 {
3885 $data = $r->getData();
3886 if (array_key_exists('VIEW_PRODUCTS_LIST', $data))
3887 {
3888 $resultList = $data['VIEW_PRODUCTS_LIST'];
3889
3890 if (!empty($resultList))
3891 {
3892 $productId = $basketItem->getProductId();
3893 $result = reset($resultList);
3894
3895 $result->setData(
3896 array(
3897 $productId => reset($resultList)
3898 )
3899 );
3900 }
3901 }
3902 }
3903 }
3904 }
3905
3906 return $result;
3907 }
3908
3917 public static function getViewProduct($provider, array $fields)
3918 {
3919 $result = new Result();
3920
3921 if (!array_key_exists("IBXSaleProductProvider", class_implements($provider)))
3922 {
3923 throw new ArgumentTypeException('provider');
3924 }
3925
3926 $resultData = $provider::viewProduct($fields);
3927 $result->setData(
3928 array(
3929 $fields['PRODUCT_ID'] => $resultData
3930 )
3931 );
3932 return $result;
3933 }
3934
3941 public static function recurringOrderProduct(BasketItem $basketItem)
3942 {
3943 $result = new Result();
3944 $basketProviderData = static::createProviderBasketItemMap($basketItem, array('SITE_ID', 'USER_ID'));
3945 $provider = $basketProviderData['PROVIDER'];
3946 if (!empty($provider))
3947 {
3948 if (array_key_exists("IBXSaleProductProvider", class_implements($provider)))
3949 {
3950 $data = array(
3951 'PRODUCT_ID' => $basketProviderData['PRODUCT_ID'],
3952 'USER_ID' => $basketProviderData['USER_ID'],
3953 );
3954
3955 $r = static::recurringProduct($provider, $data);
3956 if ($r->isSuccess())
3957 {
3958 $resultProductData = $r->getData();
3959 if (array_key_exists($basketProviderData['PRODUCT_ID'], $resultProductData))
3960 {
3961 $result->setData($resultProductData);
3962 }
3963
3964 }
3965
3966 }
3967 elseif (class_exists($provider))
3968 {
3970 $basket = $basketItem->getCollection();
3971 if (!$basket)
3972 {
3973 throw new ObjectNotFoundException('Entity "Basket" not found');
3974 }
3975
3976 $order = $basket->getOrder();
3977
3978 if ($order)
3979 {
3980 $context = array(
3981 'USER_ID' => $order->getUserId(),
3982 'SITE_ID' => $order->getSiteId(),
3983 'CURRENCY' => $order->getCurrency(),
3984 );
3985 }
3986 else
3987 {
3988 global $USER;
3989 $context = array(
3990 'USER_ID' => $USER->getId(),
3991 'SITE_ID' => SITE_ID,
3992 'CURRENCY' => Currency\CurrencyManager::getBaseCurrency(),
3993 );
3994 }
3995
3996 $creator = Internals\ProviderCreator::create($context);
3997
3998 $providerClass = $basketItem->getProviderEntity();
3999 if ($providerClass instanceof SaleProviderBase)
4000 {
4001 $creator->addBasketItem($basketItem);
4002 }
4003
4004 $r = $creator->recurring();
4005 if ($r->isSuccess())
4006 {
4007 $data = $r->getData();
4008 if (array_key_exists('RECURRING_PRODUCTS_LIST', $data))
4009 {
4010 $resultList = $data['RECURRING_PRODUCTS_LIST'];
4011
4012 if (!empty($resultList))
4013 {
4014 $productId = $basketItem->getProductId();
4015 $result = reset($resultList);
4016
4017 $result->setData(
4018 array(
4019 $productId => reset($resultList)
4020 )
4021 );
4022 }
4023 }
4024 }
4025 }
4026 }
4027
4028 return $result;
4029 }
4030
4038 public static function recurringProduct($provider, array $fields)
4039 {
4040 $result = new Result();
4041 if (!array_key_exists("IBXSaleProductProvider", class_implements($provider)))
4042 {
4043 throw new ArgumentTypeException('provider');
4044 }
4045
4046 $resultData = $provider::recurringOrderProduct($fields);
4047 $result->setData(
4048 array(
4049 $fields['PRODUCT_ID'] => $resultData
4050 )
4051 );
4052 return $result;
4053 }
4054
4061 public static function getSetItems(BasketItemBase $basketItem)
4062 {
4063 $bundleChildList = array();
4064 $provider = $basketItem->getProvider();
4065 if ($provider)
4066 {
4067 if (array_key_exists("IBXSaleProductProvider", class_implements($provider)))
4068 {
4069 $bundleChildList = $provider::GetSetItems($basketItem->getProductId(), BasketItem::TYPE_SET, array('BASKET_ID' => $basketItem->getId()));
4070 }
4071 elseif (class_exists($provider))
4072 {
4074 $collection = $basketItem->getCollection();
4075
4077 $basket = $collection->getBasket();
4078 if (!$basket)
4079 {
4080 throw new ObjectNotFoundException('Entity "Basket" not found');
4081 }
4082
4083 $order = $basket->getOrder();
4084
4085 if ($order)
4086 {
4087 $context = array(
4088 'SITE_ID' => $order->getSiteId(),
4089 'USER_ID' => $order->getUserId(),
4090 'CURRENCY' => $order->getCurrency(),
4091 );
4092 }
4093 else
4094 {
4095 global $USER;
4096 $context = array(
4097 'SITE_ID' => SITE_ID,
4098 'USER_ID' => $USER && $USER->GetID() > 0 ? $USER->GetID() : 0,
4099 'CURRENCY' => Currency\CurrencyManager::getBaseCurrency(),
4100 );
4101 }
4102 $creator = Internals\ProviderCreator::create($context);
4103
4104 $creator->addBasketItem($basketItem);
4105
4106 $r = $creator->getBundleItems();
4107 if ($r->isSuccess())
4108 {
4109 $resultProductListData = $r->getData();
4110 if (!empty($resultProductListData['BUNDLE_LIST']))
4111 {
4112 $bundleChildList = $resultProductListData['BUNDLE_LIST'];
4113 }
4114 }
4115
4116 $order = $basket->getOrder();
4117
4118 if ($order)
4119 {
4120 $context = array(
4121 'SITE_ID' => $order->getSiteId(),
4122 'USER_ID' => $order->getUserId(),
4123 'CURRENCY' => $order->getCurrency(),
4124 );
4125 }
4126 else
4127 {
4128 global $USER;
4129 $context = array(
4130 'SITE_ID' => SITE_ID,
4131 'USER_ID' => $USER && $USER->GetID() > 0 ? $USER->GetID() : 0,
4132 'CURRENCY' => Currency\CurrencyManager::getBaseCurrency(),
4133 );
4134 }
4135 $creator = Internals\ProviderCreator::create($context);
4136
4137 $creator->addBasketItem($basketItem);
4138
4139 $r = $creator->getBundleItems();
4140 if ($r->isSuccess())
4141 {
4142 $resultProductListData = $r->getData();
4143 if (!empty($resultProductListData['BUNDLE_LIST']))
4144 {
4145 $bundleChildList = $resultProductListData['BUNDLE_LIST'];
4146 }
4147 }
4148 }
4149 else
4150 {
4151 $bundleChildList = \CSaleBasket::executeCallbackFunction(
4152 $basketItem->getField('CALLBACK_FUNC'),
4153 $basketItem->getField('MODULE'),
4154 $basketItem->getField('PRODUCT_ID'),
4155 $basketItem->getField('QUANTITY')
4156 );
4157 }
4158
4159 return $bundleChildList;
4160 }
4161
4162 return false;
4163 }
4164
4171 private static function getBundleChildItemsByProductData($providerName, array $productData)
4172 {
4173 if (array_key_exists("IBXSaleProductProvider", class_implements($providerName)))
4174 {
4175 $bundleChildList = $providerName::GetSetItems($productData['PRODUCT_ID'], BasketItem::TYPE_SET, array('BASKET_ID' => $productData['BASKET_ID']));
4176 }
4177 else
4178 {
4179 $bundleChildList = \CSaleBasket::executeCallbackFunction(
4180 $productData['CALLBACK_FUNC'],
4181 $productData['MODULE'],
4182 $productData['PRODUCT_ID'],
4183 $productData['QUANTITY']
4184 );
4185 }
4186
4187 if (is_array($bundleChildList))
4188 {
4189 $bundleChildList = reset($bundleChildList);
4190 }
4191
4192 return $bundleChildList;
4193 }
4194
4195
4202 public static function getBundleChildItems($providerName, array $products)
4203 {
4204 $result = new Result();
4205 $resultList = array();
4206
4207 foreach ($products as $productId => $productData)
4208 {
4209 $resultList[$productId] = static::getBundleChildItemsByProductData($providerName, $productData);
4210 }
4211
4212 if (!empty($resultList))
4213 {
4214 $result->setData(
4215 array(
4216 'BUNDLE_LIST' => $resultList,
4217 )
4218 );
4219 }
4220
4221 return $result;
4222 }
4223
4224
4230 protected static function getProductListFromBasketProviderList($basketProviderList, array $productList = array())
4231 {
4232 $select = array(
4233 'ID',
4234 'CAN_BUY_ZERO',
4235 'NEGATIVE_AMOUNT_TRACE',
4236 'QUANTITY_TRACE',
4237 'QUANTITY',
4238 'QUANTITY_RESERVED'
4239 );
4240
4241 $providerProductList = array();
4242
4243 if (!empty($basketProviderList))
4244 {
4245 foreach ($basketProviderList as $provider => $providerBasketItemList)
4246 {
4247 $providerProductList = $provider::getProductList($providerBasketItemList, $productList, $select) + $providerProductList;
4248 }
4249 }
4250
4251 return (!empty($providerProductList) && is_array($providerProductList) ? $providerProductList : false);
4252 }
4253
4262 public static function checkAvailableProductQuantity(BasketItemBase $basketItem, $deltaQuantity)
4263 {
4264 global $APPLICATION;
4265
4266 $result = new Result();
4267
4268 $resultProductData = array();
4269
4270 $orderId = null;
4271 $userId = null;
4272 $siteId = null;
4273
4275 $collection = $basketItem->getCollection();
4276
4278 if (!$basket = $collection->getBasket())
4279 {
4280 throw new ObjectNotFoundException('Entity "Basket" not found');
4281 }
4282
4283
4284 if (($order = $basket->getOrder()) !== null)
4285 {
4286 $userId = $order->getUserId();
4287 $siteId = $order->getSiteId();
4288 }
4289
4290 if ($siteId === null)
4291 {
4292 $siteId = $basket->getSiteId();
4293 }
4294
4295 $provider = $basketItem->getProvider();
4296
4297 if (!empty($provider))
4298 {
4299 if (array_key_exists("IBXSaleProductProvider", class_implements($provider)))
4300 {
4301 $needQuantity = $basketItem->getQuantity();
4302 if ($order && $order->getId() > 0)
4303 {
4304 $needQuantity = $deltaQuantity;
4305 }
4306
4307 $poolQuantity = 0;
4308
4309 if ($order)
4310 {
4311 $poolQuantity = static::getQuantityPoolItem($order->getInternalId(), $basketItem);
4312 }
4313
4314 $checkQuantity = $needQuantity - floatval($poolQuantity);
4315
4316 $data = array(
4317 "PRODUCT_ID" => $basketItem->getProductId(),
4318 "QUANTITY" => $checkQuantity,
4319 "USER_ID" => $userId,
4320 "SITE_ID" => $siteId,
4321 "BASKET_ID" => $basketItem->getId(),
4322 "CHECK_QUANTITY" => "Y",
4323 "AVAILABLE_QUANTITY" => "Y",
4324 'CHECK_PRICE' => 'N',
4325 'CHECK_COUPONS' => 'N',
4326 "SELECT_QUANTITY_TRACE" => "Y",
4327 );
4328
4329 // TODO: !
4330 if ($deltaQuantity <= 0 || $checkQuantity == 0)
4331 {
4332 $result->setData(array('AVAILABLE_QUANTITY' => $deltaQuantity));
4333 return $result;
4334 }
4335
4336 $hasTrustData = false;
4337
4338 $trustData = static::getTrustData($siteId, $basketItem->getField('MODULE'), $basketItem->getField('PRODUCT_ID'));
4339
4340 if (static::isReadTrustData() === true
4341 && !empty($trustData) && is_array($trustData))
4342 {
4343 $hasTrustData = true;
4344 $resultProductData = $trustData;
4345 $productDataRequiredFields = array_merge(static::getProductDataRequiredFields(), array('AVAILABLE_QUANTITY'));
4346 foreach ($productDataRequiredFields as $requiredField)
4347 {
4348 if (!array_key_exists($requiredField, $resultProductData))
4349 {
4350 $hasTrustData = false;
4351 break;
4352 }
4353 }
4354
4355 if ($hasTrustData
4356 && roundEx($checkQuantity, SALE_VALUE_PRECISION) > roundEx($resultProductData["AVAILABLE_QUANTITY"], SALE_VALUE_PRECISION))
4357 {
4358 $hasTrustData = false;
4359 }
4360
4361 }
4362
4363 if(!$hasTrustData)
4364 {
4365 $APPLICATION->ResetException();
4366 $resultProductData = $provider::GetProductData($data);
4367 $ex = $APPLICATION->GetException();
4368 if ($ex)
4369 {
4370 $result->addWarning( new ResultWarning($ex->GetString(), $ex->GetID()) );
4371 }
4372 }
4373
4374 }
4375 elseif (class_exists($provider))
4376 {
4378 $providerClass = new $provider();
4379 if ($providerClass && $providerClass instanceof SaleProviderBase)
4380 {
4381 $productId = $basketItem->getProductId();
4382 $products = array(
4383 $productId => array(
4384 'ITEM_CODE' => $productId,
4385 'BASKET_CODE' => $basketItem->getBasketCode(),
4386 'QUANTITY' => $deltaQuantity,
4387 )
4388 );
4389 $r = $providerClass->getAvailableQuantity($products);
4390 if ($r->isSuccess())
4391 {
4392 $resultData = $r->getData();
4393 if (!empty($resultData['AVAILABLE_QUANTITY_LIST']))
4394 {
4395 $resultProductData = array(
4396 'AVAILABLE_QUANTITY' => reset($resultData['AVAILABLE_QUANTITY_LIST'])
4397 );
4398 }
4399 }
4400 }
4401 }
4402 else
4403 {
4404 $APPLICATION->ResetException();
4405 $resultProductData = \CSaleBasket::ExecuteCallbackFunction(
4406 $basketItem->getField('CALLBACK_FUNC'),
4407 $basketItem->getField('MODULE'),
4408 $basketItem->getProductId(),
4409 $basketItem->getQuantity()
4410 );
4411
4412 if ($ex = $APPLICATION->GetException())
4413 {
4414 $result->addWarning( new ResultWarning($ex->GetString(), $ex->GetID()) );
4415 }
4416 }
4417 }
4418 else
4419 {
4420 $availableQuantity = $basketItem->getQuantity();
4421 if ($deltaQuantity <= 0)
4422 {
4423 $availableQuantity = $deltaQuantity;
4424 }
4425 $result->setData([
4426 'AVAILABLE_QUANTITY' => $availableQuantity,
4427 ]);
4428
4429 return $result;
4430 }
4431
4432 $fields = array();
4433
4434 if (array_key_exists('AVAILABLE_QUANTITY', $resultProductData))
4435 {
4436 $fields['AVAILABLE_QUANTITY'] = $resultProductData['AVAILABLE_QUANTITY'];
4437 }
4438
4439 if (array_key_exists('QUANTITY_TRACE', $resultProductData))
4440 {
4441 $fields['QUANTITY_TRACE'] = ($resultProductData['QUANTITY_TRACE'] == "Y");
4442 }
4443
4444 if (!empty($fields))
4445 {
4446 $result->setData($fields);
4447 }
4448
4449 return $result;
4450 }
4451
4460 private static function getAvailableQuantityByProductData($providerClass, $productData, array $context)
4461 {
4462 global $APPLICATION;
4463
4464 $result = new Result();
4465
4466 $callbackFunction = null;
4467 $basketItem = null;
4468 if (!empty($productData['BASKET_ITEM']))
4469 {
4470 $basketItem = $productData['BASKET_ITEM'];
4471 }
4472
4473 if (!empty($productData['CALLBACK_FUNC']))
4474 {
4475 $callbackFunction = $productData['CALLBACK_FUNC'];
4476 }
4477
4478 $resultProductData = array();
4479
4480 $userId = $context['USER_ID'];
4481 $siteId = $context['SITE_ID'];
4482
4483 $productId = $productData['PRODUCT_ID'];
4484
4485 $productQuantity = 0;
4486 if (array_key_exists('QUANTITY', $productData))
4487 {
4488 $productQuantity = $productData['QUANTITY'];
4489 }
4490 elseif (!empty($productData['QUANTITY_LIST']))
4491 {
4492 foreach ($productData['QUANTITY_LIST'] as $basketCode => $quantity)
4493 {
4494 $productQuantity += $quantity;
4495 }
4496 }
4497
4498 if (!empty($providerClass) && array_key_exists("IBXSaleProductProvider", class_implements($providerClass)))
4499 {
4500 if ($productQuantity <= 0)
4501 {
4502 $result->setData(
4503 array(
4504 'AVAILABLE_QUANTITY' => $productQuantity
4505 )
4506 );
4507 return $result;
4508 }
4509
4510 $basketId = null;
4511 if ($basketItem)
4512 {
4513 $basketId = $basketItem->getId();
4514 }
4515
4516 $data = array(
4517 "PRODUCT_ID" => $productId,
4518 "QUANTITY" => $productQuantity,
4519 "USER_ID" => $userId,
4520 "SITE_ID" => $siteId,
4521 "BASKET_ID" => $basketId,
4522 "CHECK_QUANTITY" => "Y",
4523 "AVAILABLE_QUANTITY" => "Y",
4524 'CHECK_PRICE' => 'N',
4525 'CHECK_COUPONS' => 'N',
4526 "SELECT_QUANTITY_TRACE" => "Y",
4527 );
4528
4529 // TODO: !
4530// if ($deltaQuantity <= 0 || $checkQuantity == 0)
4531// {
4532// $result->setData(array('AVAILABLE_QUANTITY' => $deltaQuantity));
4533// return $result;
4534// }
4535
4536 $hasTrustData = false;
4537
4538 $trustData = static::getTrustData($siteId, $productData['MODULE'], $productId);
4539
4540 if (static::isReadTrustData() === true
4541 && !empty($trustData) && is_array($trustData))
4542 {
4543 $hasTrustData = true;
4544 $resultProductData = $trustData;
4545 $productDataRequiredFields = array_merge(static::getProductDataRequiredFields(), array('AVAILABLE_QUANTITY'));
4546 foreach ($productDataRequiredFields as $requiredField)
4547 {
4548 if (!array_key_exists($requiredField, $resultProductData))
4549 {
4550 $hasTrustData = false;
4551 break;
4552 }
4553 }
4554
4555 if ($hasTrustData
4556 && roundEx($productQuantity, SALE_VALUE_PRECISION) > roundEx($resultProductData["AVAILABLE_QUANTITY"], SALE_VALUE_PRECISION))
4557 {
4558 $hasTrustData = false;
4559 }
4560
4561 }
4562
4563 if(!$hasTrustData)
4564 {
4565 $APPLICATION->ResetException();
4566 $resultProductData = $providerClass::GetProductData($data);
4567 if ($ex = $APPLICATION->GetException())
4568 {
4569 $result->addWarning( new ResultWarning($ex->GetString(), $ex->GetID()) );
4570 }
4571 }
4572
4573 }
4574 elseif (!empty($callbackFunction))
4575 {
4576 $APPLICATION->ResetException();
4577 $resultProductData = \CSaleBasket::ExecuteCallbackFunction(
4578 $callbackFunction,
4579 $productData['MODULE'],
4580 $productId,
4581 $productQuantity
4582 );
4583
4584 if ($ex = $APPLICATION->GetException())
4585 {
4586 $result->addWarning( new ResultWarning($ex->GetString(), $ex->GetID()) );
4587 }
4588 }
4589 else
4590 {
4591 $result->setData(
4592 array(
4593 'AVAILABLE_QUANTITY' => $productQuantity
4594 )
4595 );
4596 return $result;
4597 }
4598
4599 $fields = array();
4600
4601 if (!empty($resultProductData))
4602 {
4603 if (array_key_exists('AVAILABLE_QUANTITY', $resultProductData))
4604 {
4605 $fields['AVAILABLE_QUANTITY'] = $resultProductData['AVAILABLE_QUANTITY'];
4606 }
4607
4608 if (array_key_exists('QUANTITY_TRACE', $resultProductData))
4609 {
4610 $fields['QUANTITY_TRACE'] = ($resultProductData['QUANTITY_TRACE'] == "Y");
4611 }
4612 }
4613
4614 if (!empty($fields))
4615 {
4616 $result->setData($fields);
4617 }
4618
4619 return $result;
4620 }
4621
4630 private static function getProviderDataByProductData($providerClass, $productData, array $context)
4631 {
4632 $result = new Result();
4633
4634 $providerName = null;
4635 if (!empty($providerClass))
4636 {
4637 $reflect = new \ReflectionClass($providerClass);
4638 $providerName = $reflect->getName();
4639 }
4640
4641 $productId = $productData['PRODUCT_ID'];
4642
4643 $items = array( $productId => $productData );
4644
4645 $r = static::getProductDataByList($items, $providerName, array('PRICE', 'COUPONS', 'AVAILABLE_QUANTITY', 'QUANTITY'), $context);
4646
4647 if ($r->isSuccess())
4648 {
4649 $resultData = $r->getData();
4650 $isExistsProductDataList = isset($resultData['PRODUCT_DATA_LIST']) && !empty($resultData['PRODUCT_DATA_LIST']);
4651 $isExistsProductData = isset($resultData['PRODUCT_DATA_LIST'][$productId]);
4652
4653 if ($isExistsProductDataList && $isExistsProductData)
4654 {
4655 $result->setData($resultData['PRODUCT_DATA_LIST'][$productId]);
4656 }
4657 }
4658
4659 return $result;
4660 }
4661
4669 public static function deliverShipment(Shipment $shipment)
4670 {
4671
4672 $result = new Result();
4673
4674 $needDeliver = null;
4675 if ($shipment->getFields()->isChanged('ALLOW_DELIVERY'))
4676 {
4677 $needDeliver = $shipment->getField('ALLOW_DELIVERY') === "Y";
4678 }
4679
4680 if ($needDeliver === null || ($needDeliver === false && $shipment->getId() <= 0))
4681 return $result;
4682
4683 $resultList = array();
4684
4686 if (!$shipmentItemCollection = $shipment->getShipmentItemCollection())
4687 {
4688 throw new ObjectNotFoundException('Entity "ShipmentItemCollection" not found');
4689 }
4690
4692 if (!$shipmentCollection = $shipment->getCollection())
4693 {
4694 throw new ObjectNotFoundException('Entity "ShipmentCollection" not found');
4695 }
4696
4698 if (!$order = $shipmentCollection->getOrder())
4699 {
4700 throw new ObjectNotFoundException('Entity "Order" not found');
4701 }
4702
4704 if (!$basket = $order->getBasket())
4705 {
4706 return $result;
4707 }
4708
4709 $basketList = static::getBasketFromShipmentItemCollection($shipmentItemCollection);
4710
4711 $basketProviderMap = static::createProviderBasketMap($basketList, array('ORDER_ID', 'USER_ID', 'QUANTITY', 'ALLOW_DELIVERY', 'PAY_CALLBACK', 'PAID'));
4712 $basketProviderList = static::redistributeToProviders($basketProviderMap);
4713
4714 if (!empty($basketProviderList))
4715 {
4716 foreach ($basketProviderList as $provider => $providerBasketItemList)
4717 {
4718 if (array_key_exists("IBXSaleProductProvider", class_implements($provider)))
4719 {
4720
4721 foreach ($providerBasketItemList as $providerBasketItem)
4722 {
4723
4724 if ($providerBasketItem['BASKET_ITEM']->isBundleParent())
4725 {
4726 continue;
4727 }
4728
4729 if ($providerBasketItem['BASKET_ITEM']->getField('MODULE') != '')
4730 {
4731 $data = array(
4732 "PRODUCT_ID" => $providerBasketItem["PRODUCT_ID"],
4733 "USER_ID" => $providerBasketItem["USER_ID"],
4734 "PAID" => $providerBasketItem["PAID"],
4735 "ORDER_ID" => $providerBasketItem["ORDER_ID"],
4736 "BASKET_ID" => $providerBasketItem['BASKET_ID']
4737 );
4738
4739 $r = static::deliverProductData($provider, $data);
4740 if ($r->isSuccess())
4741 {
4742 $resultData = $r->getData();
4743
4744 if (array_key_exists($providerBasketItem["PRODUCT_ID"], $resultData))
4745 {
4746 $resultProductData = $resultData[$providerBasketItem["PRODUCT_ID"]];
4747 }
4748 }
4749 else
4750 {
4751 $result->addErrors($r->getErrors());
4752 }
4753
4754 if (!empty($resultProductData) && is_array($resultProductData))
4755 {
4756 $resultProductData['ORDER_ID'] = $providerBasketItem['ORDER_ID'];
4757 }
4758 }
4759 else
4760 {
4761 $resultProductData = true;
4762 }
4763
4764 $resultList[$providerBasketItem['BASKET_CODE']] = $resultProductData;
4765
4766 }
4767
4768 }
4769 elseif (class_exists($provider))
4770 {
4771 $context = array(
4772 'SITE_ID' => $order->getSiteId(),
4773 'CURRENCY' => $order->getCurrency(),
4774 );
4775
4776 if ($order->getUserId() > 0)
4777 {
4778 $context['USER_ID'] = $order->getUserId();
4779 }
4780 else
4781 {
4782 global $USER;
4783 $context['USER_ID'] = $USER->getId();
4784 }
4785
4786 $creator = Internals\ProviderCreator::create($context);
4787
4789 foreach ($shipmentItemCollection as $shipmentItem)
4790 {
4791 $basketItem = $shipmentItem->getBasketItem();
4792 $providerClass = $basketItem->getProviderEntity();
4793
4794 if ($providerClass instanceof SaleProviderBase)
4795 {
4796 $creator->addShipmentItem($shipmentItem);
4797 }
4798 }
4799
4800 $r = $creator->deliver();
4801 if ($r->isSuccess())
4802 {
4803 $r = $creator->createItemsResultAfterDeliver($r);
4804 if ($r->isSuccess())
4805 {
4806 $data = $r->getData();
4807 if (array_key_exists('RESULT_AFTER_DELIVER_LIST', $data))
4808 {
4809 $resultList = $data['RESULT_AFTER_DELIVER_LIST'] + $resultList;
4810 }
4811 }
4812 }
4813 else
4814 {
4815 $result->addErrors($r->getErrors());
4816 }
4817 }
4818 else
4819 {
4820 foreach ($providerBasketItemList as $providerBasketItem)
4821 {
4822 $resultProductData = \CSaleBasket::ExecuteCallbackFunction(
4823 $providerBasketItem['CALLBACK_FUNC'],
4824 $providerBasketItem['MODULE'],
4825 $providerBasketItem['PRODUCT_ID'],
4826 $providerBasketItem['USER_ID'],
4827 $providerBasketItem["ALLOW_DELIVERY"],
4828 $providerBasketItem['ORDER_ID'],
4829 $providerBasketItem["QUANTITY"]
4830 );
4831
4832 $basketCode = $providerBasketItem['BASKET_ITEM']->getBasketCode();
4833
4834 if (!empty($resultProductData) && is_array($resultProductData))
4835 {
4836 $resultProductData['ORDER_ID'] = $providerBasketItem['ORDER_ID'];
4837 }
4838
4839 $resultList[$basketCode] = $resultProductData;
4840 }
4841 }
4842 }
4843
4844 if (!empty($resultList) && is_array($resultList))
4845 {
4846 $recurringID = intval($order->getField("RECURRING_ID"));
4847 foreach ($resultList as $basketCode => $resultData)
4848 {
4849 if ($order->isPaid())
4850 {
4851 if (!empty($resultData) && is_array($resultData))
4852 {
4853 if (empty($resultData['ORDER_ID']) || intval($resultData['ORDER_ID']) < 0)
4854 $resultData["ORDER_ID"] = $order->getId();
4855
4856 $resultData["REMAINING_ATTEMPTS"] = (defined("SALE_PROC_REC_ATTEMPTS") ? SALE_PROC_REC_ATTEMPTS : 3);
4857 $resultData["SUCCESS_PAYMENT"] = "Y";
4858
4859 if ($recurringID > 0)
4860 \CSaleRecurring::Update($recurringID, $resultData);
4861 else
4862 \CSaleRecurring::Add($resultData);
4863 }
4864 elseif ($recurringID > 0)
4865 {
4866 \CSaleRecurring::Delete($recurringID);
4867 }
4868 }
4869 else
4870 {
4872 if (!$basketItem = $basket->getItemByBasketCode($basketCode))
4873 {
4874 throw new ObjectNotFoundException('Entity "BasketItem" not found');
4875 }
4876
4877 $resRecurring = \CSaleRecurring::GetList(
4878 array(),
4879 array(
4880 "USER_ID" => $order->getUserId(),
4881 "PRODUCT_ID" => $basketItem->getProductId(),
4882 "MODULE" => $basketItem->getField("MODULE")
4883 )
4884 );
4885 while ($recurringData = $resRecurring->Fetch())
4886 {
4887 \CSaleRecurring::Delete($recurringData["ID"]);
4888 }
4889 }
4890 }
4891 }
4892 }
4893
4894 if (!empty($resultList))
4895 {
4896 $result->setData($resultList);
4897 }
4898
4899 return $result;
4900 }
4901
4908 public static function deliverProductData($provider, array $fields)
4909 {
4910 global $APPLICATION;
4911
4912 $result = new Result();
4913 $APPLICATION->ResetException();
4914 $resultProductData = false;
4915
4916 if ($provider && array_key_exists("IBXSaleProductProvider", class_implements($provider)))
4917 {
4918 $resultProductData = $provider::DeliverProduct($fields);
4919 }
4920 else
4921 {
4922 $resultProductData = \CSaleBasket::ExecuteCallbackFunction(
4923 $fields['CALLBACK_FUNC'],
4924 $fields['MODULE'],
4925 $fields['PRODUCT_ID'],
4926 $fields['USER_ID'],
4927 $fields["ALLOW_DELIVERY"],
4928 $fields['ORDER_ID'],
4929 $fields["QUANTITY"]
4930 );
4931
4932 if (!empty($resultProductData) && is_array($resultProductData))
4933 {
4934 $resultProductData['ORDER_ID'] = $fields['ORDER_ID'];
4935 }
4936
4937 }
4938
4939 $ex = $APPLICATION->GetException();
4940 if (!empty($ex))
4941 {
4942 $result->addError( new ResultError($ex->GetString(), $ex->GetID()) );
4943 }
4944 else
4945 {
4946 $resultList[$fields['PRODUCT_ID']] = $resultProductData;
4947 }
4948
4949 if (!empty($resultList) && is_array($resultList))
4950 {
4951 $result->setData($resultList);
4952 }
4953
4954 return $result;
4955 }
4956
4957
4964 protected static function createProviderBasketMap(array $basketList, array $select = array())
4965 {
4966 $basketProviderMap = array();
4967
4972 foreach($basketList as $basketIndex => $basketItemDat)
4973 {
4974 if (is_array($basketItemDat) && isset($basketItemDat['BASKET_ITEM']))
4975 {
4976 $basketItem = $basketItemDat['BASKET_ITEM'];
4977 }
4978 else
4979 {
4980 $basketItem = $basketItemDat;
4981 }
4982
4983 $basketProviderData = static::createProviderBasketItemMap($basketItem, $select);
4984 if (!$basketProviderData)
4985 {
4986 continue;
4987 }
4988
4989 $basketProviderMap[$basketIndex] = $basketProviderData;
4990
4991 }
4992
4993 return $basketProviderMap;
4994 }
4995
4996
4997 protected static function createProviderBasketItemMap(BasketItem $basketItem, array $select = array())
4998 {
4999
5000 $basketProviderData = array(
5001 'BASKET_ITEM' => $basketItem,
5002 'BASKET_ID' => $basketItem->getId(),
5003 'BASKET_CODE' => $basketItem->getBasketCode(),
5004 'PRODUCT_ID' => $basketItem->getProductId(),
5005 'MODULE' => $basketItem->getField('MODULE'),
5006 );
5007
5008 $provider = $basketItem->getProvider();
5009 $providerClass = $basketItem->getProviderEntity();
5010 if ($provider)
5011 {
5012 if (array_key_exists("IBXSaleProductProvider", class_implements($provider))
5013 || $providerClass instanceof SaleProviderBase)
5014 {
5015 $basketProviderData['PROVIDER'] = $provider;
5016 }
5017 }
5018 elseif (strval($basketItem->getField('CALLBACK_FUNC')) != '')
5019 {
5020 $basketProviderData['CALLBACK_FUNC'] = $basketItem->getField('CALLBACK_FUNC');
5021 }
5022 elseif (strval($basketItem->getField('PAY_CALLBACK_FUNC')) != '' && in_array('PAY_CALLBACK', $select))
5023 {
5024 $basketProviderData['CALLBACK_FUNC'] = $basketItem->getField('PAY_CALLBACK_FUNC');
5025 }
5026
5027 if (in_array('QUANTITY', $select))
5028 {
5029 $basketProviderData['QUANTITY'] = $basketItem->getQuantity(); // ????
5030 }
5031
5032 if (in_array('RENEWAL', $select))
5033 {
5034 $basketProviderData['RENEWAL'] = $basketItem->getField('RENEWAL')!== null && $basketItem->getField('RENEWAL') != 'N'? 'Y' : 'N';
5035 }
5036
5037 if (in_array('RESERVED', $select))
5038 {
5039 $basketProviderData['RESERVED'] = $basketItem->getField('RESERVED');
5040 }
5041
5042 if (in_array('SITE_ID', $select))
5043 {
5044 $basketProviderData['SITE_ID'] = $basketItem->getField('LID');
5045 }
5046
5047 if (in_array('ORDER_ID', $select))
5048 {
5050 if (!$basket = $basketItem->getCollection())
5051 {
5052 throw new ObjectNotFoundException('Entity "Basket" not found');
5053 }
5054
5055 if ($basket->getOrder() && $basket->getOrderId() > 0)
5056 {
5057 $basketProviderData['ORDER_ID'] = $basket->getOrderId();
5058 }
5059
5060 }
5061
5062 if (in_array('USER_ID', $select))
5063 {
5065 if (!$basket = $basketItem->getCollection())
5066 {
5067 throw new ObjectNotFoundException('Entity "Basket" not found');
5068 }
5069
5070 if ($order = $basket->getOrder())
5071 {
5072 $userId = $order->getUserId();
5073
5074 if ($userId === null)
5075 {
5076 $userId = Sale\Fuser::getUserIdById($basket->getFUserId());
5077 }
5078
5079 if ($userId > 0)
5080 {
5081 $basketProviderData['USER_ID'] = $userId;
5082 }
5083 }
5084
5085 }
5086
5087 if (in_array('PAID', $select))
5088 {
5090 if (!$basket = $basketItem->getCollection())
5091 {
5092 throw new ObjectNotFoundException('Entity "Basket" not found');
5093 }
5094
5095 if ($basket->getOrder() && $basket->getOrderId() > 0)
5096 {
5097 $order = $basket->getOrder();
5098 $basketProviderData['PAID'] = $order->isPaid();
5099 }
5100
5101 }
5102
5103 if (in_array('ALLOW_DELIVERY', $select))
5104 {
5106 if (!$basket = $basketItem->getCollection())
5107 {
5108 throw new ObjectNotFoundException('Entity "Basket" not found');
5109 }
5110
5111 if ($basket->getOrder() && $basket->getOrderId() > 0)
5112 {
5114 $order = $basket->getOrder();
5115
5117 if ($shipmentCollection = $order->getShipmentCollection())
5118 {
5119 $basketProviderData['ALLOW_DELIVERY'] = $shipmentCollection->isAllowDelivery();
5120 }
5121 }
5122
5123 }
5124
5125 return $basketProviderData;
5126 }
5131 private static function getProviderBasketFromShipment(Shipment $shipment)
5132 {
5133 $shipmentItemCollection = $shipment->getShipmentItemCollection();
5134
5135 $basketList = static::getBasketFromShipmentItemCollection($shipmentItemCollection);
5136
5137 $basketProviderMap = static::createProviderBasketMap($basketList, array('QUANTITY', 'PRODUCT_ID'));
5138
5139 $basketProviderList = static::redistributeToProviders($basketProviderMap);
5140
5141 return $basketProviderList;
5142 }
5143
5148 protected static function redistributeToProviders(array $basketProviderMap)
5149 {
5150
5151 $basketProviderList = array();
5152 foreach($basketProviderMap as $basketProviderItem)
5153 {
5154 $providerName = $basketProviderItem['PROVIDER'] ?? '';
5155 $productId = $basketProviderItem['BASKET_ITEM']->getProductId();
5156 $quantity = floatval($basketProviderItem['QUANTITY']);
5157 unset($basketProviderItem['QUANTITY']);
5158
5159 $basketCode = $basketProviderItem['BASKET_CODE'];
5160
5161 if (!isset($basketProviderList[$providerName][$productId]))
5162 {
5163 $basketProviderList[$providerName][$productId] = $basketProviderItem;
5164 }
5165
5166 if (isset($basketProviderList[$providerName][$productId]['QUANTITY_LIST'][$basketCode]))
5167 {
5168 $basketProviderList[$providerName][$productId]['QUANTITY_LIST'][$basketCode] += $quantity;
5169 }
5170 else
5171 {
5172 $basketProviderList[$providerName][$productId]['QUANTITY_LIST'][$basketCode] = $quantity;
5173 }
5174
5175
5176
5177 }
5178
5179 return $basketProviderList;
5180 }
5181
5186 public static function setUsingTrustData($value)
5187 {
5188 static::$useReadTrustData = (bool)$value;
5189 }
5190
5195 public static function isReadTrustData()
5196 {
5197 return (bool)static::$useReadTrustData;
5198 }
5199
5200
5209 public static function isExistsTrustData($siteId, $module, $productId)
5210 {
5211 return (!empty(static::$trustData[$siteId][$module][$productId]) && is_array(static::$trustData[$siteId][$module][$productId]));
5212 }
5213
5214
5222 public static function setTrustData($siteId, $module, $productId, array $fields)
5223 {
5224 static::$trustData[$siteId][$module][$productId] = $fields;
5225 }
5226
5227
5236 public static function getTrustData($siteId, $module, $productId)
5237 {
5238 if (static::isExistsTrustData($siteId, $module, $productId))
5239 return static::$trustData[$siteId][$module][$productId];
5240
5241 return null;
5242 }
5243
5250 public static function resetTrustData($siteId = null, $module = null, $productId = null)
5251 {
5252 if (strval($siteId) != '')
5253 {
5254 if (!empty(static::$trustData[$siteId]))
5255 {
5256 if (intval($productId) > 0 )
5257 {
5258 if (strval($module) == '')
5259 {
5260 foreach (static::$trustData[$siteId] as $moduleName => $data)
5261 {
5262 if (isset(static::$trustData[$siteId][$moduleName][$productId]))
5263 unset(static::$trustData[$siteId][$moduleName][$productId]);
5264 }
5265 }
5266 else
5267 {
5268 if (isset(static::$trustData[$siteId][$module][$productId]))
5269 unset(static::$trustData[$siteId][$module][$productId]);
5270 }
5271 }
5272 elseif (strval($module) != '')
5273 {
5274 if (isset(static::$trustData[$siteId][$module]))
5275 unset(static::$trustData[$siteId][$module]);
5276 }
5277 else
5278 {
5279 if (isset(static::$trustData[$siteId]))
5280 unset(static::$trustData[$siteId]);
5281 }
5282 }
5283 }
5284 else
5285 {
5286 static::$trustData = array();
5287 }
5288
5289 }
5290
5302 protected static function refreshMarkers(Order $order)
5303 {
5304 if ($order->getId() == 0)
5305 {
5306 return;
5307 }
5308
5309 if (!$shipmentCollection = $order->getShipmentCollection())
5310 {
5311 throw new ObjectNotFoundException('Entity "ShipmentCollection" not found');
5312 }
5313
5314 if (!$paymentCollection = $order->getPaymentCollection())
5315 {
5316 throw new ObjectNotFoundException('Entity "PaymentCollection" not found');
5317 }
5318
5319 if (!$basket = $order->getBasket())
5320 {
5321 throw new ObjectNotFoundException('Entity "Basket" not found');
5322 }
5323
5324 $markList = array();
5325
5326 $markerEntityList = array();
5327
5328 $filter = array(
5329 'filter' => array(
5330 '=ORDER_ID' => $order->getId(),
5332 ),
5333 'select' => array('ID', 'ENTITY_TYPE', 'ENTITY_ID', 'CODE', 'SUCCESS'),
5334 'order' => array('ID' => 'DESC')
5335 );
5336 $res = EntityMarker::getList($filter);
5337 while($markerData = $res->fetch())
5338 {
5339 if (!empty($markList[$markerData['ENTITY_TYPE']])
5340 && !empty($markList[$markerData['ENTITY_TYPE']][$markerData['ENTITY_ID']])
5341 && $markerData['CODE'] == $markList[$markerData['ENTITY_TYPE']][$markerData['ENTITY_ID']]
5342 )
5343 {
5344 continue;
5345 }
5346
5347 if ($markerData['SUCCESS'] != EntityMarker::ENTITY_SUCCESS_CODE_DONE)
5348 {
5349 $markList[$markerData['ENTITY_TYPE']][$markerData['ENTITY_ID']][] = $markerData['CODE'];
5350 }
5351
5352 if ($poolItemSuccess = EntityMarker::getPoolItemSuccess($order, $markerData['ID'], $markerData['ENTITY_TYPE'], $markerData['ENTITY_ID'], $markerData['CODE']))
5353 {
5354 if ($poolItemSuccess == EntityMarker::ENTITY_SUCCESS_CODE_DONE)
5355 {
5356 foreach ($markList[$markerData['ENTITY_TYPE']][$markerData['ENTITY_ID']] as $markerIndex => $markerCode)
5357 {
5358 if ($markerData['CODE'] == $markerCode)
5359 {
5360 unset($markList[$markerData['ENTITY_TYPE']][$markerData['ENTITY_ID']][$markerIndex]);
5361 }
5362 }
5363
5364 if (empty($markList[$markerData['ENTITY_TYPE']][$markerData['ENTITY_ID']]))
5365 {
5366 unset($markList[$markerData['ENTITY_TYPE']][$markerData['ENTITY_ID']]);
5367 }
5368 }
5369 }
5370
5371 if (empty($markList[$markerData['ENTITY_TYPE']]))
5372 {
5373 unset($markList[$markerData['ENTITY_TYPE']]);
5374 }
5375 }
5376
5377 if (!empty($markList))
5378 {
5379 foreach ($markList as $markEntityType => $markEntityList)
5380 {
5381 foreach ($markEntityList as $markEntityId => $markEntityCodeList)
5382 {
5383 if (empty($markEntityCodeList))
5384 {
5385 if (($entity = EntityMarker::getEntity($order, $markEntityType, $markEntityId)) && ($entity instanceof \IEntityMarker))
5386 {
5387 if ($entity->canMarked())
5388 {
5389 $markedField = $entity->getMarkField();
5390 $entity->setField($markedField, 'N');
5391 }
5392 }
5393 }
5394 }
5395 }
5396 }
5397
5398 if (empty($markList) && !EntityMarker::hasErrors($order))
5399 {
5400 if ($shipmentCollection->isMarked())
5401 {
5403 foreach ($shipmentCollection as $shipment)
5404 {
5405 if ($shipment->isMarked())
5406 {
5407 $shipment->setField('MARKED', 'N');
5408 }
5409 }
5410 }
5411 if ($paymentCollection->isMarked())
5412 {
5414 foreach ($paymentCollection as $payment)
5415 {
5416 if ($payment->isMarked())
5417 {
5418 $payment->setField('MARKED', 'N');
5419 }
5420 }
5421 }
5422
5423 $order->setField('MARKED', 'N');
5424 }
5425 }
5426
5427
5428
5432 protected static function getPrimaryFields()
5433 {
5434 return array_merge(
5435 array(
5436 'NAME',
5437 'CATALOG_XML_ID',
5438 'PRODUCT_XML_ID',
5439 'WEIGHT',
5440 'DETAIL_PAGE_URL',
5441 'BARCODE_MULTI',
5442 'DIMENSIONS',
5443 'TYPE',
5444 'SET_PARENT_ID',
5445 'MEASURE_CODE',
5446 'MEASURE_NAME',
5447 ),
5448 static::getUpdatableFields()
5449 );
5450 }
5451
5456 public static function getUpdatableFields()
5457 {
5458 return array(
5459 'CAN_BUY',
5460
5461 'VAT_RATE',
5462 'VAT_INCLUDED',
5463
5464 'PRODUCT_PRICE_ID',
5465 'PRICE',
5466 'CURRENCY',
5467 'BASE_PRICE',
5468 'DISCOUNT_PRICE',
5469
5470 'QUANTITY',
5471 'QUANTITY_RESERVED',
5472 );
5473 }
5474
5479 protected static function getProductDataRequiredFields()
5480 {
5481 return array(
5482 'NAME',
5483 'CAN_BUY',
5484 'BARCODE_MULTI',
5485 'WEIGHT',
5486 'TYPE',
5487 'QUANTITY',
5488 );
5489 }
5490
5495 protected static function getProductDataRequiredPriceFields()
5496 {
5497 return array(
5498 'PRODUCT_PRICE_ID',
5499 'NOTES',
5500 'VAT_RATE',
5501 'BASE_PRICE',
5502 'PRICE',
5503 'CURRENCY',
5504 'DISCOUNT_PRICE',
5505 );
5506 }
5507
5516 public static function getAvailableQuantity($providerClass, array $products, array $context)
5517 {
5518 $result = new Result();
5519 $resultList = array();
5520
5521 foreach ($products as $productId => $productData)
5522 {
5523 $r = static::getAvailableQuantityByProductData($providerClass, $productData, $context);
5524 if (!$r->isSuccess())
5525 {
5526 $result->addErrors($r->getErrors());
5527 }
5528 elseif ($r->hasWarnings())
5529 {
5530 $result->addWarnings($r->getWarnings());
5531 }
5532
5533 $availableQuantityData = $r->getData();
5534 if (array_key_exists('AVAILABLE_QUANTITY', $availableQuantityData))
5535 {
5536 $resultList[$productId] ??= 0;
5537
5538 $resultList[$productId] += floatval($availableQuantityData['AVAILABLE_QUANTITY']);
5539 }
5540 else
5541 {
5542 $result->addWarning(new ResultWarning(Loc::getMessage('SALE_PROVIDER_BASKET_ITEM_WRONG_AVAILABLE_QUANTITY', array(
5543 '#PRODUCT_ID#' => $productId
5544 )), 'PROVIDER_BASKET_ITEM_WRONG_AVAILABLE_QUANTITY'));
5545
5546 }
5547 }
5548
5549 if (!empty($resultList))
5550 {
5551 $result->setData(
5552 array(
5553 'AVAILABLE_QUANTITY_LIST' => $resultList,
5554 )
5555 );
5556 }
5557
5558 return $result;
5559 }
5560
5570 public static function getAvailableQuantityAndPrice($providerClass, array $products, array $context)
5571 {
5572 $result = new Result();
5573 $availableQuantityList = array();
5574 $priceData = array();
5575 $providerName = null;
5576
5577 foreach ($products as $productId => $productData)
5578 {
5580 $basketItem = $productData['BASKET_ITEM'];
5581 if (!$basketItem)
5582 {
5583 throw new ObjectNotFoundException('Entity "BasketItem" not found');
5584 }
5585
5586 $callbackFunction = null;
5587 if (!empty($productData['CALLBACK_FUNC']))
5588 {
5589 $callbackFunction = $productData['CALLBACK_FUNC'];
5590 }
5591
5592 $isCustomItem = !($providerClass || $callbackFunction);
5593
5594 if ($isCustomItem)
5595 {
5596 $providerData = $basketItem->getFieldValues();
5597 $providerData['AVAILABLE_QUANTITY'] = $basketItem->getQuantity();
5598 }
5599 else
5600 {
5601 $r = static::getProviderDataByProductData($providerClass, $productData, $context);
5602 if (!$r->isSuccess())
5603 {
5604 $result->addErrors($r->getErrors());
5605 }
5606 elseif ($r->hasWarnings())
5607 {
5608 $result->addWarnings($r->getWarnings());
5609 }
5610 $providerData = $r->getData();
5611 }
5612
5613 if (!empty($providerData))
5614 {
5615 if (isset($providerData['AVAILABLE_QUANTITY']))
5616 {
5617 $availableQuantityList[$productId] ??= 0;
5618 $availableQuantityList[$productId] += (float)$providerData['AVAILABLE_QUANTITY'];
5619 }
5620 else
5621 {
5622 $result->addWarning(new ResultWarning(Loc::getMessage('SALE_PROVIDER_BASKET_ITEM_WRONG_AVAILABLE_QUANTITY', array(
5623 '#PRODUCT_ID#' => $productId
5624 )), 'PROVIDER_BASKET_ITEM_WRONG_AVAILABLE_QUANTITY'));
5625
5626 }
5627
5628 if (!$isCustomItem)
5629 {
5630 $priceFields = static::getPriceFields();
5631
5632 foreach ($priceFields as $fieldName)
5633 {
5634 if (array_key_exists($fieldName, $providerData))
5635 {
5636 $priceData[$productId][$basketItem->getBasketCode()][$fieldName] = $providerData[$fieldName];
5637 }
5638
5639 }
5640 }
5641 }
5642 }
5643
5644 $result->setData(
5645 array(
5646 'PRODUCT_DATA_LIST' => array(
5647 'PRICE_LIST' => $priceData,
5648 'AVAILABLE_QUANTITY_LIST' => $availableQuantityList
5649 )
5650 )
5651 );
5652
5653 return $result;
5654 }
5655
5656
5663 public static function isNeedShip($shipmentItemList)
5664 {
5665 $result = new Result();
5666
5667 $resultList = array();
5668
5670 foreach ($shipmentItemList as $shipmentItem)
5671 {
5672 $basketItem = $shipmentItem->getBasketItem();
5673 $providerName = $basketItem->getProviderName();
5674
5675 if ($providerName && array_key_exists("IBXSaleProductProvider", class_implements($providerName)))
5676 {
5677
5678 $isNeedShip = false;
5679
5680 if (method_exists($providerName, 'isNeedShip'))
5681 {
5682 $isNeedShip = $providerName::isNeedShip();
5683 }
5684
5685 $resultList[$providerName] = $isNeedShip;
5686
5687 }
5688 }
5689
5690 if (!empty($resultList))
5691 {
5692 $result->setData($resultList);
5693 }
5694
5695 return $result;
5696 }
5697
5701 protected static function getPriceFields()
5702 {
5703 return array(
5704 'PRODUCT_PRICE_ID',
5705 'NOTES',
5706 'VAT_RATE',
5707 'DISCOUNT_NAME',
5708 'DISCOUNT_COUPON',
5709 'DISCOUNT_VALUE',
5710 'RESULT_PRICE',
5711 'PRICE_TYPE_ID',
5712 'BASE_PRICE',
5713 'PRICE',
5714 'CURRENCY',
5715 'DISCOUNT_PRICE',
5716 'CUSTOM_PRICE',
5717 );
5718 }
5719
5720
5721}
static loadMessages($file)
Definition loc.php:64
static getMessage($code, $replace=null, $language=null)
Definition loc.php:29
static hasErrors(Order $order)
static getPoolItemSuccess(Order $order, $id, $entityType, $entityId, $code)
static getList(array $parameters=array())
static getBundleChildItems($providerName, array $products)
static getProductListFromBasketProviderList($basketProviderList, array $productList=array())
static reserveProduct($provider, $productId, $quantity)
static setUsingTrustData($value)
static getStores($provider, array $fields)
static getProductData(BasketItemCollection $basketCollection, array $select=array(), BasketItem $refreshItem=null)
static getQuantityPoolItem($key, BasketItem $item)
static getStoreDataFromShipmentItemCollection($shipmentItemList)
static addQuantityPoolItem($key, BasketItem $item, $value)
static addReservationPoolItem($key, BasketItem $item, $value)
static setReservationPoolItem($key, BasketItem $item, $value)
static getReservationPool($key)
static recurringProduct($provider, array $fields)
static getAvailableQuantity($providerClass, array $products, array $context)
static resetTrustData($siteId=null, $module=null, $productId=null)
static getProductDataByList(array $products, $providerClassName, array $select, array $context, array $options=array())
static redistributeToProviders(array $basketProviderMap)
static checkBarcode($provider, array $barcodeParams)
static getViewProduct($provider, array $fields)
static getTrustData($siteId, $module, $productId)
static isExistsTrustData($siteId, $module, $productId)
static setQuantityPoolItem($key, BasketItem $item, $value)
static setTrustData($siteId, $module, $productId, array $fields)
static getReservationPoolItem($key, BasketItem $item)
static resetReservationPool($key)
static deliverProductData($provider, array $fields)
static getProductDataRequiredPriceFields()