2namespace Bitrix\Sale\Delivery\Services;
4use Bitrix\Main\Config\Option;
9use Bitrix\Main\ORM\Data\AddResult;
10use Bitrix\Sale\Internals\Pool;
11use Bitrix\Sale\Result;
12use Bitrix\Main\IO\File;
13use Bitrix\Sale\Shipment;
14use Bitrix\Main\IO\Directory;
15use Bitrix\Main\SystemException;
16use Bitrix\Main\Localization\Loc;
17use Bitrix\Main\Entity\EventResult;
18use Bitrix\Main\ArgumentNullException;
19use Bitrix\Sale\Delivery\Restrictions;
20use Bitrix\Sale\Delivery\ExtraServices;
21use Bitrix\Sale\Internals\ShipmentTable;
22use Bitrix\Sale\Delivery\CalculationResult;
23use Bitrix\Sale\Internals\ServiceRestrictionTable;
24use Bitrix\Sale\Delivery\Services\Base;
26Loc::loadMessages(__FILE__);
53 public static function getById($deliveryId)
55 $id = intval($deliveryId);
60 if(!isset(self::$cachedFields[$deliveryId]) || !is_array(self::$cachedFields[$deliveryId]))
62 self::$cachedFields[$deliveryId] =
array();
64 $resSrvParams = Table::getList(
array(
65 'filter' =>
array(
"=ID" => $deliveryId)
68 if($srvParams = $resSrvParams->fetch())
69 self::$cachedFields[$srvParams[
"ID"]] = $srvParams;
72 return self::$cachedFields[$deliveryId];
95 $services = self::getRestrictedList($shipment, $restrictionMode);
97 foreach($services as $srvParams)
99 if($srvParams[
"CLASS_NAME"]::canHasProfiles())
102 if(is_callable($srvParams[
"CLASS_NAME"].
"::canHasChildren") && $srvParams[
"CLASS_NAME"]::canHasChildren())
105 $service = self::getPooledObject($srvParams);
110 if(!
$service->isCompatible($shipment))
115 $service->getExtraServices()->setOperationCurrency(
133 if(intval($deliveryId) <= 0)
136 $srv = self::getById($deliveryId);
147 public static function getActiveList($calculatingOnly =
false, $restrictedIds =
null)
150 static $isDataPrepared =
false;
151 static $activeIds =
array();
152 static $canHasProfiles =
array();
153 static $canHasChildren =
array();
154 static $DontHaveRestrictionsIds =
array();
156 if(is_array($restrictedIds))
158 $unPreparedRestrictedIds = array_diff_key(
165 $unPreparedRestrictedIds = array_keys($unPreparedRestrictedIds);
169 $unPreparedRestrictedIds =
array();
172 if(!$isDataPrepared || !empty($unPreparedRestrictedIds))
175 self::initHandlers();
182 'order' =>
array(
'SORT' =>
'ASC',
'NAME' =>
'ASC'),
188 'RESTRICTIONS_EXIST',
190 'SELECT 1 FROM b_sale_service_rstr SSR WHERE SSR.SERVICE_ID = %s AND SSR.SERVICE_TYPE = '.
Restrictions\Manager::SERVICE_TYPE_SHIPMENT.
') THEN 1 ELSE 0 END',
197 if(!empty($unPreparedRestrictedIds))
201 $params[
'filter'][
'ID'] = $unPreparedRestrictedIds;
207 "ID" => $unPreparedRestrictedIds,
208 'RESTRICTIONS_EXIST' => 0
214 $profilesParentsIds =
array();
218 if(!is_subclass_of(
$service[
"CLASS_NAME"],
'Bitrix\Sale\Delivery\Services\Base'))
222 $DontHaveRestrictionsIds[] =
$service[
'ID'];
224 if(
$service[
"CLASS_NAME"]::canHasChildren())
225 $canHasChildren[
$service[
"ID"]] =
true;
227 if (
$service[
'CLASS_NAME']::canHasProfiles())
228 $canHasProfiles[
$service[
"ID"]] =
true;
239 foreach(array_diff_key($canHasProfiles, $profilesParentsIds) as $id =>
$tmp)
242 self::$cachedFields = self::$cachedFields +
$result;
243 Restrictions\Manager::prepareData(array_keys(
$result));
247 if(!$isDataPrepared && empty($unPreparedRestrictedIds))
248 $isDataPrepared =
true;
251 if(is_array($restrictedIds) && !empty($restrictedIds))
252 $storedIds = array_diff($restrictedIds, $unPreparedRestrictedIds);
254 $storedIds =
array();
256 if(!empty($storedIds) && is_array($storedIds))
258 foreach($storedIds as $storedId)
260 if(empty(self::$cachedFields[$storedId]))
263 $service = self::$cachedFields[$storedId];
265 if(!class_exists(
$service[
"CLASS_NAME"]))
268 if(
$service[
"CLASS_NAME"]::canHasChildren())
269 $canHasChildren[$storedId] =
true;
271 if (
$service[
'CLASS_NAME']::canHasProfiles())
272 $canHasProfiles[$storedId] =
true;
275 $activeIds[$storedId] = $storedId;
279 $active = array_intersect_key(self::$cachedFields, array_flip($activeIds));
281 if(is_array($restrictedIds))
283 $result = array_intersect_key($active, array_flip($DontHaveRestrictionsIds));
285 if(!empty($restrictedIds))
286 $result =
$result + array_intersect_key($active, array_flip($restrictedIds));
301 if(intval(
$fields[
'PARENT_ID']) <= 0)
309 $result = array_diff_key(
$result, $canHasChildren, $canHasProfiles);
327 if(empty($skipChecks))
330 self::SKIP_CHILDREN_PARENT_CHECK,
331 self::SKIP_PROFILE_PARENT_CHECK
338 $services = self::getActiveList(
false, array_keys($restrictedSrvIds));
340 foreach($services as $srvParams)
342 $srvParams[
"RESTRICTED"] =
false;
344 if(!in_array(self::SKIP_PROFILE_PARENT_CHECK, $skipChecks))
345 if($srvParams[
"CLASS_NAME"]::canHasProfiles())
348 if(!in_array(self::SKIP_CHILDREN_PARENT_CHECK, $skipChecks))
349 if(is_callable($srvParams[
"CLASS_NAME"].
"::canHasChildren") && $srvParams[
"CLASS_NAME"]::canHasChildren())
352 if(isset($restrictedSrvIds[$srvParams[
"ID"]]) && $restrictedSrvIds[$srvParams[
"ID"]] ==
Restrictions\Manager::SEVERITY_SOFT)
353 $srvParams[
"RESTRICTED"] =
true;
355 $result[$srvParams[
"ID"]] = $srvParams;
369 self::initHandlers();
373 if(!isset($srvParams[
'PARENT_ID']))
375 $srvParams[
'PARENT_ID'] = 0;
378 if(class_exists($srvParams[
'CLASS_NAME']))
380 if(is_subclass_of($srvParams[
'CLASS_NAME'], Base::class))
384 $service =
new $srvParams[
'CLASS_NAME']($srvParams);
393 $errorMsg =
'Class "' . $srvParams[
'CLASS_NAME'] .
'" is not subclass of of Bitrix\Sale\Delivery\Services\Base';
398 $errorMsg =
'Can\'t create delivery object. Class "'.$srvParams[
'CLASS_NAME'].
'" does not exist.';
406 'AUDIT_TYPE_ID' =>
'SALE_DELIVERY_CREATE_OBJECT_ERROR',
407 'MODULE_ID' =>
'sale',
408 'ITEM_ID' =>
'createObject()',
409 'DESCRIPTION' =>
$errorMsg.
' Fields: '.serialize($srvParams),
426 if(self::$objectsPool ===
null)
429 return self::$objectsPool->getObject(
$fields);
440 if(intval($deliveryId) <= 0 )
443 $srvParams = self::getById($deliveryId);
445 if(empty($srvParams))
448 return self::getPooledObject($srvParams);
460 if($serviceCode ==
'' )
463 $srvParams =
array();
465 foreach(self::$cachedFields as $id => $srv)
467 if($srv[
'CODE'] == $serviceCode)
473 if(empty($srvParams))
475 $resSrvParams = Table::getList(
array(
476 'filter' =>
array(
'=CODE' => $serviceCode)
479 if(!($srvParams = $resSrvParams->fetch()))
480 throw new SystemException(
"Can't get delivery service data with code: \"".$serviceCode.
"\"");
482 self::$cachedFields[$srvParams[
'ID']] = $srvParams;
485 return self::getPooledObject($srvParams);
495 protected static function initHandlers()
497 if(self::$handlers !==
null)
500 self::$handlersDirectories =
array(
501 'LOCAL' =>
'/local/php_interface/include/sale_delivery/',
502 'CUSTOM' => Option::get(
'sale',
'delivery_handles_custom_path', BX_PERSONAL_ROOT.
'/php_interface/include/sale_delivery/'),
503 'SYSTEM' =>
'/bitrix/modules/sale/handlers/delivery/'
507 '\Bitrix\Sale\Delivery\Services\Group' =>
'lib/delivery/services/group.php',
508 '\Bitrix\Sale\Delivery\Services\Automatic' =>
'lib/delivery/services/automatic.php',
509 '\Bitrix\Sale\Delivery\Services\Configurable' =>
'lib/delivery/services/configurable.php',
510 '\Bitrix\Sale\Delivery\Services\AutomaticProfile' =>
'lib/delivery/services/automatic_profile.php',
511 '\Bitrix\Sale\Delivery\Services\EmptyDeliveryService' =>
'lib/delivery/services/emptydeliveryservice.php',
533 $event =
new Event(
'sale',
'onSaleDeliveryHandlersClassNamesBuildList');
535 $resultList =
$event->getResults();
537 if (is_array($resultList) && !empty($resultList))
539 $customClasses =
array();
541 foreach ($resultList as $eventResult)
544 if ($eventResult->getType() != EventResult::SUCCESS)
547 $params = $eventResult->getParameters();
550 $customClasses = array_merge($customClasses,
$params);
553 if(!empty($customClasses))
560 $handlers = self::getHandlersClasses();
562 if(!empty($handlers))
568 self::$handlers = array_keys(
$result);
570 for($idx =
count(self::$handlers) - 1; $idx >= 0; $idx--)
573 $handler = self::$handlers[$idx];
575 if(!$handler::isHandlerCompatible())
577 unset(self::$handlers[$idx]);
581 $profiles = $handler::getChildrenClassNames();
583 if(!empty($profiles))
585 self::$handlers = array_merge(self::$handlers, $profiles);
596 protected static function getHandlersClasses()
600 foreach(self::$handlersDirectories as $handlersDirectory)
602 $dirPath =
$_SERVER[
'DOCUMENT_ROOT'].$handlersDirectory;
604 if(!Directory::isDirectoryExists($dirPath))
607 $dir =
new Directory(
$_SERVER[
'DOCUMENT_ROOT'].$handlersDirectory);
609 foreach (
$dir->getChildren() as $handler)
611 if (!$handler->isDirectory())
616 $handlerDir = $handler->getPath();
617 $handlerPath = $handlerDir.
'/handler.php';
619 if(!File::isFileExists($handlerPath))
622 $handlerClassName = ucfirst($handler->getName().
'Handler');
623 $fullClassName =
'\Sale\Handlers\Delivery\\'.$handlerClassName;
624 $result[$fullClassName] = $handlersDirectory.$handler->getName().
'/handler.php';
625 require_once($handlerPath);
638 if(self::$handlers ===
null)
639 self::initHandlers();
641 return self::$handlers;
652 static $init =
false;
657 'select' => [
'ID',
'NAME',
'CODE',
'SORT',
'DESCRIPTION',
'SETTINGS',
'PROFILES'],
659 foreach ($restHandlerList as $restHandler)
661 self::$restHandlers[$restHandler[
'CODE']] = $restHandler;
665 return self::$restHandlers;
685 $result = $delivery->calculate($shipment, $extraServices);
690 $result->addError(
new Error(
"Can't create delivery service object with id: \"".$deliveryId.
"\""));
706 $group = Table::getRow([
710 '=CLASS_NAME' =>
'\Bitrix\Sale\Delivery\Services\Group',
722 'CLASS_NAME' =>
'\Bitrix\Sale\Delivery\Services\Group',
724 'CURRENCY' => Option::get(
'sale',
'default_currency'),
727 if(
$res->isSuccess())
744 $srvList = self::getActiveList();
746 foreach($srvList as $id => $srv)
748 if($srv[
'PARENT_ID'] == $parentId)
763 return 'Bitrix\Sale\Delivery\DeliveryLocation';
775 self::initHandlers();
777 if(!empty(
$fields[
"CLASS_NAME"]))
781 if (!$onBeforeAddResult->isSuccess())
783 return (
new AddResult())->addErrors($onBeforeAddResult->getErrors());
787 $res = \Bitrix\Sale\Delivery\Services\Table::add(
$fields);
789 if(
$res->isSuccess())
791 if(!empty(
$fields[
"CLASS_NAME"]))
795 self::setIdCodeCached(
$res->getId(),
$fields[
'CODE']);
806 return uniqid(
'bx_');
819 self::initHandlers();
821 if (!empty(
$fields[
"CLASS_NAME"]) && class_exists(
$fields[
"CLASS_NAME"]))
826 $res = \Bitrix\Sale\Delivery\Services\Table::update($id,
$fields);
828 if (
$res->isSuccess())
830 if (!empty(
$fields[
"CLASS_NAME"]) && class_exists(
$fields[
"CLASS_NAME"]))
837 self::cleanIdCodeCached($id);
840 if (Loader::includeModule(
'pull'))
842 \CPullWatch::AddToStack(
843 'SALE_DELIVERY_SERVICE',
845 'module_id' =>
'sale',
846 'command' =>
'onDeliveryServiceSave',
868 public static function delete($id,
bool $checkServiceUsage =
true)
875 if ($checkServiceUsage)
877 $res = self::checkServiceUsage($id);
878 if (!
$res->isSuccess())
884 self::initHandlers();
890 'select' =>
array(
'ID',
'CLASS_NAME',
'LOGOTIP')
898 $className =
$service[
'CLASS_NAME'];
899 $logotip = intval(
$service[
'LOGOTIP']);
904 if (
$res->isSuccess())
906 if (!empty($className) && class_exists($className))
908 $className::onAfterDelete($id);
911 self::deleteRelatedEntities($id, $checkServiceUsage);
915 \CFile::Delete($logotip);
929 public static function onGetBusinessValueConsumers()
937 $handlers = self::getHandlersList();
938 $consumers =
array();
941 foreach($handlers as $handlerClassName)
943 $tmpCons = $handlerClassName::onGetBusinessValueConsumers();
947 $consumers[$handlerClassName] = $tmpCons;
952 '=CLASS_NAME' => array_keys($consumers),
955 'select' =>
array(
'ID',
'CLASS_NAME',
'NAME')
958 while($dlv =
$res->fetch())
960 $result[
'DELIVERY_'.$dlv[
'ID']] = $consumers[$dlv[
'CLASS_NAME']];
961 $result[
'DELIVERY_'.$dlv[
'ID']][
'NAME'] = $dlv[
'NAME'];
967 public static function onGetBusinessValueGroups()
970 'DELIVERY' =>
array(
'NAME' => Loc::getMessage(
'SALE_DLVR_MNGR_DLV_SRVS'),
'SORT' => 100),
973 $handlers = self::getHandlersList();
976 foreach($handlers as $handlerClassName)
977 $result = array_merge(
$result, $handlerClassName::onGetBusinessValueGroups());
997 'filter' =>
array(
'PARENT_ID' => $id),
998 'select' =>
array(
'ID')
1001 while($child =
$res->fetch())
1003 $ures = self::update($child[
'ID'],
$fields);
1005 if($ures->isSuccess())
1025 foreach(self::$cachedFields as $id => $srv)
1027 if($srv[
'CODE'] ==
$code)
1041 if($handler =
$res->fetch())
1044 self::$cachedFields[$handler[
"ID"]] = $handler;
1060 $result = self::getIdCodeCached($id,
"id");
1065 $srv = self::getById($id);
1068 self::setIdCodeCached($id,
$result);
1082 $cacheId =
"SALE_DELIVERY_ID_CODE_MAP_".($type ==
"id" ?
"I" :
"C").
"_".$value;
1085 if($cacheManager->read($ttl, $cacheId))
1086 $result = $cacheManager->get($cacheId);
1099 $cacheManager->set(
"SALE_DELIVERY_ID_CODE_MAP_I_".$id,
$code);
1100 $cacheManager->set(
"SALE_DELIVERY_ID_CODE_MAP_C_".
$code, $id);
1110 $code = self::getIdCodeCached($id,
"id");
1111 $cacheManager->clean(
"SALE_DELIVERY_ID_CODE_MAP_I_".$id);
1114 $cacheManager->clean(
"SALE_DELIVERY_ID_CODE_MAP_C_".
$code);
1126 "=DELIVERY_ID" => $deliveryId,
1129 'select' =>
array(
"ID")
1150 if(self::isDeliveryInShipments($deliveryId))
1152 $result->addError(
new Error(Loc::getMessage(
'SALE_DLVR_MNGR_ERR_DEL_IN_SHPMNTS_EXIST')));
1158 "PARENT_ID" => $deliveryId
1160 'select' =>
array(
"ID")
1163 while($child =
$dbRes->fetch())
1165 if(self::isDeliveryInShipments($child[
"ID"]))
1167 $result->addError(
new Error(Loc::getMessage(
'SALE_DLVR_MNGR_ERR_DEL_IN_SHPMNTS_EXIST_CHLD')));
1188 $deliveryId = (int)$deliveryId;
1190 $con->queryExecute(
"
1191 DELETE FROM b_sale_service_rstr
1193 SERVICE_ID = " . $deliveryId .
"
1194 AND SERVICE_TYPE = " . (
int)
Restrictions\Manager::SERVICE_TYPE_SHIPMENT .
"
1196 $con->queryExecute(
"DELETE FROM b_sale_delivery2location WHERE DELIVERY_ID=".$deliveryId);
1197 $con->queryExecute(
"DELETE FROM b_sale_delivery2paysystem WHERE DELIVERY_ID=".$deliveryId);
1198 $con->queryExecute(
"DELETE FROM b_sale_delivery_es WHERE DELIVERY_ID=".$deliveryId);
1202 "PARENT_ID" => $deliveryId
1204 'select' =>
array(
"ID")
1207 while ($child =
$dbRes->fetch())
1209 self::delete($child[
"ID"], $checkServiceUsage);
1212 self::cleanIdCodeCached($deliveryId);
1222 self::initHandlers();
1223 return \Bitrix\Sale\Delivery\Services\EmptyDeliveryService::getEmptyDeliveryServiceId();
1237 public static function checkServiceRestriction($deliveryId, $checkParams, $restrictionClassName)
1239 if(empty($deliveryId))
1242 if(!is_array($deliveryId))
1243 $deliveryId =
array($deliveryId);
1245 $dbRstrRes = ServiceRestrictionTable::getList(
array(
1247 '=SERVICE_ID' => $deliveryId,
1248 '=SERVICE_TYPE' =>
Restrictions\Manager::SERVICE_TYPE_SHIPMENT,
1249 '=CLASS_NAME' => $restrictionClassName
1255 $restriction = static::getRestrictionObject($restrictionClassName);
1257 while($rstFields = $dbRstrRes->fetch())
1259 $rstParams = is_array($rstFields[
"PARAMS"]) ? $rstFields[
"PARAMS"] :
array();
1260 $tmp[$rstFields[
'SERVICE_ID']] = $restriction->check($checkParams, $rstParams, $rstFields[
'SERVICE_ID']);
1263 if(
count($deliveryId) == 1)
1264 return current(
$tmp);
1268 foreach($deliveryId as $id)
1269 if(!isset(
$tmp[$id]) || (isset(
$tmp[$id]) &&
$tmp[$id] ==
true))
1286 self::initHandlers();
1288 if(!class_exists($class))
1291 if(!is_subclass_of($class,
'Bitrix\Sale\Delivery\Services\Base'))
1307 return $delivery->calculate($shipment);
1315 if(!class_exists($className))
1318 static $cache =
array();
1320 if(isset($cache[$className]))
1321 return $cache[$className];
1323 $restriction =
new $className;
1325 if(!is_subclass_of($className,
'Bitrix\Sale\Services\Base\Restriction'))
1326 throw new SystemException(
'Object must be the instance of Bitrix\Sale\Services\Base\Restriction');
1328 $cache[$className] = $restriction;
1329 return $restriction;
1345 return self::getRestrictedObjectsList($shipment);
1353 return self::isServiceExist($deliveryId);
1361 return self::getActiveList();
1369 return self::getRestrictedList($shipment,
Restrictions\Manager::MODE_CLIENT, $skipChecks);
1377 return self::createObject($srvParams);
1393 return self::getObjectByCode($serviceCode);
1401 return self::getHandlersList();
static getConnection($name="")
static registerAutoLoadClasses($moduleName, array $classes)
static getList(array $parameters=array())
static getObjectById($id)
static getRestrictedIds(\Bitrix\Sale\Shipment $shipment=null, $restrictionMode)
static getObjectById($deliveryId)
static setIdCodeCached($id, $code)
static getRestHandlerList()
static setChildrenFieldsValues($id, array $fields)
static getRestrictedObjectsList(Shipment $shipment, $restrictionMode=Restrictions\Manager::MODE_CLIENT)
static getRestrictionObject($className)
static getList(array $params=array())
const SKIP_PROFILE_PARENT_CHECK
static calculate(Shipment $shipment)
static isExistService($deliveryId)
static deleteRelatedEntities($deliveryId, bool $checkServiceUsage=true)
static createServiceObject(array $srvParams)
static getIdCodeCached($value, $type)
static cleanIdCodeCached($id)
static getLocationConnectorEntityName()
static isDeliveryServiceClassValid($class)
static getRestrictedList(Shipment $shipment=null, $restrictionMode, array $skipChecks=array())
static getEmptyDeliveryServiceId()
static calculateDeliveryPrice(Shipment $shipment, $deliveryId=0, $extraServices=array())
static getServicesBriefsForShipment(Shipment $shipment=null, array $skipChecks=array(), $getAll=false)
static getGroupId(string $name)
static getById($deliveryId)
static createObject(array $srvParams)
static getByParentId($parentId)
static getIdByCode($code)
static getRestrictionClassNames()
static checkServiceUsage($deliveryId)
static getObjectByCode($serviceCode)
static getServiceByCode($serviceCode)
static isServiceExist($deliveryId)
static $handlersDirectories
static getActiveList($calculatingOnly=false, $restrictedIds=null)
static checkServiceRestrictions($deliveryId, Shipment $shipment, $restrictionsClassesToSkip=array())
static isDeliveryInShipments($deliveryId)
static log(array $params)
static getServicesForShipment(Shipment $shipment)
static getService($deliveryId)
static update($id, array $fields)
static getHandlersClassNames()
static getRestrictionsByDeliveryId($deliveryId)
static getPooledObject(array $fields)
const SKIP_CHILDREN_PARENT_CHECK
static checkService($serviceId, Entity $entity, $mode=self::MODE_CLIENT)
static getRestrictionsList($serviceId)
if(!is_array($prop["VALUES"])) $tmp
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
$_SERVER["DOCUMENT_ROOT"]
if(!is_null($config))($config as $configItem)(! $configItem->isVisible()) $code
sortByColumn(array &$array, $columns, $callbacks='', $defaultValueIfNotSetValue=null, $preserveKeys=false)
</p ></td >< td valign=top style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0cm 2.0pt 0cm 2.0pt;height:9.0pt'>< p class=Normal align=center style='margin:0cm;margin-bottom:.0001pt;text-align:center;line-height:normal'>< a name=ТекстовоеПоле54 ></a ><?=($taxRate > count( $arTaxList) > 0) ? $taxRate."%"
if($inWords) echo htmlspecialcharsbx(Number2Word_Rus(roundEx($totalVatSum $params['CURRENCY']