43 public function resetCollection()
47 $deliveryInfo = array();
49 if (
count($this->collection) > 0)
52 foreach ($this->collection as $shipment)
54 if (empty($deliveryInfo))
56 if ($shipment->isSystem() && $shipment->getDeliveryId() > 0)
58 foreach (static::getClonedFields() as $field)
60 if (strval(trim($shipment->getField($field))) !=
'')
61 $deliveryInfo[$field] = trim($shipment->getField($field));
69 $systemShipment = $this->getSystemShipment();
72 $systemShipmentItemCollection = $systemShipment->getShipmentItemCollection();
75 $basket = $this->
getOrder()->getBasket();
76 $systemShipmentItemCollection->resetCollection($basket);
78 if (!empty($deliveryInfo))
80 $systemShipment->setFieldsNoDemand($deliveryInfo);
88 $r = $this->tryReserve();
91 $result->addErrors($r->getErrors());
114 public function createItem(
Delivery\Services\
Base $delivery =
null)
117 $shipmentClassName = static::getItemCollectionClassName();
118 $shipment = $shipmentClassName::create($this, $delivery);
119 $this->addItem($shipment);
131 protected function addItem(Internals\CollectableEntity $shipment)
134 $shipment = parent::addItem($shipment);
154 public function deleteItem($index)
156 $result =
new Result();
158 $oldItem = parent::deleteItem($index);
161 if ($oldItem->getId() > 0 && !$oldItem->isSystem() && ($systemShipment = $this->getSystemShipment()) && $systemShipment->getId() == 0)
163 $r = $this->cloneShipment($oldItem, $systemShipment);
164 if (!$r->isSuccess())
166 $result->addErrors($r->getErrors());
190 public function onItemModify(Internals\CollectableEntity $item, $name =
null, $oldValue =
null, $value =
null)
195 if ($item instanceof Shipment)
223 $shipmentCollection = static::createShipmentCollectionObject();
224 $shipmentCollection->setOrder(
$order);
229 $shipmentClassName = static::getItemCollectionClassName();
230 $shipmentList = $shipmentClassName::loadForOrder(
$order->getId());
232 foreach ($shipmentList as $shipment)
234 $shipment->setCollection($shipmentCollection);
235 $shipmentCollection->addItem($shipment);
238 $controller = Internals\CustomFieldsController::getInstance();
239 $controller->initializeCollection($shipmentCollection);
242 return $shipmentCollection;
248 private static function createShipmentCollectionObject()
251 $className = $registry->getShipmentCollectionClassName();
253 return new $className();
269 public function getSystemShipment()
272 foreach ($this->collection as $shipment)
274 if ($shipment->isSystem())
281 $shipmentClassName = static::getItemCollectionClassName();
282 $shipment = $shipmentClassName::createSystem($this);
283 $this->addItem($shipment);
293 public function isExistsSystemShipment()
296 foreach ($this->collection as $shipment)
298 if ($shipment->isSystem())
313 public function save()
315 $result =
new Entity\Result();
320 throw new Main\ObjectNotFoundException(
'Entity "Order" not found');
323 $itemsFromDb = array();
326 $itemsFromDbList = static::getList(
328 "filter" => array(
"ORDER_ID" =>
$order->getId()),
329 "select" => array(
"ID" ,
"DELIVERY_NAME",
"DELIVERY_ID")
332 while ($itemsFromDbItem = $itemsFromDbList->fetch())
333 $itemsFromDb[$itemsFromDbItem[
"ID"]] = $itemsFromDbItem;
337 foreach ($this->collection as $shipment)
339 if ($shipment->isSystem())
342 if (($systemShipment = $this->getSystemShipment()) && $systemShipment->getId() == 0)
345 $r = $this->cloneShipment($shipment, $systemShipment);
352 $result->addErrors($r->getErrors());
357 $changeMeaningfulFields = array(
360 "CUSTOM_PRICE_DELIVERY",
371 "BASE_PRICE_DELIVERY",
376 foreach ($this->collection as $shipment)
378 $isNew = (bool)($shipment->getId() <= 0);
383 $logFields = array();
386 $fields = $shipment->getFields();
387 $originalValues = $fields->getOriginalValues();
389 foreach($originalValues as $originalFieldName => $originalFieldValue)
391 if (in_array($originalFieldName, $changeMeaningfulFields) && $shipment->getField($originalFieldName) != $originalFieldValue)
393 $logFields[$originalFieldName] = $shipment->getField($originalFieldName);
395 $logFields[
'OLD_'.$originalFieldName] = $originalFieldValue;
401 $r = $shipment->save();
411 $orderHistory = $registry->getOrderHistoryClassName();
412 $orderHistory::addLog(
415 $isNew ?
'SHIPMENT_ADD' :
'SHIPMENT_UPDATE',
419 $orderHistory::SALE_ORDER_HISTORY_LOG_LEVEL_1
422 $orderHistory::addAction(
437 $result->addErrors($r->getErrors());
440 if (isset($itemsFromDb[$shipment->getId()]))
441 unset($itemsFromDb[$shipment->getId()]);
444 foreach ($itemsFromDb as $k => $v)
446 $v[
'ENTITY_REGISTRY_TYPE'] = static::getRegistryType();
449 $event =
new Main\Event(
'sale',
"OnBeforeSaleShipmentDeleted", array(
458 $event =
new Main\Event(
'sale',
"OnSaleShipmentDeleted", array(
468 $orderHistory = $registry->getOrderHistoryClassName();
469 $orderHistory::addAction(
477 'DELIVERY_NAME' => $v[
'DELIVERY_NAME'],
478 'DELIVERY_ID' => $v[
'DELIVERY_ID'],
485 $entityMarker = $registry->getEntityMarkerClassName();
486 $entityMarker::deleteByFilter(array(
487 '=ORDER_ID' =>
$order->getId(),
488 '=ENTITY_TYPE' => $entityMarker::ENTITY_TYPE_SHIPMENT,
500 $orderHistory = $registry->getOrderHistoryClassName();
501 $orderHistory::collectEntityFields(
'SHIPMENT',
$order->getId());
524 public function cloneShipment(
Shipment $parentShipment,
Shipment $childShipment)
526 foreach (static::getClonedFields() as $fieldName)
529 $childShipment->
setFieldNoDemand($fieldName, $parentShipment->getField($fieldName));
557 public function isShipped()
559 if (!empty($this->collection) && is_array($this->collection))
562 foreach ($this->collection as $shipment)
564 if ($shipment->isSystem())
566 if (!$shipment->isEmpty())
574 if (!$shipment->isShipped() && !$shipment->isEmpty())
591 public function hasShipped()
593 if (!empty($this->collection) && is_array($this->collection))
596 foreach ($this->collection as $shipment)
598 if ($shipment->isSystem())
603 if ($shipment->isShipped() && !$shipment->isEmpty())
618 public function isMarked()
620 if (!empty($this->collection) && is_array($this->collection))
623 foreach ($this->collection as $shipment)
625 if ($shipment->isSystem())
628 if ($shipment->isMarked())
641 public function isReserved()
643 if (!empty($this->collection) && is_array($this->collection))
646 foreach ($this->collection as $shipment)
648 if ($shipment->isSystem())
650 if (
count($this->collection) == 1)
651 return $shipment->isReserved();
656 if (!$shipment->isReserved())
671 public function isAllowDelivery()
673 if (!empty($this->collection) && is_array($this->collection))
676 foreach ($this->collection as $shipment)
678 if ($shipment->isSystem())
680 if (!$shipment->isEmpty())
688 if (!$shipment->isAllowDelivery() && !$shipment->isEmpty())
703 public function hasAllowDelivery()
710 if ($shipment->isAllowDelivery())
726 return $this->getSystemShipment()->isEmpty();
734 public function allowDelivery()
743 $r = $shipment->allowDelivery();
744 if (!$r->isSuccess())
746 $result->addErrors($r->getErrors());
756 public function disallowDelivery()
758 $result =
new Result();
765 $r = $shipment->disallowDelivery();
766 if (!$r->isSuccess())
768 $result->addErrors($r->getErrors());
779 public function tryReserve()
781 $result =
new Result();
784 foreach ($this->collection as $shipment)
786 if ($shipment->isReserved() || $shipment->isShipped())
789 $r = $shipment->tryReserve();
790 if (!$r->isSuccess())
792 $result->addErrors($r->getErrors());
794 elseif ($r->hasWarnings())
796 $result->addWarnings($r->getWarnings());
800 $entityMarker = $registry->getEntityMarkerClassName();
801 $entityMarker::addMarker($this->
getOrder(), $shipment, $r);
802 if (!$shipment->isSystem())
804 $shipment->setField(
'MARKED',
'Y');
820 public function tryUnreserve()
822 $result =
new Result();
826 throw new Main\ObjectNotFoundException(
'Entity "Order" not found');
829 foreach ($this->collection as $shipment)
831 if ($shipment->isShipped())
834 !Internals\ActionEntity::isTypeExists(
840 Internals\ActionEntity::add(
844 'METHOD' =>
'Bitrix\Sale\Shipment::updateReservedFlag',
845 'PARAMS' => array($shipment)
853 $r = $shipment->tryUnreserve();
854 if (!$r->isSuccess())
856 if (!$shipment->isSystem())
861 $entityMarker = $registry->getEntityMarkerClassName();
862 $entityMarker::addMarker(
$order, $shipment, $r);
864 $shipment->setField(
'MARKED',
'Y');
866 $result->addErrors($r->getErrors());
868 elseif ($r->hasWarnings())
870 $result->addWarnings($r->getWarnings());
889 public function onBeforeBasketItemDelete(BasketItem $basketItem)
891 $result =
new Result();
894 foreach ($this->collection as $shipment)
896 $r = $shipment->onBeforeBasketItemDelete($basketItem);
897 if (!$r->isSuccess())
899 $result->addErrors($r->getErrors());
920 public function onBasketModify($action, BasketItemBase $basketItem, $name =
null, $oldValue =
null, $value =
null) : Result
922 $result =
new Result();
924 if (!($basketItem instanceof BasketItem))
932 if ($order->getId() == 0 && !
$order->isMathActionOnly())
941 return $this->getSystemShipment()->onBasketModify($action, $basketItem, $name, $oldValue, $value);
948 if ($name ==
'QUANTITY')
950 if (!$this->isAllowAutoEdit($basketItem))
952 $result = $this->checkDistributedQuantity($basketItem, $value);
953 if (!$result->isSuccess())
959 $shipment = $this->getItemForAutoEdit($basketItem);
961 if ($value - $oldValue > 0)
963 $r = $this->getSystemShipment()->onBasketModify($action, $basketItem, $name, $oldValue, $value);
964 if (!$r->isSuccess())
966 return $result->addErrors($r->getErrors());
972 $r = $shipment->onBasketModify($action, $basketItem, $name, $oldValue, $value);
973 if (!$r->isSuccess())
975 $result->addErrors($r->getErrors());
980 if ($value - $oldValue < 0)
982 $r = $this->getSystemShipment()->onBasketModify($action, $basketItem, $name, $oldValue, $value);
983 if (!$r->isSuccess())
985 return $result->addErrors($r->getErrors());
989 elseif (in_array($name, [
'WEIGHT',
'PRICE']))
994 $shipment->onBasketModify($action, $basketItem, $name, $value, $oldValue);
1007 private function getItemForAutoEdit(BasketItem $basketItem)
1009 if ($this->isAllowAutoEdit($basketItem))
1027 protected function isAllowAutoEdit(BasketItem $basketItem)
1029 if ($this->
count() === 1
1032 $this->
count() === 2
1034 $this->isExistsSystemShipment()
1038 if (!$this->getSystemShipment()->isExistBasketItem($basketItem)
1039 || (
int)$basketItem->getId() === 0
1044 if (!$shipment->isAllowDelivery()
1045 && !$shipment->isCanceled()
1046 && !$shipment->isShipped()
1050 if ($deliveryService = $shipment->getDelivery())
1052 return $deliveryService->isAllowEditShipment();
1070 private function checkDistributedQuantity(BasketItem $basketItem, $value)
1072 $result =
new Result();
1074 $basketItemQuantity = $this->getBasketItemDistributedQuantity($basketItem);
1075 if ($basketItemQuantity > $value)
1077 $result->addError(
new ResultError(
1080 '#PRODUCT_NAME#' => $basketItem->getField(
"NAME"),
1081 '#BASKET_ITEM_QUANTITY#' => $basketItemQuantity,
1082 '#BASKET_ITEM_MEASURE#' => $basketItem->getField(
"MEASURE_NAME"),
1083 '#QUANTITY#' => $basketItemQuantity - $value
1086 'SALE_ORDER_SYSTEM_SHIPMENT_LESS_QUANTITY')
1104 public function onOrderModify($name, $oldValue, $value)
1106 $result =
new Result();
1115 foreach ($this->collection as $shipment)
1117 if ($shipment->isShipped())
1129 'SALE_ORDER_CANCEL_SHIPMENT_EXIST_SHIPPED'
1136 $this->tryUnreserve();
1141 foreach ($this->collection as $shipment)
1143 if ($shipment->needReservation())
1146 $r = $shipment->tryReserve();
1147 if (!$r->isSuccess())
1152 $entityMarker = $registry->getEntityMarkerClassName();
1153 $entityMarker::addMarker($this->
getOrder(), $shipment, $r);
1154 if (!$shipment->isSystem())
1156 $shipment->setField(
'MARKED',
'Y');
1159 $result->addErrors($r->getErrors());
1171 foreach ($this->collection as $shipment)
1173 if ($shipment->isSystem())
1176 $shipment->setField(
'MARKED', $value);
1195 $r = $this->calculateDelivery();
1196 if (!$r->isSuccess())
1198 $result->addErrors($r->getErrors());
1207 public function calculateDelivery()
1212 $calculatedDeliveries = [];
1219 if ($shipment->getDeliveryId() == 0)
1222 if ($shipment->isCustomPrice())
1224 $priceDelivery = $shipment->getPrice();
1227 $calcResult->setDeliveryPrice($priceDelivery);
1232 $calcResult = $shipment->calculateDelivery();
1233 if (!$calcResult->isSuccess())
1235 $result->addErrors($calcResult->getErrors());
1239 $priceDelivery = $calcResult->getPrice();
1240 if ($priceDelivery < 0)
1242 $result->addError(
new ResultError(
Loc::getMessage(
'SALE_ORDER_SHIPMENT_WRONG_DELIVERY_PRICE'),
'WRONG_DELIVERY_PRICE'));
1248 $shipment->setField(
'BASE_PRICE_DELIVERY', $priceDelivery);
1250 $calculatedDeliveries[] = $calcResult;
1253 $result->setData([
'CALCULATED_DELIVERIES' => $calculatedDeliveries]);
1261 public function resetData()
1268 $shipment->resetData();
1279 public function getBasketItemDistributedQuantity(BasketItem $basketItem)
1288 $allQuantity += $shipment->getBasketItemQuantity($basketItem);
1291 return $allQuantity;
1301 public function getBasketItemShippedQuantity(BasketItem $basketItem)
1306 foreach ($this->collection as $shipment)
1308 if ($shipment->isShipped())
1310 $quantity += $shipment->getShipmentItemCollection()->getBasketItemQuantity($basketItem);
1324 public function isExistBasketItem(BasketItem $basketItem, $includeSystemShipment =
false)
1327 foreach ($this->collection as $shipment)
1329 if (!$includeSystemShipment && $shipment->isSystem())
1334 return $shipment->isExistBasketItem($basketItem);
1342 public function getBasePriceDelivery()
1350 $sum += $shipment->getField(
'BASE_PRICE_DELIVERY');
1359 public function getPriceDelivery()
1367 $sum += $shipment->getPrice();
1378 public function getItemByShipmentCode($itemCode)
1381 foreach ($this->collection as $shipment)
1383 $shipmentCode = $shipment->getShipmentCode();
1384 if ($itemCode == $shipmentCode)
1402 $result =
new Result();
1405 foreach ($this->collection as $shipment)
1407 if ($shipment->isSystem())
1412 $r = $shipment->verify();
1413 if (!$r->isSuccess())
1415 $result->addErrors($r->getErrors());
1420 $entityMarker = $registry->getEntityMarkerClassName();
1421 $entityMarker::addMarker($this->
getOrder(), $shipment, $r);
1423 $shipment->setField(
'MARKED',
'Y');
1436 public function createClone(\SplObjectStorage $cloneEntity)
1438 if ($this->
isClone() && $cloneEntity->contains($this))
1440 return $cloneEntity[$this];
1444 $shipmentCollectionClone = parent::createClone($cloneEntity);
1448 if ($cloneEntity->contains($this->order))
1450 $shipmentCollectionClone->order = $cloneEntity[
$this->order];
1454 return $shipmentCollectionClone;
1462 public function getErrorEntity($value)
1466 foreach ($this->collection as $shipment)
1468 if ($className = $shipment->getErrorEntity($value))
1482 public function canAutoFixError($value)
1487 foreach ($this->collection as $shipment)
1489 if ($autoFix = $shipment->canAutoFixError($value))
1502 public static function updateReservedFlag(ShipmentCollection
$collection)
1504 $result =
new Result();
1509 $shipmentClassName = static::getItemCollectionClassName();
1510 $r = $shipmentClassName::updateReservedFlag($shipment);
1511 if (!$r->isSuccess())
1513 $result->addErrors($r->getErrors());
1516 if ($r->hasWarnings())
1518 $result->addWarnings($r->getWarnings());
1528 private static function getItemCollectionClassName()
1531 return $registry->getShipmentClassName();
1538 public static function getList(array $parameters = array())
1540 return Internals\ShipmentTable::getList($parameters);
1549 return Internals\ShipmentTable::deleteWithItems($primary);
1557 Internals\ShipmentExtraServiceTable::deleteByShipmentId($shipmentId);
1566 $callback =
function (
Shipment $shipment)
1568 return !$shipment->isSystem();