31 return [
'QUANTITY',
'RESERVED_QUANTITY',
'XML_ID'];
55 'XML_ID' => static::generateXmlId(),
56 'RESERVED_QUANTITY' => 0
64 $shipmentItem = static::createShipmentItemObject($fields);
89 public function delete()
95 $oldEntityValues = $this->fields->getOriginalValues();
97 $event =
new Main\Event(
'sale',
"OnBeforeSaleShipmentItemEntityDeleted", [
99 'VALUES' => $oldEntityValues,
103 foreach($event->getResults() as $eventResult)
105 if($eventResult->getType() == Main\EventResult::ERROR)
108 Loc::getMessage(
'SALE_EVENT_ON_BEFORE_SALESHIPMENTITEM_ENTITY_DELETED_ERROR'),
109 'SALE_EVENT_ON_BEFORE_SALESHIPMENTITEM_ENTITY_DELETED_ERROR'
111 if ($eventResultData = $eventResult->getParameters())
113 if (isset($eventResultData) && $eventResultData instanceof
ResultError)
115 $errorMsg = $eventResultData;
119 $result->addError($errorMsg);
123 if (!$result->isSuccess())
129 if (!$shipment->isSystem())
131 if ($shipment->isShipped())
136 throw new Main\ObjectNotFoundException(
'Entity "BasketItem" not found');
141 Loc::getMessage(
'SALE_SHIPMENT_ITEM_SHIPMENT_ALREADY_SHIPPED_CANNOT_EDIT'),
142 'SALE_SHIPMENT_ITEM_SHIPMENT_ALREADY_SHIPPED_CANNOT_EDIT'
149 $r = $this->
setField(
"QUANTITY", 0);
151 if (!$r->isSuccess())
153 return $result->addErrors($r->getErrors());
156 elseif ($shipment->isSystem() && $this->getQuantity() > 1e-10)
158 throw new \ErrorException(
'System shipment not empty');
161 $r = parent::delete();
162 if (!$r->isSuccess())
164 $result->addErrors($r->getErrors());
168 $event =
new Main\Event(
'sale',
"OnSaleShipmentItemEntityDeleted", [
170 'VALUES' => $oldEntityValues,
174 foreach($event->getResults() as $eventResult)
176 if($eventResult->getType() == Main\EventResult::ERROR)
178 $errorMsg =
new ResultError(
179 Loc::getMessage(
'SALE_EVENT_ON_SALESHIPMENTITEM_ENTITY_DELETED_ERROR'),
180 'SALE_EVENT_ON_SALESHIPMENTITEM_ENTITY_DELETED_ERROR'
182 $eventResultData = $eventResult->getParameters();
183 if (isset($eventResultData) && $eventResultData instanceof ResultError)
185 $errorMsg = $eventResultData;
188 $result->addError($errorMsg);
200 return (
float)$this->getField(
'QUANTITY');
220 $order = $shipment->getCollection()->getOrder();
222 if ($shipment->isShipped())
224 return $result->addError(
226 Loc::getMessage(
'SALE_SHIPMENT_ITEM_SHIPMENT_ALREADY_SHIPPED_CANNOT_EDIT'),
227 'SALE_SHIPMENT_ITEM_SHIPMENT_ALREADY_SHIPPED_CANNOT_EDIT'
232 if ($name ==
"QUANTITY")
243 $deltaQuantity = $value - $oldValue;
247 $systemShipment = $shipment->getCollection()->getSystemShipment();
249 $systemBasketItemQuantity = $systemShipment->getBasketItemQuantity(
$basketItem);
250 if ($systemBasketItemQuantity < abs($deltaQuantity))
257 if (!($parentBasketItem =
$basketItem->getParentBasketItem()))
259 throw new Main\ObjectNotFoundException(
'Entity "Parent Basket Item" not found');
262 $errorBasketCode = $parentBasketItem->getBasketCode();
265 if (isset(static::$errors[$errorBasketCode][
$basketItem->getField(
'ORDER_DELIVERY_BASKET_ID')][
'STORE_QUANTITY_LARGER_ALLOWED']))
267 static::$errors[$errorBasketCode][
$basketItem->getField(
'ORDER_DELIVERY_BASKET_ID')][
'STORE_QUANTITY_LARGER_ALLOWED'] +=
$basketItem->getQuantity();
274 'SALE_SHIPMENT_ITEM_LESS_AVAILABLE_QUANTITY_2',
278 ),
'SALE_SHIPMENT_ITEM_LESS_AVAILABLE_QUANTITY'
282 static::$errors[$errorBasketCode][
$basketItem->getField(
'ORDER_DELIVERY_BASKET_ID')][
'STORE_QUANTITY_LARGER_ALLOWED'] =
$basketItem->getQuantity();
294 $r = $this->calculateDelivery();
295 if (!$r->isSuccess())
297 $result->addErrors($r->getErrors());
309 throw new Main\ObjectNotFoundException(
'Entity "ShipmentItemStoreCollection" not found');
314 if ((
int)$value === 0)
316 $basketItemName =
Loc::getMessage(
"SALE_SHIPMENT_ITEM_BASKET_WRONG_BASKET_ITEM");
317 $basketItemProductId =
'1';
322 $basketItemProductId =
$basketItem->getProductId();
328 $orderHistory = $registry->getOrderHistoryClassName();
329 $orderHistory::addAction(
332 'SHIPMENT_ITEM_BASKET_REMOVED',
336 'NAME' => $basketItemName,
337 'PRODUCT_ID' => $basketItemProductId,
344 $shipmentItemStore->delete();
352 if (!$r->isSuccess())
354 $result->addErrors($r->getErrors());
359 if ($barcodeQuantity > $value)
364 'BARCODE_MORE_ITEM_QUANTITY'
380 return parent::onFieldModify($name, $oldValue, $value);
388 public function checkMarkingCodeOnDeducted()
390 $result =
new Result();
403 return $result->addError(
406 'SALE_SHIPMENT_ITEM_MARKING_CODE_LESS_ITEM_QUANTITY_LONG_2',
407 [
'#PRODUCT_NAME#' => $this->
getBasketItem()->getField(
'NAME')])
415 if ($itemStore->getMarkingCode() ===
'')
417 return $result->addError(
420 'SALE_SHIPMENT_ITEM_MARKING_CODE_LESS_ITEM_QUANTITY_LONG_2',
421 [
'#PRODUCT_NAME#' => $this->
getBasketItem()->getField(
'NAME')])
438 return $this->
setField(
'QUANTITY', (
float)$quantity);
443 if ($name ===
'RESERVED_QUANTITY')
447 $result = parent::setField($name, $value);
448 if ($result->isSuccess())
450 $this->setReserveQuantity($value, $oldValue);
456 return parent::setField($name, $value);
461 if ($name ===
'RESERVED_QUANTITY')
465 parent::setFieldNoDemand($name, $value);
467 $this->setReserveQuantity($value, $oldValue);
472 parent::setFieldNoDemand($name, $value);
475 protected function setReserveQuantity($value, $oldValue)
481 $reserveCollection =
$basketItem->getReserveQuantityCollection();
482 if (!$reserveCollection)
487 if ($value - $oldValue > 0)
490 foreach ($reserveCollection as $reserve)
495 if ($reserve ===
null)
497 $reserve = $reserveCollection->create();
500 $settableReserveQuantity = $reserve->getQuantity() + $value - $oldValue;
501 $reserve->setFieldNoDemand(
'QUANTITY', $settableReserveQuantity);
505 $delta = abs($value - $oldValue);
508 foreach ($reserveCollection as $reserve)
515 if ($reserve->getQuantity() > $delta)
517 $settableReserveQuantity = $reserve->getQuantity() - $delta;
518 $reserve->setFieldNoDemand(
'QUANTITY', $settableReserveQuantity);
523 $delta -= $reserve->getQuantity();
524 $reserve->deleteNoDemand();
536 return $this->getField(
'RESERVED_QUANTITY');
544 return (
int)$this->getField(
'BASKET_ID');
586 public function save()
588 $this->checkCallingContext();
592 $id = $this->getId();
593 $fields = $this->fields->getValues();
598 $order = $shipment->getCollection()->getOrder();
603 $event =
new Main\Event(
'sale',
'OnBeforeSaleShipmentItemEntitySaved', [
605 'VALUES' => $this->fields->getOriginalValues()
612 $fields = $this->fields->getChangedValues();
614 if (!empty($fields) && is_array($fields))
616 if (!$shipment->isSystem())
618 if (isset($fields[
"QUANTITY"]) && (floatval($fields[
"QUANTITY"]) == 0))
625 if (!$r->isSuccess())
630 $orderHistory = $registry->getOrderHistoryClassName();
631 $orderHistory::addAction(
634 'SHIPMENT_ITEM_UPDATE_ERROR',
637 [
"ERROR" => $r->getErrorMessages()]
640 $result->addErrors($r->getErrors());
644 if ($resultData = $r->getData())
645 $result->setData($resultData);
648 if ($order && $order->getId() > 0)
653 $orderHistory = $registry->getOrderHistoryClassName();
654 $orderHistory::collectEntityFields(
'SHIPMENT_ITEM_STORE', $order->getId(), $id);
659 $fields[
'ORDER_DELIVERY_ID'] = $this->getParentShipmentId();
662 $fields[
'DATE_INSERT'] =
new Main\Type\DateTime();
665 $fields[
"BASKET_ID"] = $this->basketItem->getId();
668 if ($fields[
'BASKET_ID'] <= 0)
673 if (!isset($fields[
"QUANTITY"]) || (floatval($fields[
"QUANTITY"]) == 0))
679 if (!$r->isSuccess())
684 $orderHistory = $registry->getOrderHistoryClassName();
685 $orderHistory::addAction(
688 'SHIPMENT_ITEM_ADD_ERROR',
691 [
"ERROR" => $r->getErrorMessages()]
694 $result->addErrors($r->getErrors());
698 if ($resultData = $r->getData())
699 $result->setData($resultData);
704 if (!$shipment->isSystem())
709 $orderHistory = $registry->getOrderHistoryClassName();
710 $orderHistory::addAction(
713 'SHIPMENT_ITEM_BASKET_ADDED',
717 'QUANTITY' => $this->getQuantity(),
731 $event =
new Main\Event(
'sale',
'OnSaleShipmentItemEntitySaved', [
733 'VALUES' => $this->fields->getOriginalValues(),
742 if (!$r->isSuccess())
744 $result->addErrors($r->getErrors());
748 if ($result->isSuccess())
753 $orderHistory = $registry->getOrderHistoryClassName();
754 $orderHistory::collectEntityFields(
'SHIPMENT_ITEM', $order->getId(), $id);
765 private function checkCallingContext()
770 throw new Main\ObjectNotFoundException(
'Entity "ShipmentItemCollection" not found');
774 if (!$shipment = $shipmentItemCollection->getShipment())
776 throw new Main\ObjectNotFoundException(
'Entity "Shipment" not found');
780 if (!$shipmentCollection = $shipment->getCollection())
782 throw new Main\ObjectNotFoundException(
'Entity "ShipmentCollection" not found');
786 if (!$order = $shipmentCollection->getOrder())
788 throw new Main\ObjectNotFoundException(
'Entity "Order" not found');
791 if (!$order->isSaveRunning())
793 trigger_error(
"Incorrect call to the save process. Use method save() on \Bitrix\Sale\Order entity", E_USER_WARNING);
797 private function getParentShipmentId()
802 return $shipment->getId();
813 if (intval($id) <= 0)
818 $itemDataList = static::getList([
820 '=ORDER_DELIVERY_ID' => $id,
823 'order' => [
'DATE_INSERT' =>
'ASC',
'ID' =>
'ASC']
826 while ($itemData = $itemDataList->fetch())
827 $items[] = static::createShipmentItemObject($itemData);
836 private static function createShipmentItemObject(array $itemData = [])
839 $shipmentItemClassName = $registry->getShipmentItemClassName();
841 return new $shipmentItemClassName($itemData);
864 protected function loadBasketItem()
876 if (!$shipmentCollection = $shipment->getCollection())
882 if (!$order = $shipmentCollection->getOrder())
884 throw new Main\ObjectNotFoundException(
'Entity "Order" not found');
888 if (!$basket = $order->getBasket())
890 throw new Main\ObjectNotFoundException(
'Entity "Basket" not found');
896 return $basket->getItemByBasketCode($this->
getBasketId());
904 if ($this->basketItem ==
null)
906 $this->basketItem = $this->loadBasketItem();
915 public function getShipmentItemStoreCollection()
922 if (empty($this->shipmentItemStoreCollection))
927 $itemStoreCollectionClassName = $registry->getShipmentItemStoreCollectionClassName();
928 $this->shipmentItemStoreCollection = $itemStoreCollectionClassName::load($this);
963 protected function calculateDelivery()
973 $shipmentCollection = $shipment->getCollection();
976 $order = $shipmentCollection->getOrder();
978 if ($order->getId() > 0)
983 $deliveryCalculate = $shipment->calculateDelivery();
984 if (!$deliveryCalculate->isSuccess())
986 $result->addErrors($deliveryCalculate->getErrors());
989 if ($deliveryCalculate->getPrice() > 0)
991 $shipment->setField(
'BASE_PRICE_DELIVERY', $deliveryCalculate->getPrice());
1004 protected function addChangesToHistory($name, $oldValue =
null, $value =
null)
1006 if ($this->getId() > 0)
1011 throw new Main\ObjectNotFoundException(
'Entity "ShipmentItemCollection" not found');
1015 if (!$shipment = $shipmentItemCollection->getShipment())
1017 throw new Main\ObjectNotFoundException(
'Entity "Shipment" not found');
1020 if ($shipment->isSystem())
1024 if (!$shipmentCollection = $shipment->getCollection())
1026 throw new Main\ObjectNotFoundException(
'Entity "ShipmentCollection" not found');
1029 $historyFields = [];
1036 'PRODUCT_ID' =>
$basketItem->getField(
'PRODUCT_ID'),
1041 if (($order = $shipmentCollection->getOrder()) && $order->getId() > 0)
1046 $orderHistory = $registry->getOrderHistoryClassName();
1047 $orderHistory::addField(
1068 if (parent::isChanged())
1084 return Internals\Catalog\Provider::tryReserveShipmentItem($this);
1094 return Internals\Catalog\Provider::tryUnreserveShipmentItem($this);
1102 public function verify()
1113 if (!$shipment = $shipmentItemCollection->getShipment())
1123 'SALE_SHIPMENT_ITEM_BASKET_ITEM_NOT_FOUND',
1126 '#SHIPMENT_ID#' => $shipment->getId(),
1127 '#SHIPMENT_ITEM_ID#' => $this->getId(),
1129 ),
'SALE_SHIPMENT_ITEM_BASKET_ITEM_NOT_FOUND'
1141 'SALE_SHIPMENT_ITEM_ERR_QUANTITY_EMPTY',
1143 '#BASKET_ITEM_NAME#' => $this->
getBasketItem()->getField(
'NAME'),
1145 ),
'SALE_SHIPMENT_ITEM_ERR_QUANTITY_EMPTY'
1158 $r = $shipmentItemStore->verify();
1159 if (!$r->isSuccess())
1161 $result->addErrors($r->getErrors());
1177 return Internals\ShipmentItemTable::getList($parameters);
1193 public function createClone(\SplObjectStorage $cloneEntity)
1195 if ($this->
isClone() && $cloneEntity->contains($this))
1197 return $cloneEntity[$this];
1201 $shipmentItemClone = parent::createClone($cloneEntity);
1213 $shipmentItemClone->basketItem = $cloneEntity[
$basketItem];
1231 return $shipmentItemClone;
1242 static $className =
null;
1243 $errorsList = static::getAutoFixErrorsList();
1244 if (is_array($errorsList) && in_array($value, $errorsList))
1246 if ($className ===
null)
1247 $className = static::getClassName();
1270 $errorsList = static::getAutoFixErrorsList();
1271 if (is_array($errorsList) && in_array($value, $errorsList))
1320 parent::clearChanged();
1326 $shipmentItemStore->clearChanged();
1339 $this->fields->isChanged(
'RESERVED_QUANTITY')
1340 || $this->
getCollection()->getShipment()->getField(
'RESERVED') ==
'Y'
1355 $changedFields = $this->fields->getChangedValues();
1356 $originalFields = $this->fields->getOriginalValues();
1358 return $changedFields[
'RESERVED_QUANTITY'] - $originalFields[
'RESERVED_QUANTITY'];
1368 return Internals\ShipmentItemTable::add($data);
1379 return Internals\ShipmentItemTable::update($primary, $data);
1387 return Internals\ShipmentItemTable::getMap();
1397 return 'SaleShipmentItem';
1405 $result = parent::toArray();