9namespace Bitrix\Sender\Integration\Crm\Connectors;
11use Bitrix\Crm\Service\Container;
12use Bitrix\Main\Application;
13use Bitrix\Main\Config\Option;
14use Bitrix\Main\DB\SqlExpression;
15use Bitrix\Main\Entity;
16use Bitrix\Main\Loader;
17use Bitrix\Main\Localization\Loc;
19use Bitrix\Main\UI\Filter\AdditionalDateType;
20use Bitrix\Main\UI\Filter\Type as UiFilterType;
21use Bitrix\Sender\Connector;
22use Bitrix\Sender\Integration;
23use Bitrix\Sender\Integration\Crm\Connectors\Personalize\BasePersonalize;
24use Bitrix\Sender\Integration\Crm\Connectors\Personalize\FactoryBased;
25use Bitrix\Sender\Recipient;
27Loc::loadMessages(__FILE__);
36 private const PERSONALIZE_NAMESPACE =
"\\Bitrix\\Sender\\Integration\\Crm\\Connectors\\Personalize\\";
48 return new Orm\Fields\ExpressionField(
50 '(' . $sqlHelper->getTopSql(
53 FROM b_crm_field_multi FM
54 WHERE FM.ENTITY_ID = '$entityName'
55 AND FM.ELEMENT_ID = %s
56 AND FM.TYPE_ID = '$multiFieldTypeId'
80 array(
'CODE' =>
'CRM_ENTITY_TYPE'),
81 array(
'CODE' =>
'CRM_ENTITY_TYPE_ID'),
82 array(
'CODE' =>
'CRM_ENTITY_ID'),
88 $documentClass = self::PERSONALIZE_NAMESPACE.ucfirst($entityType);
90 if(!is_subclass_of($documentClass, BasePersonalize::class))
95 $fields = $documentClass::isFactoryBased($entityType)
97 : $documentClass::getEntityFields($entityType);
104 return static::preparePersonalizeList($entityType,
$fields);
113 foreach (
$fields as $fieldCode => $field)
116 'CODE' => $entityType.
'.'.$fieldCode,
117 'NAME' => $field[
'Name'],
118 'DESC' => $field[
'Name'],
120 if(isset($field[
'personalizeCode']) && $field[
'personalizeCode'])
129 $name = Loc::getMessage(
'SENDER_INTEGRATION_CRM_CONNECTOR_'.$entityType);
132 $name = \CCrmOwnerType::GetDescription(\CCrmOwnerType::ResolveID($entityType));
135 'CODE' => $entityType,
145 $documentClass = self::PERSONALIZE_NAMESPACE.ucfirst($entityType);
147 if(!is_subclass_of($documentClass, BasePersonalize::class))
158 return $documentClass::isFactoryBased($entityType)
160 : $documentClass::getData($entityType, $entityIds,
$fields)
166 $connectors = Connector\Manager::getConnectorList();
176 if(method_exists(
$connector,
'getPersonalizeList'))
183 if(isset(
$data[
'ITEMS']) && in_array(
$data[
'CODE'], [
'LEAD',
'CONTACT',
'COMPANY']))
209 $ufManager = is_object(
$GLOBALS[
'USER_FIELD_MANAGER']) ?
$GLOBALS[
'USER_FIELD_MANAGER'] :
null;
215 $ufEntityId = \CCrmOwnerType::resolveUserFieldEntityID($entityTypeId);
216 $crmUserType = new \CCrmUserType($ufManager, $ufEntityId);
217 $logicFilter =
array();
220 if (!$checkAccessRights)
222 $fieldsParams = [
'skipUserFieldVisibilityCheck' =>
true];
224 $crmUserType->prepareListFilterFields($list, $logicFilter, $fieldsParams);
225 $originalList = $crmUserType->getFields($fieldsParams);
226 $restrictedTypes = [
'address',
'file',
'crm',
'resourcebooking'];
228 $list = array_filter(
230 function ($field) use ($originalList, $restrictedTypes)
232 if (empty($originalList[$field[
'id']]))
237 $type = $originalList[$field[
'id']][
'USER_TYPE'][
'USER_TYPE_ID'];
238 return !in_array(
$type, $restrictedTypes);
242 foreach ($list as $index => $field)
244 if ($field[
'type'] ===
'date')
246 $list[$index][
'include'] = [
247 AdditionalDateType::CUSTOM_DATE,
248 AdditionalDateType::PREV_DAY,
249 AdditionalDateType::NEXT_DAY,
250 AdditionalDateType::MORE_THAN_DAYS_AGO,
251 AdditionalDateType::AFTER_DAYS,
253 if (!isset($list[$index][
'allow_years_switcher']))
255 $list[$index][
'allow_years_switcher'] =
true;
258 if ($originalList[$field[
'id']][
'MULTIPLE'] ==
'Y')
260 $list[$index][
'multiple_uf'] =
true;
277 $entityDbName =
null,
283 'name' =>
'HAS_EMAIL',
288 'name' =>
'HAS_PHONE',
293 'name' =>
'HAS_IMOL',
298 'name' =>
'CONTACT_ID',
303 'name' =>
'COMPANY_ID',
309 $entityName = $entityName ?? mb_strtoupper(
$query->getEntity()->getName());
313 if (!isset(
$map[$dataTypeId]))
318 $field =
$map[$dataTypeId];
320 if($field[
'operator'] ===
null)
325 if ($dataTypeId ==
Recipient\Type::CRM_COMPANY_ID && in_array($entityName, [
'CONTACT']))
327 $field[
'name'] =
'CRM_COMPANY_ID';
330 $query->where($field[
'name'], $field[
'operator'], $field[
'value']);
333 $query->whereExists(self::getImSqlExpression(
$query, $entityDbName, $entityName));
336 else if (!in_array($entityName, [
'CONTACT',
'COMPANY']))
338 $filter = Entity\Query::filter();
339 foreach (
$map as $dataTypeId => $field)
341 if($field[
'operator'] ===
null)
349 ->where($field[
'name'], $field[
'operator'], $field[
'value'])
350 ->whereExists(self::getImSqlExpression(
$query, $entityDbName, $entityName))
355 $filter->where($field[
'name'], $field[
'operator'], $field[
'value']);
372 $entityDbName =
null,
379 $codes =
array(
'livechat',
'network');
382 $column = $entityDbName ?
'CRM_ENTITY_ID' :
'ID';
384 $entityTypeName = $entityName ?? mb_strtoupper(
$query->getEntity()->getName());
387 $regexp =
"'^imol\\\\|(" . implode(
'|', $codes) .
")'";
389 $filterImolSql =
"SELECT FM.VALUE " .
390 "FROM b_crm_field_multi FM " .
391 "WHERE FM.ENTITY_ID = '$entityTypeName' AND FM.ELEMENT_ID = ?#.{$column} " .
392 "AND FM.TYPE_ID = 'IM' " .
393 "AND NOT {$sqlHelper->getRegexpOperator('FM.VALUE', $regexp)} " .
394 "ORDER BY FM.ID LIMIT 1";
407 if (isset(self::$runtimeByEntity[$entityTypeName]))
409 return self::$runtimeByEntity[$entityTypeName];
425 $filter[$item->getKey()] = $item->getValue();
426 if (empty(self::$runtimeByEntity[$entityTypeName]))
428 self::$runtimeByEntity[$entityTypeName] = [];
430 self::$runtimeByEntity[$entityTypeName] = array_merge(
431 self::$runtimeByEntity[$entityTypeName],
433 function ($item) use ($entityTypeName)
435 $search = $entityTypeName ? $entityTypeName .
'_' :
'';
436 $runtimeName = $entityTypeName ? $entityTypeName .
'.' :
'';
437 $item[
'expression'] = str_replace(
442 $item[
'buildFrom'] = array_map(
443 function ($from) use ($search, $runtimeName)
445 return str_replace($search, $runtimeName, $from);
468 foreach ($entityTypeNames as $entityTypeName)
470 $map[$entityTypeName] =
array($entityTypeName);
472 $map[
'CLIENT'] =
array(\CCrmOwnerType::CompanyName, \CCrmOwnerType::ContactName);
473 $map[\CCrmOwnerType::CompanyName] =
array(\CCrmOwnerType::CompanyName);
474 $map[\CCrmOwnerType::ContactName] =
array(\CCrmOwnerType::ContactName);
479 if (!self::isFieldFilterable($field, $values))
485 foreach (
$map as $prefix => $entityTypes)
487 $search = $prefix .
'_';
488 if (mb_strpos($id, $search) !== 0)
493 foreach ($entityTypes as $entityTypeName)
495 $filterKey =
"$entityTypeName.".mb_substr($id, mb_strlen($search));
496 if (!self::isFieldTypeFilter($field[
'type']))
498 $filterKey =
"=$filterKey";
500 if ($field[
'multiple_uf'] ??
false)
502 $filterKey .=
"_SINGLE";
505 $field[
'sender_segment_filter'] = $filterKey;
506 if (!isset(
$result[$entityTypeName]))
511 $result[$entityTypeName][] = $field;
518 self::$runtimeByEntity = [];
521 $items = self::getFilterByFields(
$fields, $values, $entityTypeName);
532 $codeKey =
'sender_segment_filter';
533 if (isset($field[$codeKey]) && $field[$codeKey] ===
false)
538 if (!isset($values[$id]) || (!$values[$id] && !is_numeric($values[$id])))
558 if (!empty(self::$runtimeByEntity[$entityTypeName]))
560 self::$runtimeByEntity[$entityTypeName] = [];
565 self::$runtimeByEntity = [];
571 if (!self::isFieldFilterable($field, $values))
577 if (isset($field[
'params']) && is_array($field[
'params']))
579 if (isset($field[
'params'][
'multiple']) && $field[
'params'][
'multiple'])
586 $value = $values[$id];
587 $value = $isMultiple && !is_array($value) ?
array($value) :
588 ($value ===
"" ?
null:$value);
592 foreach($value as &
$val)
601 $field[
'value'] = $value;
603 if ($field[
'filter_callback'] ??
false)
605 $extraCallbackParams = [
607 'ENTITY_TYPE_NAME' => $entityTypeName
609 call_user_func_array($field[
'filter_callback'], [$value, &
$filter, $extraCallbackParams]);
613 $filterKey = self::getFilterFieldKey($field);
614 if (is_array($filterKey))
616 foreach ($filterKey as $fieldValue => $fieldFilter)
618 if ($value !== $fieldValue)
623 $filter[$fieldFilter[0]] = $fieldFilter[1];
626 elseif (self::isFieldTypeFilter($field[
'type']))
628 self::setFieldTypeFilter($filterKey, $field,
$filter);
629 self::processRuntimeFilter(
$filter, $entityTypeName);
642 $codeKey =
'sender_segment_filter';
645 if (isset($field[$codeKey]) && $field[$codeKey])
647 return $field[$codeKey];
650 if (self::isFieldTypeFilter($field[
'type']))
662 UiFilterType::NUMBER,
663 UiFilterType::DEST_SELECTOR
665 return in_array(mb_strtoupper(
$type), $types);
670 $fieldData[
'filter-key'] = $filterKey;
671 switch(mb_strtoupper($fieldData[
'type']))
673 case UiFilterType::DATE:
676 case UiFilterType::NUMBER:
679 case UiFilterType::DEST_SELECTOR:
687 if (in_array(\CCrmFieldMulti::PHONE, $commTypes))
691 if (in_array(\CCrmFieldMulti::EMAIL, $commTypes))
695 if (in_array(\CCrmFieldMulti::IM, $commTypes))
703 if (is_array($value))
708 $filter[
'@CRM_ENTITY_ID'] = array_map(
'trim', explode(
",", $value));
713 $entityTypeName = $extraCallbackParams[
'ENTITY_TYPE_NAME'];
714 $field = $extraCallbackParams[
'FIELD'];
715 if (!$entityTypeName)
718 if ($value[$field[
'id'] .
'_datesel'] !=
'NONE')
721 self::setFieldTypeFilter(
'%PURCHASE_DATE%', $field,
$filter[
'NO_PURCHASES']);
722 self::processRuntimeFilter(
$filter[
'NO_PURCHASES'], $entityTypeName);
730 if (!is_array($value) || in_array(
"", $value))
734 $filter[
'PRODUCT_SOURCE'] = $value;
741 foreach ($values as
$k => $value)
745 $filter[
'DEAL'][] = [
'SGT_DEAL.ID',
'=', $value];
746 $filter[
'DEAL'][
'JOIN_TYPE'] =
'LEFT';
752 $filter[
'DEAL'][] = [
'SGT_DEAL.CATEGORY_ID',
'in', $values];
764 switch ($row[
'CRM_ENTITY_TYPE_ID'])
766 case \CCrmOwnerType::Company:
767 $crmRow = \Bitrix\Crm\CompanyTable::getRowById($row[
'CRM_ENTITY_ID']);
768 $row[
'~NAME'] = self::getResultViewTitle(
769 $row[
'CRM_ENTITY_TYPE_ID'],
770 $row[
'CRM_ENTITY_ID'],
772 \CCrmOwnerType::GetDescription($row[
'CRM_ENTITY_TYPE_ID']),
773 self::getCrmStatusName(
'COMPANY_TYPE', $crmRow[
'COMPANY_TYPE'])
776 case \CCrmOwnerType::Contact:
777 $crmRow = \Bitrix\Crm\ContactTable::getRowById($row[
'CRM_ENTITY_ID']);
778 $row[
'~NAME'] = self::getResultViewTitle(
779 $row[
'CRM_ENTITY_TYPE_ID'],
780 $row[
'CRM_ENTITY_ID'],
782 \CCrmOwnerType::GetDescription($row[
'CRM_ENTITY_TYPE_ID']),
783 self::getCrmStatusName(
'SOURCE', $crmRow[
'SOURCE_ID'])
786 case \CCrmOwnerType::Lead:
787 $crmRow = \Bitrix\Crm\LeadTable::getRowById($row[
'CRM_ENTITY_ID']);
788 $row[
'CRM_LEAD'] = $row[
'~CRM_LEAD'] = self::getResultViewTitle(
789 $row[
'CRM_ENTITY_TYPE_ID'],
790 $row[
'CRM_ENTITY_ID'],
792 self::getCrmStatusName(
'SOURCE', $crmRow[
'SOURCE_ID']),
793 $crmRow[
'IS_RETURN_CUSTOMER'] ===
'Y' ? Loc::getMessage(
'SENDER_INTEGRATION_CRM_CONNECTOR_LEAD_FIELD_RC_LEAD') :
null
806 $sources = \CCrmStatus::GetStatus($statusType);
819 if (
$url && \CCrmAuthorizationHelper::checkReadPermission($entityTypeId,
$entityId))
826 $title .=
"<br><span style=\"color:grey; font-size: 12px;\">";
833 $title .=
"<br><span style=\"color:grey; font-size: 12px;\">";
845 return Container::getInstance()->getRouter()->getItemDetailUrl($entityTypeId,
$entityId);
847 switch ($entityTypeId)
849 case \CCrmOwnerType::Company:
852 case \CCrmOwnerType::Contact:
855 case \CCrmOwnerType::Lead:
866 [
'#company_id#',
'#contact_id#',
'#lead_id#'],
886 private static function filterOnlyAllowedFields(
string $entityType,
array $fields):
array
897 $entityField =
"$entityType.$field";
901 if (($allowedField[
'CODE'] ??
null) !== $entityType)
909 if (($item[
'CODE'] ??
null) === $entityField)
static getConnection($name="")
static includeModule($moduleName)
static create(array $data)
getResultViewTitle($entityTypeId, $entityId, $title, $secondTitle=null, $thirdTitle=null)
static getPersonalizeFieldsFromConnectors($isTrigger=false)
static getCommunicationTypeFilter(array $commTypes, &$filter, $extraCallbackParams=[])
static isCrmSaleEnabled()
static setFieldTypeFilter($filterKey, array $fieldData, &$filter)
static productSourceFilter($value, &$filter, $extraCallbackParams=[])
static buildPersonalizeList($entityType)
static getFilterFieldKey(array $field)
static preparePersonalizeList(string $entityType, array $fields)
getCrmStatusName($statusType, $statusId)
static getFilterByFields(array $fields=array(), array $values=array(), $entityTypeName='')
static isFieldTypeFilter($type)
static processRuntimeFilter(array &$filter, $entityTypeName='')
static getDealCategoryFilter($values, &$filter, $extraCallbackParams=[])
static getImSqlExpression(Entity\Query $query, $entityDbName=null, $entityName=null)
static getData($entityType, $entityIds, $fields=[' *'])
static prepareQuery(Entity\Query $query, $dataTypeId=null, $entityDbName=null, $entityName=null)
static createExpressionMultiField($entityName, $multiFieldTypeId)
static getFilterByEntity(array $fields=array(), array $values=array(), array $entityTypeNames=array())
getPathToDetail($entityTypeId, $entityId)
static getIdFilter($value, &$filter)
onResultViewDraw(array &$row)
static getPersonalizeList()
static getNoPurchasesFilter($value, &$filter, $extraCallbackParams=[])
static getRuntimeByEntity($entityTypeName='')
static getFilterUserFields(int $entityTypeId, bool $checkAccessRights=true)
static getData(string $entityType, array $entityIds, array $usedFields=[' *'], string $sortBy='id', string $sortOrder='asc')
static getEntityFields($entityType)
static getExcludedChannelCodes()
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
htmlspecialcharsbx($string, $flags=ENT_COMPAT, $doubleEncode=true)
$GLOBALS['____1690880296']
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)
if(empty($signedUserToken)) $key
</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."%"