Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
shipmentitemcollection.php
1<?php
8namespace Bitrix\Sale;
9
10use Bitrix\Main;
13
14Loc::loadMessages(__FILE__);
15
18{
20 protected $shipment;
21
22 protected $shipmentItemIndexMap = array();
23
27 protected function getEntityParent()
28 {
29 return $this->getShipment();
30 }
31
41 public function resetCollection(Basket $basket)
42 {
43 if ($this->getShipment()->isShipped())
44 {
46 }
47
48 if (!empty($this->collection))
49 {
51 foreach ($this->collection as $shipmentItem)
52 {
53 $shipmentItem->setFieldNoDemand('QUANTITY', 0);
54 $shipmentItem->delete();
55 }
56 }
57
58 $quantityList = [];
59
61 $shipmentCollection = $this->getShipment()->getCollection();
62
64 foreach ($basket as $basketItem)
65 {
66 $quantityList[$basketItem->getBasketCode()] = $shipmentCollection->getBasketItemDistributedQuantity($basketItem);
67 }
68
70 $itemClassName = static::getItemCollectionClassName();
71
73 foreach ($basket as $basketItem)
74 {
75 $shipmentItem = $itemClassName::create($this, $basketItem);
76 $this->addItem($shipmentItem);
77
78 $basketItemQuantity = 0;
79
80 if (array_key_exists($basketItem->getBasketCode(), $quantityList))
81 {
82 $basketItemQuantity = $quantityList[$basketItem->getBasketCode()];
83 }
84
85 $quantity = $basketItem->getQuantity() - $basketItemQuantity;
86
87 $shipmentItem->setFieldNoDemand("QUANTITY", $quantity);
88
89 if ($basketItem->isBundleParent())
90 {
91 $this->addBundleToCollection($basketItem);
92 }
93 }
94 }
95
105 public function createItem(BasketItem $basketItem)
106 {
107 if ($this->getShipment()->isShipped())
108 {
109 return null;
110 }
111
112 $shipmentItem = $this->getItemByBasketCode($basketItem->getBasketCode());
113 if ($shipmentItem !== null)
114 {
115 return $shipmentItem;
116 }
117
119 $itemClassName = static::getItemCollectionClassName();
120
121 $shipmentItem = $itemClassName::create($this, $basketItem);
122
123 $shipmentItem->setCollection($this);
124 $this->addItem($shipmentItem);
125
126 $shipment = $this->getShipment();
127
128 if ($basketItem->isBundleParent() && !$shipment->isSystem())
129 {
130 $this->addBundleToCollection($basketItem);
131 }
132
133 return $shipmentItem;
134 }
135
144 private function addBundleToCollection(BasketItem $basketItem)
145 {
146 $result = new Result();
147
149 if (!$bundleCollection = $basketItem->getBundleCollection())
150 {
151 throw new Main\ObjectNotFoundException('Entity "BundleCollection" not found');
152 }
153
154 if ($bundleCollection->getOrder() === null)
155 {
157 if ($basketCollection = $basketItem->getCollection())
158 {
159 if ($order = $basketCollection->getOrder())
160 {
161 $bundleCollection->setOrder($order);
162 }
163 }
164 }
165
167 $shipment = $this->getShipment();
168
170 if (!$shipmentCollection = $shipment->getCollection())
171 {
172 throw new Main\ObjectNotFoundException('Entity "ShipmentCollection" not found');
173 }
174
176 if (!$systemShipment = $shipmentCollection->getSystemShipment())
177 {
178 throw new Main\ObjectNotFoundException('Entity "System Shipment" not found');
179 }
180
182 if (!$systemShipmentItemCollection = $systemShipment->getShipmentItemCollection())
183 {
184 throw new Main\ObjectNotFoundException('Entity "ShipmentItemCollection" not found');
185 }
186
187 $baseQuantity = $basketItem->getQuantity();
188
190 if ($systemShipmentItem = $systemShipmentItemCollection->getItemByBasketCode($basketItem->getBasketCode()))
191 {
192 $baseQuantity = $systemShipmentItem->getQuantity();
193 }
194
195 $bundleBaseQuantity = $basketItem->getBundleBaseQuantity();
196
198 foreach ($bundleCollection as $bundleBasketItem)
199 {
200
201 if ($this->isExistsBasketItem($bundleBasketItem))
202 {
203 continue;
204 }
205
206 $bundleProductId = $bundleBasketItem->getProductId();
207
208 if (!isset($bundleBaseQuantity[$bundleProductId]))
209 throw new Main\ArgumentOutOfRangeException("bundle product id");
210
211 $quantity = $bundleBaseQuantity[$bundleProductId] * $baseQuantity;
212
213 if ($quantity == 0)
214 continue;
215
217 $itemClassName = static::getItemCollectionClassName();
218 $shipmentItemBundle = $itemClassName::create($this, $bundleBasketItem);
219 $this->addItem($shipmentItemBundle);
220
221
222
223 if ($shipment->isSystem())
224 {
225 $shipmentItemBundle->setFieldNoDemand('QUANTITY', $quantity);
226 }
227 else
228 {
229 $r = $shipmentItemBundle->setQuantity($quantity);
230 if (!$r->isSuccess())
231 {
232 $result->addErrors($r->getErrors());
233 }
234 }
235 }
236
237 return $result;
238 }
239
245 protected function addItem(Internals\CollectableEntity $shipmentItem)
246 {
247 parent::addItem($shipmentItem);
248
249 $this->shipmentItemIndexMap[$shipmentItem->getBasketCode()] = $shipmentItem->getInternalIndex();
250
252 $shipment = $this->getShipment();
253 $shipment->onShipmentItemCollectionModify(EventActions::ADD, $shipmentItem);
254 }
255
256 protected function createIndex()
257 {
258 $index = parent::createIndex();
259 $shipment = $this->getShipment();
260 return $shipment->getInternalIndex()."_".$index;
261 }
262
271 public function deleteItem($index)
272 {
273 $oldShipmentItem = parent::deleteItem($index);
274
275 unset($this->shipmentItemIndexMap[$oldShipmentItem->getBasketCode()]);
276
277 $shipment = $this->getShipment();
278 $shipment->onShipmentItemCollectionModify(EventActions::DELETE, $oldShipmentItem);
279 }
280
290 public function onItemModify(Internals\CollectableEntity $item, $name = null, $oldValue = null, $value = null)
291 {
292 $shipment = $this->getShipment();
293 return $shipment->onShipmentItemCollectionModify(EventActions::UPDATE, $item, $name, $oldValue, $value);
294 }
295
300 public function getItemByBasketCode($itemCode)
301 {
302 if (
303 isset($this->shipmentItemIndexMap[$itemCode])
304 && isset($this->collection[$this->shipmentItemIndexMap[$itemCode]])
305 )
306 {
307 return $this->collection[$this->shipmentItemIndexMap[$itemCode]];
308 }
309
310 return null;
311 }
312
317 public function getItemByBasketId($itemId)
318 {
319 $itemId = (int)$itemId;
320 foreach ($this->collection as $shippedItem)
321 {
323 $shippedItemId = (int)($shippedItem->getBasketId());
324 if ($itemId === $shippedItemId)
325 return $shippedItem;
326 }
327
328 return null;
329 }
330
336 public function getShippableItems()
337 {
338 $callback = function (ShipmentItem $shipmentItem)
339 {
340 return $shipmentItem->isShippable();
341 };
342
343 return new Internals\CollectionFilterIterator($this->getIterator(), $callback);
344 }
345
349 public function getSellableItems()
350 {
351 $callback = function (ShipmentItem $shipmentItem)
352 {
353 $basketItem = $shipmentItem->getBasketItem();
354 if ($basketItem)
355 return !$basketItem->isBundleChild();
356
357 return true;
358 };
359
360 return new Internals\CollectionFilterIterator($this->getIterator(), $callback);
361 }
362
367 public function getPrice()
368 {
369 $price = 0;
370
371 $sellableItems = $this->getSellableItems();
373 foreach ($sellableItems as $shipmentItem)
374 {
376 if ($basketItem = $shipmentItem->getBasketItem())
377 {
378 $price += PriceMaths::roundPrecision($basketItem->getPriceWithVat() * $shipmentItem->getQuantity());
379 }
380 }
381
382 return $price;
383 }
384
389 public function getWeight() : float
390 {
391 $weight = 0;
392
394 foreach ($this->getShippableItems() as $shipmentItem)
395 {
396 $basketItem = $shipmentItem->getBasketItem();
397
398 $weight += $basketItem->getWeight() * $shipmentItem->getQuantity();
399 }
400
401 return $weight;
402 }
403
407 public function getShipment()
408 {
409 return $this->shipment;
410 }
411
419 public function save()
420 {
421 $result = new Main\Entity\Result();
422
424 if (!$shipment = $this->getShipment())
425 {
426 throw new Main\ObjectNotFoundException('Entity "Shipment" not found');
427 }
428
430 if (!$shipmentCollection = $shipment->getCollection())
431 {
432 throw new Main\ObjectNotFoundException('Entity "ShipmentCollection" not found');
433 }
434
436 if (!$order = $shipmentCollection->getOrder())
437 {
438 throw new Main\ObjectNotFoundException('Entity "Order" not found');
439 }
440
441 $itemsFromDb = array();
442 if ($this->getShipment()->getId() > 0)
443 {
444 $itemsFromDbList = static::getList(
445 array(
446 "filter" => array("ORDER_DELIVERY_ID" => $this->getShipment()->getId()),
447 "select" => array("ID", 'BASKET_ID')
448 )
449 );
450 while ($itemsFromDbItem = $itemsFromDbList->fetch())
451 $itemsFromDb[$itemsFromDbItem["ID"]] = $itemsFromDbItem;
452 }
453
454
456 foreach ($this->collection as $shipmentItem)
457 {
459 if (!$basketItem = $shipmentItem->getBasketItem())
460 {
461 continue;
462 }
463
464 if ($basketItem->isBundleParent())
465 {
466 $this->addBundleToCollection($basketItem);
467 }
468 }
469
471 if (!$shipment = $this->getShipment())
472 {
473 throw new Main\ObjectNotFoundException('Entity "Shipment" not found');
474 }
475
476 $changeMeaningfulFields = array(
477 "QUANTITY",
478 "RESERVED_QUANTITY",
479 );
480
482 foreach ($this->collection as $shipmentItem)
483 {
485 if (!$basketItem = $shipmentItem->getBasketItem())
486 {
487 continue;
488 }
489
490 $isNew = (bool)($shipmentItem->getId() <= 0);
491 $isChanged = $shipmentItem->isChanged();
492
493 if ($order->getId() > 0 && $isChanged)
494 {
495 $logFields = array(
496 "BASKET_ID" => $basketItem->getId(),
497 "BASKET_ITEM_NAME" => $basketItem->getField("NAME"),
498 "BASKET_ITEM_PRODUCT_ID" => $basketItem->getField("PRODUCT_ID"),
499 "ORDER_DELIVERY_ID" => $shipmentItem->getField("ORDER_DELIVERY_ID"),
500 );
501
502 $fields = $shipmentItem->getFields();
503 $originalValues = $fields->getOriginalValues();
504
505 foreach($originalValues as $originalFieldName => $originalFieldValue)
506 {
507 if (in_array($originalFieldName, $changeMeaningfulFields) && $shipmentItem->getField($originalFieldName) != $originalFieldValue)
508 {
509 $logFields[$originalFieldName] = $shipmentItem->getField($originalFieldName);
510 if (!$isNew)
511 $logFields['OLD_'.$originalFieldName] = $originalFieldValue;
512 }
513 }
514 }
515
516 $r = $shipmentItem->save();
517 if ($r->isSuccess())
518 {
519 if ($order->getId() > 0 && $isChanged)
520 {
521 $registry = Registry::getInstance(static::getRegistryType());
522
524 $orderHistory = $registry->getOrderHistoryClassName();
525 $orderHistory::addLog(
526 'SHIPMENT_ITEM',
527 $order->getId(),
528 $isNew ? 'SHIPMENT_ITEM_ADD' : 'SHIPMENT_ITEM_UPDATE',
529 $shipmentItem->getId(),
530 $shipmentItem,
531 $logFields,
532 $orderHistory::SALE_ORDER_HISTORY_LOG_LEVEL_1
533 );
534 }
535 }
536 else
537 {
538 $result->addErrors($r->getErrors());
539 }
540
541 if (isset($itemsFromDb[$shipmentItem->getId()]))
542 {
543 unset($itemsFromDb[$shipmentItem->getId()]);
544 }
545 }
546
548 if (!$basket = $order->getBasket())
549 {
550 throw new Main\ObjectNotFoundException('Entity "Basket" not found');
551 }
552
553 foreach ($itemsFromDb as $k => $v)
554 {
555 $v['ENTITY_REGISTRY_TYPE'] = static::getRegistryType();
556
558 $event = new Main\Event('sale', "OnBeforeSaleShipmentItemDeleted", array(
559 'VALUES' => $v,
560 ));
561 $event->send();
562
563 static::deleteInternal($k);
564
566 $event = new Main\Event('sale', "OnSaleShipmentItemDeleted", array(
567 'VALUES' => $v,
568 ));
569 $event->send();
570
572 if ($basketItem = $basket->getItemById($k))
573 {
574 $registry = Registry::getInstance(static::getRegistryType());
575
577 $orderHistory = $registry->getOrderHistoryClassName();
578 $orderHistory::addAction(
579 'SHIPMENT',
580 $order->getId(),
581 'SHIPMENT_ITEM_BASKET_REMOVED',
582 $shipment->getId(),
583 null,
584 array(
585 'NAME' => $basketItem->getField('NAME'),
586 'QUANTITY' => $basketItem->getQuantity(),
587 'PRODUCT_ID' => $basketItem->getProductId(),
588 )
589 );
590 }
591 }
592
593 if ($order->getId() > 0)
594 {
595 $registry = Registry::getInstance(static::getRegistryType());
596
598 $orderHistory = $registry->getOrderHistoryClassName();
599 $orderHistory::collectEntityFields('SHIPMENT_ITEM', $order->getId());
600 }
601
602 return $result;
603 }
604
608 private static function createShipmentItemCollectionObject()
609 {
610 $registry = Registry::getInstance(static::getRegistryType());
611 $shipmentItemCollectionClassName = $registry->getShipmentItemCollectionClassName();
612
613 return new $shipmentItemCollectionClassName();
614 }
615
619 public static function getRegistryType()
620 {
622 }
623
627 private static function getItemCollectionClassName()
628 {
629 $registry = Registry::getInstance(static::getRegistryType());
630 return $registry->getShipmentItemClassName();
631 }
632
640 public static function load(Shipment $shipment)
641 {
643 $shipmentItemCollection = static::createShipmentItemCollectionObject();
644 $shipmentItemCollection->shipment = $shipment;
645
646 if ($shipment->getId() > 0)
647 {
648
650 if (!$shipmentCollection = $shipment->getCollection())
651 {
652 throw new Main\ObjectNotFoundException('Entity "ShipmentCollection" not found');
653 }
654
656 if (!$order = $shipmentCollection->getOrder())
657 {
658 throw new Main\ObjectNotFoundException('Entity "Order" not found');
659 }
660
662 $itemClassName = static::getItemCollectionClassName();
663 $shipmentItemList = $itemClassName::loadForShipment($shipment->getId());
664
666 foreach ($shipmentItemList as $shipmentItem)
667 {
668 $shipmentItem->setCollection($shipmentItemCollection);
669 $shipmentItemCollection->addItem($shipmentItem);
670
671 if (!$basketItem = $shipmentItem->getBasketItem())
672 {
673 $msg = Loc::getMessage("SALE_SHIPMENT_ITEM_COLLECTION_BASKET_ITEM_NOT_FOUND", array(
674 '#BASKET_ITEM_ID#' => $shipmentItem->getBasketId(),
675 '#SHIPMENT_ID#' => $shipment->getId(),
676 '#SHIPMENT_ITEM_ID#' => $shipmentItem->getId(),
677 ));
678
679 $r = new Result();
680 $r->addError( new ResultError($msg, 'SALE_SHIPMENT_ITEM_COLLECTION_BASKET_ITEM_NOT_FOUND'));
681
682
683 $registry = Registry::getInstance(static::getRegistryType());
685 $entityMarker = $registry->getEntityMarkerClassName();
686 $entityMarker::addMarker($order, $shipment, $r);
687 if (!$shipment->isSystem())
688 {
689 $shipment->setField('MARKED', 'Y');
690 }
691 }
692 }
693 }
694
695 return $shipmentItemCollection;
696 }
697
703 public static function getList(array $parameters = array())
704 {
705 return Internals\ShipmentItemTable::getList($parameters);
706 }
707
712 protected function deleteInternal($primary)
713 {
714 return Internals\ShipmentItemTable::deleteWithItems($primary);
715 }
716
726 public function onBeforeBasketItemDelete(BasketItem $basketItem)
727 {
728 $result = new Result();
729
730 $r = $this->deleteByBasketItem($basketItem);
731 if (!$r->isSuccess())
732 {
733 $result->addErrors($r->getErrors());
734 }
735
736 return $result;
737 }
738
752 public function onBasketModify($action, BasketItem $basketItem, $name = null, $oldValue = null, $value = null)
753 {
754 $result = new Result();
755
756 if ($action === EventActions::ADD)
757 {
758 $shipmentItem = $this->createItem($basketItem);
759 if ($shipmentItem)
760 {
761 $shipmentItem->onBasketModify($action, $basketItem, $name, $oldValue, $value);
762 }
763
764 return $result;
765 }
766 elseif ($action === EventActions::UPDATE)
767 {
768 $shipmentItem = $this->getItemByBasketCode($basketItem->getBasketCode());
769
770 if (!$shipmentItem)
771 {
772 $shipmentItem = $this->createItem($basketItem);
773 }
774
775 $r = $shipmentItem->setField('QUANTITY', $value);
776 if (!$r->isSuccess())
777 {
778 return $result->addErrors($r->getErrors());
779 }
780 }
781
782 return $result;
783 }
784
790 protected function isExistsBasketItem(BasketItem $basketItem)
791 {
793 foreach ($this->collection as $shipmentItem)
794 {
795 if ($shipmentItem->getBasketCode() == $basketItem->getBasketCode())
796 return true;
797 }
798
799 return false;
800 }
801
811 public function deleteByBasketItem(BasketItem $basketItem)
812 {
813 $result = new Result();
814 $systemShipmentItem = null;
815
817 if (!$shipment = $this->getShipment())
818 {
819 throw new Main\ObjectNotFoundException('Entity "Shipment" not found');
820 }
821
823 foreach ($this->collection as $shipmentItem)
824 {
825 if ($shipmentItem->getBasketCode() == $basketItem->getBasketCode())
826 {
827 if ($shipment->isSystem())
828 {
829 $systemShipmentItem = $shipmentItem;
830 continue;
831 }
832
833 $r = $shipmentItem->delete();
834 if (!$r->isSuccess())
835 {
836 $result->addErrors($r->getErrors());
837 }
838 }
839 }
840
841 if ($systemShipmentItem !== null)
842 {
843 if ($systemShipmentItem->getReservedQuantity() > 0)
844 {
846 $r = $systemShipmentItem->tryUnreserve();
847 if (!$r->isSuccess())
848 {
849 $result->addErrors($r->getErrors());
850 }
851 }
852
853 if ($result->isSuccess())
854 {
855 $systemShipmentItem->setFieldNoDemand('QUANTITY', 0);
856 $r = $systemShipmentItem->delete();
857 if (!$r->isSuccess())
858 {
859 $result->addErrors($r->getErrors());
860 }
861 }
862 }
863
864 return $result;
865 }
866
870 public function isEmpty()
871 {
872 if (count($this->collection) == 0)
873 return true;
874
876 foreach ($this->collection as $item)
877 {
878 if ($item->getQuantity() > 0)
879 return false;
880 }
881
882 return true;
883 }
884
890 public function getBasketItemQuantity(BasketItem $basketItem)
891 {
892 $quantity = 0;
893
894 $shipmentItem = $this->getItemByBasketCode($basketItem->getBasketCode());
895 if ($shipmentItem)
896 {
897 $quantity = $shipmentItem->getQuantity();
898 }
899
900 return $quantity;
901 }
902
909 public function isExistBasketItem(BasketItem $basketItem)
910 {
912 foreach ($this->collection as $shipmentItem)
913 {
914 if ($shipmentItem->getBasketCode() == $basketItem->getBasketCode())
915 {
916 return true;
917 }
918 }
919
920 return false;
921 }
922
932 public function createClone(\SplObjectStorage $cloneEntity)
933 {
934 if ($this->isClone() && $cloneEntity->contains($this))
935 {
936 return $cloneEntity[$this];
937 }
938
940 $shipmentItemCollectionClone = parent::createClone($cloneEntity);
941
943 if ($shipment = $this->shipment)
944 {
945 if (!$cloneEntity->contains($shipment))
946 {
947 $cloneEntity[$shipment] = $shipment->createClone($cloneEntity);
948 }
949
950 if ($cloneEntity->contains($shipment))
951 {
952 $shipmentItemCollectionClone->shipment = $cloneEntity[$shipment];
953 }
954 }
955
956 return $shipmentItemCollectionClone;
957 }
958
964 public function getErrorEntity($value)
965 {
966 $className = null;
967
969 foreach ($this->collection as $shipmentItem)
970 {
971 if ($className = $shipmentItem->getErrorEntity($value))
972 {
973 break;
974 }
975 }
976
977 return $className;
978 }
979
985 public function canAutoFixError($value)
986 {
987 $autoFix = false;
988
990 foreach ($this->collection as $shipmentItem)
991 {
992 if ($autoFix = $shipmentItem->canAutoFixError($value))
993 {
994 break;
995 }
996 }
997 return $autoFix;
998 }
999
1000}
static loadMessages($file)
Definition loc.php:64
static getMessage($code, $replace=null, $language=null)
Definition loc.php:29
static roundPrecision($value)
static getInstance($type)
Definition registry.php:183
static getList(array $parameters=array())
onBasketModify($action, BasketItem $basketItem, $name=null, $oldValue=null, $value=null)
onItemModify(Internals\CollectableEntity $item, $name=null, $oldValue=null, $value=null)