100 self::initClassNames();
108 if (self::$instance ===
null)
109 self::$instance =
new static();
111 return self::$instance;
120 $statusesNames = self::getStatusesList();
123 if(empty($statusesNames[
$status]))
124 return Loc::getMessage(
"SALE_DTM_STATUS_NAME_UNKNOWN");
126 return $statusesNames[
$status];
162 return $trackingObject->getTrackingUrl($trackingNumber);
175 if(intval($shipmentId) <= 0)
185 'ID',
'ORDER_ID',
'DELIVERY_ID',
'TRACKING_STATUS',
'TRACKING_NUMBER'
189 if(!$shipment =
$res->fetch())
191 $result->addError(
new Error(
"Can't find shipment with id:\"".$shipmentId.
'"'));
195 if($trackingNumber <>
'' && $trackingNumber != $shipment[
'TRACKING_NUMBER'])
196 $shipment[
'TRACKING_NUMBER'] = $trackingNumber;
198 if($shipment[
'TRACKING_NUMBER'] ==
'')
205 if($shipment[
'TRACKING_STATUS'] !=
$result->status)
208 $eventParams->orderId = $shipment[
'ORDER_ID'];
209 $eventParams->shipmentId = $shipmentId;
210 $eventParams->status =
$result->status;
211 $eventParams->trackingNumber = $shipment[
'TRACKING_NUMBER'];
212 $eventParams->description =
$result->description;
213 $eventParams->lastChangeTimestamp =
$result->lastChangeTimestamp;
214 $eventParams->deliveryId = $shipment[
'DELIVERY_ID'];
215 $res = $this->processStatusChange(
array($eventParams));
217 if(!
$res->isSuccess())
234 $result = unserialize(Option::get(
'sale',
'tracking_map_statuses',
''), [
'allowed_classes' =>
false]);
244 return (
int)Option::get(
'sale',
'tracking_check_period',
'24');
257 if(intval($shipment[
'DELIVERY_ID']) <= 0)
265 return $trackingObject->getStatusShipment($shipment);
278 if(intval($deliveryId) <= 0)
285 if(!$deliveryService)
288 $class = $deliveryService->getTrackingClass();
294 $deliveryService->getTrackingParams(),
315 if(!class_exists($className))
318 if(get_parent_class($className) !=
'Bitrix\Sale\Delivery\Tracking\Base')
319 throw new SystemException($className.
' is not inherited from \"\Bitrix\Sale\Delivery\Tracking\Base\"!');
321 return new $className(
$params, $deliveryService);
334 $eventLog = new \CEventLog;
336 $eventLog->Add(
array(
338 "AUDIT_TYPE_ID" =>
'SALE_DELIVERY_TRACKING_REFRESHING_STATUS_ERROR',
339 "MODULE_ID" =>
"sale",
341 "DESCRIPTION" => implode(
'\n',
$result->getErrorMessages())
353 $eventLog = new \CEventLog;
355 $eventLog->Add(
array(
357 "AUDIT_TYPE_ID" =>
'SALE_DELIVERY_TRACKING_REFRESHING_STATUS_ERROR',
358 "MODULE_ID" =>
"sale",
360 "DESCRIPTION" => implode(
'\n',
$result->getErrorMessages())
365 return '\Bitrix\Sale\Delivery\Tracking\Manager::startRefreshingStatuses();';
375 $checkPeriod = self::getCheckPeriod();
377 if($checkPeriod <= 0)
385 '!=TRACKING_NUMBER' =>
false,
386 '!=DELIVERY_ID' =>
false,
394 array(
'=TRACKING_STATUS' =>
false)
400 array(
'=TRACKING_LAST_CHANGE' =>
false),
401 array(
'>=DATE_INSERT' => $lastChage),
403 array(
'>=TRACKING_LAST_CHANGE' => $lastChage)
407 array(
'=TRACKING_LAST_CHECK' =>
false),
408 array(
'<=TRACKING_LAST_CHECK' => $lastUpdate)
412 'ID',
'ORDER_ID',
'DELIVERY_ID',
'TRACKING_STATUS',
'TRACKING_NUMBER'
415 'DELIVERY_ID' =>
'ASC'
420 $shipmentsData =
array();
422 while($shipment =
$dbRes->fetch())
424 if(!isset($shipmentsData[$shipment[
'DELIVERY_ID']]))
425 $shipmentsData[$shipment[
'DELIVERY_ID']] =
array();
427 if($shipment[
'TRACKING_NUMBER'] ==
'')
430 $shipmentsData[$shipment[
'DELIVERY_ID']][$shipment[
'TRACKING_NUMBER']] =
array(
431 'SHIPMENT_ID' => $shipment[
'ID'],
432 'ORDER_ID' => $shipment[
'ORDER_ID'],
433 'DELIVERY_ID' => $shipment[
'DELIVERY_ID'],
434 'TRACKING_STATUS' => $shipment[
'TRACKING_STATUS']
437 if($shipment[
'DELIVERY_ID'] != $deliveryId && $deliveryId > 0)
439 $res = $this->processStatusesByDelivery($deliveryId, $shipmentsData[$deliveryId]);
441 if(
$res->isSuccess())
453 $deliveryId = $shipment[
'DELIVERY_ID'];
457 $deliveryId = $shipment[
'DELIVERY_ID'];
462 $res = $this->processStatusesByDelivery($deliveryId, $shipmentsData[$deliveryId]);
464 if(
$res->isSuccess())
480 protected function processStatusesByDelivery($deliveryId, $shipmentsData)
483 $trackingObject = $this->getTrackingObjectByDeliveryId($deliveryId);
487 $statusResults = $trackingObject->getStatusesShipment($shipmentsData);
488 $eventsParams =
array();
491 foreach($statusResults as $number => $statusResult)
495 if(empty($shipmentsData[$number]))
498 if(!$statusResult->isSuccess())
500 $eventLog = new \CEventLog;
502 $eventLog->Add(
array(
504 "AUDIT_TYPE_ID" =>
'SALE_DELIVERY_TRACKING_STATUS_RESULT',
505 "MODULE_ID" =>
"sale",
506 "ITEM_ID" => $shipmentsData[$number][
'SHIPMENT_ID'],
507 "DESCRIPTION" => implode(
'\n', $statusResult->getErrorMessages())
513 if(($statusResult->status != $shipmentsData[$number][
'TRACKING_STATUS']))
515 $eventParams =
new StatusChangeEventParam();
516 $eventParams->orderId = $shipmentsData[$number][
'ORDER_ID'];
517 $eventParams->shipmentId = $shipmentsData[$number][
'SHIPMENT_ID'];
518 $eventParams->status = $statusResult->status;
519 $eventParams->trackingNumber = $number;
520 $eventParams->description = $statusResult->description;
521 $eventParams->lastChangeTimestamp = $statusResult->lastChangeTimestamp;
522 $eventParams->deliveryId = $deliveryId;
523 $eventsParams[] = $eventParams;
526 $res = $this->updateShipment(
527 $shipmentsData[$number][
'SHIPMENT_ID'],
531 if(!
$res->isSuccess())
533 $eventLog = new \CEventLog;
535 $eventLog->Add(
array(
537 "AUDIT_TYPE_ID" =>
'SALE_DELIVERY_TRACKING_UPDATE_SHIPMENT',
538 "MODULE_ID" =>
"sale",
539 "ITEM_ID" => $shipmentsData[$number][
'SHIPMENT_ID'],
540 "DESCRIPTION" => implode(
'\n',
$res->getErrorMessages())
545 $result->setData($eventsParams);
557 protected function processStatusChange(
$params)
563 $orderClass = $registry->getOrderClassName();
567 if(intval($param->status) <= 0 && $param->description ==
'')
572 if(!empty($mappedStatuses[$param->status]))
575 $order = $orderClass::load($param->orderId);
576 $shipmentCollection =
null;
582 $shipmentCollection =
$order->getShipmentCollection();
585 if($shipmentCollection)
588 $oShipment = $shipmentCollection->getItemById($param->shipmentId);
593 $res = $oShipment->setField(
'STATUS_ID', $mappedStatuses[$param->status]);
595 if(
$res->isSuccess())
599 if(!
$res->isSuccess())
611 $this->sendStatusChangedMail(
$params);
619 protected function sendStatusChangedMail(
$params)
625 $paramsByShipmentId =
array();
632 $orderClass = $registry->getOrderClassName();
636 '=ID' => array_keys($paramsByShipmentId)
640 'SITE_ID' =>
'ORDER.LID',
641 'SITE_NAME' =>
'SITE.NAME',
642 'SHIPMENT_NO' =>
'ID',
643 'SHIPMENT_DATE' =>
'DATE_INSERT',
644 'ORDER_NO' =>
'ORDER.ACCOUNT_NUMBER',
645 'ORDER_DATE' =>
'ORDER.DATE_INSERT',
646 'USER_NAME' =>
'ORDER.USER.NAME',
647 'USER_LAST_NAME' =>
'ORDER.USER.LAST_NAME',
648 'EMAIL' =>
'ORDER.USER.EMAIL'
652 'data_type' =>
'Bitrix\Main\SiteTable',
653 'reference' =>
array(
654 'ref.LID' =>
'this.ORDER.LID',
656 'join_type' =>
'left'
667 $order = $orderClass::load($paramsByShipmentId[
$data[
'SHIPMENT_NO']]->orderId);
670 if ($propertyCollection =
$order->getPropertyCollection())
672 if ($propUserEmail = $propertyCollection->getUserEmail())
673 $userEmail = $propUserEmail->getValue();
675 if ($propPayerName = $propertyCollection->getPayerName())
679 if(empty($userEmail))
680 $userEmail =
$data[
'EMAIL'];
683 $userName =
$data[
"USER_NAME"].(($data[
"USER_NAME"] ==
'' ||
$data[
"USER_LAST_NAME"] ==
'') ?
"" :
" ").
$data[
"USER_LAST_NAME"];
685 $siteFields = \CEvent::GetSiteFieldsArray(
$data[
'SITE_ID']);
688 'SITE_NAME' =>
$data[
'SITE_NAME'],
689 'ORDER_NO' =>
$data[
'ORDER_NO'],
690 'ORDER_DATE' =>
$data[
'ORDER_DATE']->toString(),
692 'SHIPMENT_NO' =>
$data[
'SHIPMENT_NO'],
693 'SHIPMENT_DATE' =>
$data[
'SHIPMENT_DATE']->toString(),
694 'EMAIL' => $userEmail,
695 'STATUS_NAME' => self::getStatusName($paramsByShipmentId[
$data[
'SHIPMENT_NO']]->status),
696 'STATUS_DESCRIPTION' => $paramsByShipmentId[
$data[
'SHIPMENT_NO']]->description,
697 'TRACKING_NUMBER' => $paramsByShipmentId[
$data[
'SHIPMENT_NO']]->trackingNumber,
698 'DELIVERY_NAME' =>
$data[
'DELIVERY_NAME'],
699 "ORDER_ACCOUNT_NUMBER_ENCODE" => urlencode(urlencode(
$data[
'ORDER_NO'])),
700 "SALE_EMAIL" => Option::get(
"sale",
"order_email",
"order@".
$_SERVER[
"SERVER_NAME"]),
703 $fields[
'ORDER_DETAIL_URL'] = Loc::getMessage(
704 'SALE_DTM_ORDER_DETAIL_URL',
706 '#A1#' =>
'<a href="http://'.$siteFields[
'SERVER_NAME'].
'/personal/order/detail/'.
$fields[
'ORDER_ACCOUNT_NUMBER_ENCODE'].
'/">',
711 $trackingUrl = self::getTrackingUrl(
712 $paramsByShipmentId[
$data[
'SHIPMENT_NO']]->deliveryId,
713 $paramsByShipmentId[
$data[
'SHIPMENT_NO']]->trackingNumber
716 $deliveryTrackingUrl =
'';
718 if($trackingUrl <>
'')
720 $deliveryTrackingUrl = Loc::getMessage(
721 'SALE_DTM_SHIPMENT_STATUS_TRACKING_URL',
723 '#A1#' =>
'<a href="'.$trackingUrl.
'">',
729 $fields[
'DELIVERY_TRACKING_URL'] = $deliveryTrackingUrl;
767 if(self::$classNames !==
null)
773 '\Bitrix\Sale\Delivery\Tracking\RusPost' =>
'lib/delivery/tracking/rus_post.php',
778 $event =
new Event(
'sale',
'onSaleDeliveryTrackingClassNamesBuildList');
780 $resultList =
$event->getResults();
782 if (is_array($resultList) && !empty($resultList))
784 $customClasses =
array();
786 foreach ($resultList as $eventResult)
788 $params = $eventResult->getParameters();
791 $customClasses = array_merge($customClasses,
$params);
794 if(!empty($customClasses))
797 $classes = array_merge($customClasses, $classes);
801 self::$classNames = array_keys($classes);
811 return self::$classNames;
826 $updParams =
array();
829 $updParams[
'TRACKING_STATUS'] =
$params->status;
831 $updParams[
'TRACKING_LAST_CHECK'] = new \Bitrix\Main\Type\DateTime();
833 if(intval(
$params->lastChangeTimestamp) > 0)
841 $updParams[
'TRACKING_LAST_CHANGE'] =
null;
844 if(
$params->trackingNumber !==
null)
845 $updParams[
'TRACKING_NUMBER'] =
$params->trackingNumber;
847 $updParams[
'TRACKING_DESCRIPTION'] =
$params->description;
850 $updParams[
'TRACKING_DESCRIPTION'] .=
' '.implode(
', ',
$params->getErrorMessages());
852 return ShipmentTable::update($shipmentId, $updParams);
863 if ($this->
isClone() && $cloneEntity->contains($this))
865 return $cloneEntity[$this];
868 $trackingClone = clone $this;
869 $trackingClone->isClone =
true;
871 if (!$cloneEntity->contains($this))
873 $cloneEntity[$this] = $trackingClone;
876 return $trackingClone;
884 return $this->isClone;
static registerAutoLoadClasses($moduleName, array $classes)
static createFromTimestamp($timestamp)