- Модуль: sale
- Путь к файлу: ~/bitrix/modules/sale/lib/helpers/order/builder/orderbuilder.php
- Класс: BitrixSaleHelpersOrderBuilderOrderBuilder
- Вызов: OrderBuilder::buildShipments
public function buildShipments()
{
$isEmptyShipmentData = empty($this->formData["SHIPMENT"]) || !is_array($this->formData["SHIPMENT"]);
if ($isEmptyShipmentData)
{
$this->formData["SHIPMENT"] = [];
}
if ($isEmptyShipmentData && !$this->getSettingsContainer()->getItemValue('createDefaultShipmentIfNeed'))
{
return $this;
}
if($isEmptyShipmentData && $this->getOrder()->isNew())
{
$this->createEmptyShipment();
return $this;
}
if(!$this->removeShipments())
{
throw new BuildingException();
}
global $USER;
$shipmentCollection = $this->order->getShipmentCollection();
foreach($this->formData["SHIPMENT"] as $item)
{
$shipmentId = intval($item['ID'] ?? 0);
$isNew = ($shipmentId <= 0);
$deliveryService = null;
$storeId = null;
if (!isset($item['DEDUCTED']) || $item['DEDUCTED'] !== 'Y')
{
$item['DEDUCTED'] = 'N';
}
$extraServices =
isset($item['EXTRA_SERVICES']) && is_array($item['EXTRA_SERVICES'])
? $item['EXTRA_SERVICES']
: []
;
$settableShipmentFields = $this->getSettableShipmentFields();
if (!empty($settableShipmentFields))
{
//for backward compatibility
$product = $item['PRODUCT'] ?? null;
$storeId = (int)($item['DELIVERY_STORE_ID'] ?? 0);
$item = array_intersect_key($item, array_flip($settableShipmentFields));
if ($product !== null)
{
$item['PRODUCT'] = $product;
}
unset($product);
}
if($isNew)
{
$shipment = $shipmentCollection->createItem();
}
else
{
$shipment = $shipmentCollection->getItemById($shipmentId);
if(!$shipment)
{
$this->errorsContainer->addError(new Error(Loc::getMessage("SALE_HLP_ORDERBUILDER_SHIPMENT_NOT_FOUND")." - ".$shipmentId));
continue;
}
}
$defaultFields = $shipment->getFieldValues();
/** @var BitrixSaleBasketItem $product */
$systemShipment = $shipmentCollection->getSystemShipment();
$systemShipmentItemCollection = $systemShipment->getShipmentItemCollection();
//We suggest that if products is null - ShipmentBasket not loaded yet, if array ShipmentBasket loaded, but empty.
$products = null;
if(
!isset($item['PRODUCT'])
&& $shipment->getId() <= 0
)
{
$products = array();
$basket = $this->order->getBasket();
if($basket)
{
$basketItems = $basket->getBasketItems();
foreach($basketItems as $product)
{
$systemShipmentItem = $systemShipmentItemCollection->getItemByBasketCode($product->getBasketCode());
if($product->isBundleChild() || !$systemShipmentItem || $systemShipmentItem->getQuantity() <= 0)
continue;
$products[] = array(
'AMOUNT' => $systemShipmentItem->getQuantity(),
'BASKET_CODE' => $product->getBasketCode(),
);
}
}
}
elseif (isset($item['PRODUCT']) && is_array($item['PRODUCT']))
{
$products = $item['PRODUCT'];
}
if($item['DEDUCTED'] == 'Y' && $products !== null)
{
$basketResult = $this->buildShipmentBasket($shipment, $products);
if(!$basketResult->isSuccess())
{
$this->errorsContainer->addErrors($basketResult->getErrors());
}
}
$shipmentFields = array(
'COMPANY_ID' => (isset($item['COMPANY_ID']) && intval($item['COMPANY_ID']) > 0) ? intval($item['COMPANY_ID']) : 0,
'DEDUCTED' => $item['DEDUCTED'] ?? 'N',
'DELIVERY_DOC_NUM' => $item['DELIVERY_DOC_NUM'] ?? '',
'TRACKING_NUMBER' => $item['TRACKING_NUMBER'] ?? '',
'CURRENCY' => $this->order->getCurrency(),
'COMMENTS' => $item['COMMENTS'] ?? '',
);
if (!empty($item['IS_REALIZATION']))
{
$shipmentFields['IS_REALIZATION'] = $item['IS_REALIZATION'];
}
if (!empty($item['ACCOUNT_NUMBER']))
{
$shipmentFields['ACCOUNT_NUMBER'] = $item['ACCOUNT_NUMBER'];
}
if (!empty($item['XML_ID']))
{
$shipmentFields['XML_ID'] = $item['XML_ID'];
}
$statusId = $this->prepareFieldsStatusId($isNew, $item, $defaultFields);
if ($statusId !== '')
{
$shipmentFields['STATUS_ID'] = $statusId;
}
if (empty($item['COMPANY_ID']))
{
$shipmentFields['COMPANY_ID'] = $this->order->getField('COMPANY_ID');
}
if (empty($item['RESPONSIBLE_ID']))
{
$shipmentFields['RESPONSIBLE_ID'] = $this->order->getField('RESPONSIBLE_ID');
$shipmentFields['EMP_RESPONSIBLE_ID'] = $USER->GetID();
}
$deliveryId = 0;
if (isset($item['PROFILE_ID']) && (int)$item['PROFILE_ID'] > 0)
{
$deliveryId = (int)$item['PROFILE_ID'];
}
elseif (isset($item['DELIVERY_ID']))
{
$deliveryId = (int)$item['DELIVERY_ID'];
}
elseif ($shipment->getField('DELIVERY_ID'))
{
$deliveryId = $shipment->getField('DELIVERY_ID');
}
$shipmentFields['DELIVERY_ID'] = $deliveryId;
$dateFields = ['DELIVERY_DOC_DATE', 'DATE_DEDUCTED', 'DATE_MARKED', 'DATE_CANCELED', 'DATE_RESPONSIBLE_ID'];
foreach($dateFields as $fieldName)
{
if(isset($item[$fieldName]))
{
if (is_string($item[$fieldName]))
{
try
{
$shipmentFields[$fieldName] = new DateTime($item[$fieldName]);
}
catch (ObjectException $exception)
{
$this->errorsContainer->addError(new Error('Wrong field "'.$fieldName.'"'));
}
}
elseif ($item[$fieldName] instanceof Date)
{
$shipmentFields[$fieldName] = $item[$fieldName];
}
}
}
try
{
if($deliveryService = DeliveryServicesManager::getObjectById($shipmentFields['DELIVERY_ID']))
{
if($deliveryService->isProfile())
{
$shipmentFields['DELIVERY_NAME'] = $deliveryService->getNameWithParent();
}
else
{
$shipmentFields['DELIVERY_NAME'] = $deliveryService->getName();
}
}
}
catch (ArgumentNullException $e)
{
$this->errorsContainer->addError(new Error(Loc::getMessage('SALE_HLP_ORDERBUILDER_DELIVERY_NOT_FOUND'), 'OB_DELIVERY_NOT_FOUND'));
return $this;
}
$responsibleId = $shipment->getField('RESPONSIBLE_ID');
if($item['RESPONSIBLE_ID'] != $responsibleId || empty($responsibleId))
{
if(isset($item['RESPONSIBLE_ID']))
{
$shipmentFields['RESPONSIBLE_ID'] = $item['RESPONSIBLE_ID'];
}
else
{
$shipmentFields['RESPONSIBLE_ID'] = $this->order->getField('RESPONSIBLE_ID');
}
if(!empty($shipmentFields['RESPONSIBLE_ID']))
{
$shipmentFields['EMP_RESPONSIBLE_ID'] = $USER->getID();
}
}
if($extraServices)
{
$shipment->setExtraServices($extraServices);
}
$setFieldsResult = $shipment->setFields($shipmentFields);
if(!$setFieldsResult->isSuccess())
{
$this->errorsContainer->addErrors($setFieldsResult->getErrors());
}
// region Properties
if (isset($item['PROPERTIES']) && is_array($item['PROPERTIES']))
{
/** @var PropertyValueCollection $propCollection */
$propCollection = $shipment->getPropertyCollection();
$res = $propCollection->setValuesFromPost($item, []);
if (!$res->isSuccess())
{
foreach ($res->getErrors() as $error)
{
$this->getErrorsContainer()->addError(
new MainError($error->getMessage(), $error->getCode(), 'SHIPMENT_PROPERTIES')
);
}
}
/** @var BitrixSalePropertyValue $propValue */
foreach ($propCollection as $propValue)
{
if ($propValue->isUtil())
{
continue;
}
$property = $propValue->getProperty();
$relatedDeliveryIds = (isset($property['RELATION']) && is_array($property['RELATION']))
? array_column(
array_filter(
$property['RELATION'],
function ($item)
{
return $item['ENTITY_TYPE'] === 'D';
}
),
'ENTITY_ID'
)
: [];
if (
!empty($relatedDeliveryIds)
&& !in_array($shipment->getField('DELIVERY_ID'), $relatedDeliveryIds)
)
{
continue;
}
$res = $propValue->verify();
if (!$res->isSuccess())
{
foreach ($res->getErrors() as $error)
{
$this->getErrorsContainer()->addError(
new MainError($error->getMessage(), $propValue->getPropertyId(), 'SHIPMENT_PROPERTIES')
);
}
}
$res = $propValue->checkRequiredValue($propValue->getPropertyId(), $propValue->getValue());
if (!$res->isSuccess())
{
foreach ($res->getErrors() as $error)
{
$this->getErrorsContainer()->addError(
new MainError($error->getMessage(), $propValue->getPropertyId(), 'SHIPMENT_PROPERTIES')
);
}
}
}
}
// endregion
if ($storeId)
{
$shipment->setStoreId($storeId);
}
if($item['DEDUCTED'] == 'N' && $products !== null)
{
$basketResult = $this->buildShipmentBasket($shipment, $products);
if(!$basketResult->isSuccess())
{
$this->errorsContainer->addErrors($basketResult->getErrors());
}
}
$isCustomPrice = false;
if (isset($item['CUSTOM_PRICE_DELIVERY']))
{
$isCustomPrice = $item['CUSTOM_PRICE_DELIVERY'] === 'Y';
}
$fields = array(
'CUSTOM_PRICE_DELIVERY' => $isCustomPrice ? 'Y' : 'N',
'PRICE_DELIVERY' => (float)str_replace(',', '.', $item['PRICE_DELIVERY'] ?? 0),
);
if (isset($item['ALLOW_DELIVERY']))
{
$fields['ALLOW_DELIVERY'] = $item['ALLOW_DELIVERY'] === 'Y' ? 'Y' : 'N';
}
if (isset($item['BASE_PRICE_DELIVERY']))
{
$fields['BASE_PRICE_DELIVERY'] = (float)str_replace(',', '.', $item['BASE_PRICE_DELIVERY']);
}
$shipment = $this->delegate->setShipmentPriceFields($shipment, $fields);
if($deliveryService && !empty($item['ADDITIONAL']))
{
$modifiedShipment = $deliveryService->processAdditionalInfoShipmentEdit($shipment, $item['ADDITIONAL']);
$registry = Registry::getInstance(Registry::REGISTRY_TYPE_ORDER);
if ($modifiedShipment && get_class($modifiedShipment) == $registry->getShipmentClassName())
{
$shipment = $modifiedShipment;
}
}
}
return $this;
}