100 self::initClassNames();
108 if (self::$instance ===
null)
109 self::$instance =
new static();
111 return self::$instance;
120 $statusesNames = self::getStatusesList();
121 $status = intval($status);
123 if(empty($statusesNames[$status]))
126 return $statusesNames[$status];
135 Statuses::NO_INFORMATION =>
Loc::getMessage(
"SALE_DTM_STATUS_NAME_NO_INFORMATION"),
136 Statuses::WAITING_SHIPMENT =>
Loc::getMessage(
"SALE_DTM_STATUS_NAME_WAITING_SHIPMENT"),
137 Statuses::ON_THE_WAY =>
Loc::getMessage(
"SALE_DTM_STATUS_NAME_ON_THE_WAY"),
142 Statuses::RETURNED =>
Loc::getMessage(
"SALE_DTM_STATUS_NAME_RETURNED"),
162 return $trackingObject->getTrackingUrl($trackingNumber);
175 if(intval($shipmentId) <= 0)
180 $res = ShipmentTable::getList(array(
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'] ==
'')
203 if($result->isSuccess())
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())
219 $result->addErrors($res->getErrors());
234 $result = unserialize(Option::get(
'sale',
'tracking_map_statuses',
''), [
'allowed_classes' =>
false]);
236 if(!is_array($result))
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)
283 $deliveryService = Services\Manager::getObjectById($deliveryId);
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);
329 $manager = self::getInstance();
330 $result = $manager->updateStatuses();
332 if(!$result->isSuccess())
334 $eventLog = new \CEventLog;
336 $eventLog->Add(array(
337 "SEVERITY" => \CEventLog::SEVERITY_ERROR,
338 "AUDIT_TYPE_ID" =>
'SALE_DELIVERY_TRACKING_REFRESHING_STATUS_ERROR',
339 "MODULE_ID" =>
"sale",
341 "DESCRIPTION" => implode(
'\n', $result->getErrorMessages())
345 $data = $result->getData();
349 $result = $manager->processStatusChange($data);
351 if(!$result->isSuccess())
353 $eventLog = new \CEventLog;
355 $eventLog->Add(array(
356 "SEVERITY" => \CEventLog::SEVERITY_ERROR,
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)
380 $lastChage = \Bitrix\Main\Type\DateTime::createFromTimestamp(time()-self::$activeStatusLiveTime);
381 $lastUpdate = \Bitrix\Main\Type\DateTime::createFromTimestamp(time()-$checkPeriod*60*60);
383 $dbRes = ShipmentTable::getList(array(
385 '!=TRACKING_NUMBER' =>
false,
386 '!=DELIVERY_ID' =>
false,
391 array(
'!=TRACKING_STATUS' => Statuses::HANDED),
392 array(
'!=TRACKING_STATUS' => Statuses::RETURNED),
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())
443 $data = $res->getData();
446 $result->setData(array_merge($result->getData(), $data));
450 $result->addErrors($res->getErrors());
453 $deliveryId = $shipment[
'DELIVERY_ID'];
457 $deliveryId = $shipment[
'DELIVERY_ID'];
462 $res = $this->processStatusesByDelivery($deliveryId, $shipmentsData[$deliveryId]);
464 if($res->isSuccess())
466 $data = $res->getData();
469 $result->setData(array_merge($result->getData(), $data));
473 $result->addErrors($res->getErrors());
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(
503 "SEVERITY" => \CEventLog::SEVERITY_ERROR,
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(
536 "SEVERITY" => \CEventLog::SEVERITY_ERROR,
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)
559 $result =
new Result();
563 $orderClass = $registry->getOrderClassName();
565 foreach($params as $param)
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())
597 $res = $order->save();
599 if(!$res->isSuccess())
600 $result->addErrors($res->getErrors());
604 $result->addErrors($res->getErrors());
611 $this->sendStatusChangedMail($params);
619 protected function sendStatusChangedMail($params)
625 $paramsByShipmentId = array();
627 foreach($params as $status)
628 $paramsByShipmentId[$status->shipmentId] = $status;
632 $orderClass = $registry->getOrderClassName();
634 $res = ShipmentTable::getList(array(
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'
661 $event = new \CEvent;
663 while($data = $res->fetch())
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())
676 $userName = $propPayerName->getValue();
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(),
691 'ORDER_USER' => $userName,
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"]),
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 <>
'')
721 'SALE_DTM_SHIPMENT_STATUS_TRACKING_URL',
723 '#A1#' =>
'<a href="'.$trackingUrl.
'">',
729 $fields[
'DELIVERY_TRACKING_URL'] = $deliveryTrackingUrl;
730 $event->Send(
"SALE_ORDER_SHIPMENT_STATUS_CHANGED", $data[
'SITE_ID'], $fields,
"N");
741 $event =
new Event(
'sale',
'onSaleShipmentsTrackingStatusesChanged', $params);
767 if(self::$classNames !==
null)
770 Services\Manager::getHandlersList();
773 '\Bitrix\Sale\Delivery\Tracking\RusPost' =>
'lib/delivery/tracking/rus_post.php',
776 \Bitrix\Main\Loader::registerAutoLoadClasses(
'sale', $classes);
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();
790 if(!empty($params) && is_array($params))
791 $customClasses = array_merge($customClasses, $params);
794 if(!empty($customClasses))
796 \Bitrix\Main\Loader::registerAutoLoadClasses(
null, $customClasses);
797 $classes = array_merge($customClasses, $classes);
801 self::$classNames = array_keys($classes);
811 return self::$classNames;
826 $updParams = array();
828 if($params->status !==
null)
829 $updParams[
'TRACKING_STATUS'] = $params->status;
831 $updParams[
'TRACKING_LAST_CHECK'] = new \Bitrix\Main\Type\DateTime();
833 if(intval($params->lastChangeTimestamp) > 0)
835 $updParams[
'TRACKING_LAST_CHANGE'] = \Bitrix\Main\Type\DateTime::createFromTimestamp(
836 $params->lastChangeTimestamp
841 $updParams[
'TRACKING_LAST_CHANGE'] =
null;
844 if($params->trackingNumber !==
null)
845 $updParams[
'TRACKING_NUMBER'] = $params->trackingNumber;
847 $updParams[
'TRACKING_DESCRIPTION'] = $params->description;
849 if(!$params->isSuccess())
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 getMessage($code, $replace=null, $language=null)