Server IP : 80.87.202.40 / Your IP : 216.73.216.169 Web Server : Apache System : Linux rospirotorg.ru 5.14.0-539.el9.x86_64 #1 SMP PREEMPT_DYNAMIC Thu Dec 5 22:26:13 UTC 2024 x86_64 User : bitrix ( 600) PHP Version : 8.2.27 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : ON Directory : /home/bitrix/ext_www/rospirotorg.ru/bitrix/modules/sender/lib/integration/crm/connectors/ |
Upload File : |
<?php /** * Bitrix Framework * @package bitrix * @subpackage sender * @copyright 2001-2012 Bitrix */ namespace Bitrix\Sender\Integration\Crm\Connectors; use Bitrix\Crm\Category\DealCategory; use Bitrix\Crm\CompanyTable as CrmCompanyTable; use Bitrix\Crm\ContactTable as CrmContactTable; use Bitrix\Crm\PhaseSemantics; use Bitrix\Main\Application; use Bitrix\Main\DB\Result; use Bitrix\Main\DB\SqlExpression; use Bitrix\Main\Entity; use Bitrix\Main\Loader; use Bitrix\Main\Localization\Loc; use Bitrix\Main\ORM\Query\Query; use Bitrix\Main\Page\Asset; use Bitrix\Main\Type\DateTime; use Bitrix\Main\UI\Filter\AdditionalDateType; use Bitrix\Sender\Connector; use Bitrix\Sender\Connector\ResultView; use Bitrix\Sender\Integration\Sender\Holiday; use Bitrix\Sender\Recipient\Type; Loc::loadMessages(__FILE__); /** * Class Client * @package Bitrix\Sender\Integration\Crm\Connectors */ class Client extends Connector\BaseFilter implements Connector\IncrementallyConnector { const PRODUCT_SOURCE_ORDERS_ALL = "ORDERS_ALL"; const PRODUCT_SOURCE_ORDERS_PAID = "ORDERS_PAID"; const PRODUCT_SOURCE_ORDERS_UNPAID = "ORDERS_UNPAID"; const PRODUCT_SOURCE_DEALS_ALL = "DEALS_ALL"; const PRODUCT_SOURCE_DEALS_PROCESS = "DEALS_PROCESS"; const PRODUCT_SOURCE_DEALS_SUCCESS = "DEALS_SUCCESS"; const PRODUCT_SOURCE_DEALS_FAILURE = "DEALS_FAILURE"; const API_VERSION = 3; const YES = 'Y'; const NO = 'N'; const DEAL_CATEGORY_ID = "DEAL_CATEGORY_ID"; private $crmEntityFilter = null; /** * Get name. * * @return string */ public function getName() { return Loc::getMessage('SENDER_INTEGRATION_CRM_CONNECTOR_CLIENT_NAME'); } /** * Get code. * * @return string */ public function getCode() { return "crm_client"; } /** * Get queries. * * @return Entity\Query[] */ public function getQueries($selectList = []) { $queries = array(); $clientType = $this->getFieldValue('CLIENT_TYPE'); if (!$clientType || $clientType === \CCrmOwnerType::ContactName) { $queryCollection = $this->prepareQueryCollection($this->getContactQuery()); $queries = array_merge($queries, $queryCollection); } if (!$clientType || $clientType === \CCrmOwnerType::CompanyName) { $queryCollection = $this->prepareQueryCollection($this->getCompanyQuery()); $queries = array_merge($queries, $queryCollection); } return $queries; } /** * Get queries. * * @param int $offset * @param int $limit * @param string|null $excludeType * * @return Entity\Query[] */ public function getLimitedQueries(int $offset, int $limit, string $excludeType = null): array { $queries = array(); $clientType = $this->getFieldValue('CLIENT_TYPE'); if (!$clientType || $clientType === \CCrmOwnerType::ContactName) { if($excludeType !== \CCrmOwnerType::ContactName) { $this->prepareQueryForType($this->getContactQuery(), $offset, $limit, $queries); } } if (!$clientType || $clientType === \CCrmOwnerType::CompanyName) { if($excludeType !== \CCrmOwnerType::CompanyName) { $this->prepareQueryForType($this->getCompanyQuery(), $offset, $limit, $queries); } } return $queries; } public function getEntityLimitInfo(): array { $lastContact = \CCrmContact::GetListEx( ['ID' => 'DESC'], [ 'CHECK_PERMISSIONS' => 'N', '@CATEGORY_ID' => 0, ], false, ['nTopCount' => '1'], ['ID'], ['limit' => 1] )->Fetch(); $lastCompany = \CCrmCompany::GetListEx( ['ID' => 'DESC'], [ 'CHECK_PERMISSIONS' => 'N', '@CATEGORY_ID' => 0, ], false, ['nTopCount' => '1'], ['ID'] )->Fetch(); $lastContactId = $lastContact['ID'] ?? 0; $lastCompanyId = $lastCompany['ID'] ?? 0; return [ 'lastContactId' => $lastContactId, 'lastCompanyId' => $lastCompanyId, 'lastId' => max($lastCompanyId, $lastContactId), ]; } public function getLimitedData(int $offset, int $limit): ?Result { $entityInfo = $this->getEntityLimitInfo(); $excludedClass = $offset > $entityInfo['lastContactId'] ? \CCrmOwnerType::ContactName : null; $excludedClass = $offset > $entityInfo['lastCompanyId'] ? \CCrmOwnerType::CompanyName : $excludedClass; $query = QueryData::getUnionizedQuery($this->getLimitedQueries($offset, $limit, $excludedClass)); return !$query ? null : QueryData::getUnionizedData($query); } protected function prepareQueryForType(Query $query, int $from, int $to, array &$queries) { $query->whereBetween('ID', $from, $to); $queryCollection = $this->prepareQueryCollection($query); $queries = array_merge($queries, $queryCollection); } protected function getContactQuery() { $query = CrmContactTable::query(); $query->setFilter($this->getCrmEntityFilter(\CCrmOwnerType::ContactName)); if ($query->getEntity()->hasField('CATEGORY_ID')) { $query->where('CATEGORY_ID', 0); } $this->addCrmEntityReferences($query); $query->registerRuntimeField(new Entity\ExpressionField('CRM_ENTITY_TYPE_ID', \CCrmOwnerType::Contact)); $query->registerRuntimeField(new Entity\ExpressionField('CRM_ENTITY_TYPE', '\''.\CCrmOwnerType::ContactName.'\'')); $query->registerRuntimeField(new Entity\ExpressionField('CRM_COMPANY_ID', 0)); $query->registerRuntimeField(new Entity\ExpressionField('CONTACT_ID', '%s', ['ID'])); $query->registerRuntimeField(Helper::createExpressionMultiField(\CCrmOwnerType::ContactName, 'EMAIL')); $query->registerRuntimeField(Helper::createExpressionMultiField(\CCrmOwnerType::ContactName, 'PHONE')); $query->setSelect( [ 'CRM_ENTITY_ID' => 'ID', 'NAME', 'CRM_ENTITY_TYPE_ID', 'CRM_ENTITY_TYPE', 'CRM_CONTACT_ID' => 'CONTACT_ID', 'CRM_COMPANY_ID', 'HAS_EMAIL', 'HAS_PHONE', 'HAS_IMOL', ] ); return $query; } protected function getCompanyQuery() { $query = CrmCompanyTable::query(); $query->setFilter($this->getCrmEntityFilter(\CCrmOwnerType::CompanyName)); if ($query->getEntity()->hasField('CATEGORY_ID')) { $query->where('CATEGORY_ID', 0); } $this->addCrmEntityReferences($query); $query->registerRuntimeField(new Entity\ExpressionField('CRM_ENTITY_TYPE_ID', \CCrmOwnerType::Company)); $query->registerRuntimeField(new Entity\ExpressionField('CRM_ENTITY_TYPE', '\''.\CCrmOwnerType::CompanyName.'\'')); $query->registerRuntimeField(new Entity\ExpressionField('CONTACT_ID', 0)); $query->registerRuntimeField(new Entity\ExpressionField('COMPANY_ID', '%s', ['ID'])); $query->registerRuntimeField(Helper::createExpressionMultiField(\CCrmOwnerType::CompanyName, 'EMAIL')); $query->registerRuntimeField(Helper::createExpressionMultiField(\CCrmOwnerType::CompanyName, 'PHONE')); $query->setSelect( [ 'CRM_ENTITY_ID' => 'ID', 'NAME' => 'TITLE', 'CRM_ENTITY_TYPE_ID', 'CRM_ENTITY_TYPE', 'CRM_CONTACT_ID' => 'CONTACT_ID', 'CRM_COMPANY_ID' => 'COMPANY_ID', 'HAS_EMAIL', 'HAS_PHONE', 'HAS_IMOL', ] ); return $query; } protected function addCrmEntityReferences(Entity\Query $query) { $docTypes = array(); $docType = $this->getFieldValue('DOC_TYPE'); if ($docType) { $docTypes[] = $docType; } else { foreach (array_keys(self::getCrmDocumentTypes()) as $entityTypeName) { $filter = $this->getCrmReferencedEntityFilter($entityTypeName); if (count($filter) === 0) { continue; } $docTypes[] = $entityTypeName; } } foreach ($docTypes as $docType) { $refClassName = "\\Bitrix\\Crm\\" . ucfirst(mb_strtolower($docType)) . "Table"; if (!class_exists($refClassName)) { continue; } if ($query->getEntity()->getName() === 'Contact') { $ref = array('=this.ID' => 'ref.CONTACT_ID'); } elseif ($query->getEntity()->getName() === 'Company') { $ref = array('=this.ID' => 'ref.COMPANY_ID'); } else { continue; } $runtimeFieldName = "SGT_$docType"; $filter = $this->getCrmReferencedEntityFilter($docType); $joinType = $filter[$docType]['JOIN_TYPE']??'INNER'; unset($filter[$docType]['JOIN_TYPE']); $query->registerRuntimeField(null, new Entity\ReferenceField( $runtimeFieldName, $refClassName, $ref, array('join_type' => $joinType) )); foreach ($filter as $key => $value) { $pattern = "/^[\W]{0,2}$docType\./"; if (preg_match($pattern, $key)) { $key = str_replace("$docType.", "$runtimeFieldName.", $key); } $query->addFilter($key, $value); } $runtime = Helper::getRuntimeByEntity($docType); foreach ($runtime as $item) { $item = new Entity\ExpressionField( $item['name'], str_replace("$docType.", "$runtimeFieldName.", $item['expression']), array_map( function ($from) use ($docType, $runtimeFieldName) { return str_replace("$docType.", "$runtimeFieldName.", $from); }, $item['buildFrom'] ) ); $query->registerRuntimeField($item); } } $entityTypeName = mb_strtoupper($query->getEntity()->getName()); $runtime = Helper::getRuntimeByEntity($entityTypeName); foreach ($runtime as $item) { $item = new Entity\ExpressionField( $item['name'], $item['expression'], array_map( function ($from) use ($entityTypeName) { return str_replace("$entityTypeName.", "", $from); }, $item['buildFrom'] ) ); $query->registerRuntimeField($item); } $filterFields = $query->getFilter(); if (array_key_exists('NO_PURCHASES', $filterFields)) { $noPurchasesFilter = $filterFields['NO_PURCHASES']; $productSource = $filterFields['PRODUCT_SOURCE']; unset($filterFields['NO_PURCHASES']); $query->setFilter($filterFields); $this->addNoPurchasesFilter($query, $noPurchasesFilter, $productSource); } if (array_key_exists('DEAL', $filterFields)) { $query->where(\Bitrix\Main\Entity\Query::filter() ->logic('or') ->where($filterFields['DEAL']) ); unset($filterFields['DEAL']); $query->setFilter($filterFields); } } /** * Add filter to exclude contacts/companies who has deals/orders in $filterValue period * @param Entity\Query $query Modifying query. * @param array $filterValue No purchases period. * @param array $productSource Purchases source (deal, order, etc). * @return void * @throws \Bitrix\Main\ArgumentException * @throws \Bitrix\Main\ArgumentTypeException * @throws \Bitrix\Main\ObjectException * @throws \Bitrix\Main\SystemException */ protected function addNoPurchasesFilter($query, $filterValue, $productSource) { $sqlHelper = Application::getConnection()->getSqlHelper(); $dealQuery = \Bitrix\Crm\DealTable::query(); if (is_array($productSource)) { $semantics = []; if (in_array(self::PRODUCT_SOURCE_DEALS_PROCESS, $productSource)) { $semantics[] = \Bitrix\Crm\PhaseSemantics::PROCESS; } if (in_array(self::PRODUCT_SOURCE_DEALS_SUCCESS, $productSource)) { $semantics[] = \Bitrix\Crm\PhaseSemantics::SUCCESS; } if (in_array(self::PRODUCT_SOURCE_DEALS_FAILURE, $productSource)) { $semantics[] = \Bitrix\Crm\PhaseSemantics::FAILURE; } if ($semantics && count($semantics) < 3) { $dealQuery->whereIn('STAGE_SEMANTIC_ID', $semantics); } } $dealsFilter = []; foreach ($filterValue as $filterCode => $date) { $dealsFilter[str_replace('%PURCHASE_DATE%', 'DATE_CREATE', $filterCode)] = new SqlExpression($sqlHelper->convertToDbDateTime(new DateTime($date))); } $dealQuery->setFilter($dealsFilter); $orderQuery = null; if (Helper::isCrmSaleEnabled()) { $orderQuery = \Bitrix\Crm\Binding\OrderContactCompanyTable::query(); $orderQuery->addSelect('ENTITY_ID', 'EID'); if (is_array($productSource)) { if (in_array(self::PRODUCT_SOURCE_ORDERS_PAID, $productSource) && !in_array(self::PRODUCT_SOURCE_ORDERS_UNPAID, $productSource)) { $orderQuery->where('ORDER.PAYED', true); } if (!in_array(self::PRODUCT_SOURCE_ORDERS_PAID, $productSource) && in_array(self::PRODUCT_SOURCE_ORDERS_UNPAID, $productSource)) { $orderQuery->where('ORDER.PAYED', false); } } $orderQuery->whereNotNull('ENTITY_ID'); $ordersFilter = []; foreach ($filterValue as $filterCode => $date) { $ordersFilter[str_replace('%PURCHASE_DATE%', 'ORDER.DATE_INSERT', $filterCode)] = new SqlExpression($sqlHelper->convertToDbDateTime(new DateTime($date))); } $orderQuery->setFilter($ordersFilter); } if ($query->getEntity()->getName() === 'Contact') { $dealQuery->addSelect('CONTACT_ID', 'EID'); $dealQuery->whereNotNull('CONTACT_ID'); if ($orderQuery) { $orderQuery->where('ENTITY_TYPE_ID', \CCrmOwnerType::Contact); } } elseif ($query->getEntity()->getName() === 'Company') { $dealQuery->addSelect('COMPANY_ID', 'EID'); $dealQuery->whereNotNull('COMPANY_ID'); if ($orderQuery) { $orderQuery->where('ENTITY_TYPE_ID', \CCrmOwnerType::Company); } } $dealsAreRequired = empty($productSource) || array_intersect($productSource, [self::PRODUCT_SOURCE_DEALS_PROCESS, self::PRODUCT_SOURCE_DEALS_SUCCESS, self::PRODUCT_SOURCE_DEALS_FAILURE]); $ordersAreRequired = empty($productSource) || array_intersect($productSource, [self::PRODUCT_SOURCE_ORDERS_PAID, self::PRODUCT_SOURCE_ORDERS_UNPAID]); $idSubQuery = false; if ($orderQuery && $dealsAreRequired && $ordersAreRequired) { $idSubQuery = new SqlExpression($dealQuery->getQuery() . ' UNION ALL ' . $orderQuery->getQuery()); } elseif ($orderQuery && $ordersAreRequired) { $idSubQuery = $orderQuery; } elseif ($dealsAreRequired) { $idSubQuery = $dealQuery; } if ($idSubQuery) { $query->whereNotIn('ID', $idSubQuery); } } protected function prepareQueryCollection(Entity\Query $query) { $result = [$query]; $filterFields = $query->getFilter(); $productSource = $filterFields['PRODUCT_SOURCE'] ?? ''; unset($filterFields['PRODUCT_SOURCE']); $query->setFilter($filterFields); $productFilterKey = '=PRODUCT_ID'; if (array_key_exists($productFilterKey, $filterFields)) { $productIds = $filterFields[$productFilterKey]; unset($filterFields[$productFilterKey]); $query->setFilter($filterFields); $productIds = array_merge($productIds, $this->getProductSkuIds($productIds)); if (empty($productIds)) { return $result; } $result = $this->getQueryCollectionForProductsFilter($query, $productIds, $productSource); } return $result; } protected function getQueryCollectionForProductsFilter(Entity\Query $query, $productIds, $productSource) { $orderRef = [ '=this.ID' => 'ref.ENTITY_ID', ]; $dealRef = []; $entityName = $query->getEntity()->getName(); if ($entityName === 'Contact') { $orderRef['ref.ENTITY_TYPE_ID'] = new SqlExpression('?i', \CCrmOwnerType::Contact); $dealRef['=this.ID'] = 'ref.CONTACT_ID'; $extraQuery = $this->getContactQuery(); } elseif ($entityName === 'Company') { $orderRef['ref.ENTITY_TYPE_ID'] = new SqlExpression('?i', \CCrmOwnerType::Company); $dealRef['=this.ID'] = 'ref.COMPANY_ID'; $extraQuery = $this->getCompanyQuery(); } else { return [$query]; } $query->whereIn('SGT_DEAL.PRODUCT_ROW.PRODUCT_ID', $productIds); $semantics = []; if (is_array($productSource)) { if (in_array(self::PRODUCT_SOURCE_DEALS_PROCESS, $productSource)) { $semantics[] = \Bitrix\Crm\PhaseSemantics::PROCESS; } if (in_array(self::PRODUCT_SOURCE_DEALS_SUCCESS, $productSource)) { $semantics[] = \Bitrix\Crm\PhaseSemantics::SUCCESS; } if (in_array(self::PRODUCT_SOURCE_DEALS_FAILURE, $productSource)) { $semantics[] = \Bitrix\Crm\PhaseSemantics::FAILURE; } } switch (count($semantics)) { case 1: $dealRef['ref.STAGE_SEMANTIC_ID'] = new SqlExpression('?', $semantics[0]); break; case 2: $dealRef['@ref.STAGE_SEMANTIC_ID'] = new SqlExpression('?, ?', $semantics[0], $semantics[1]); break; } $query->registerRuntimeField(new Entity\ReferenceField( 'SGT_DEAL', '\Bitrix\Crm\DealTable', $dealRef, array('join_type' => 'LEFT') )); $query->addSelect("SGT_DEAL.ID", "SGT_DEAL_ID"); $extraQuery->setFilter($query->getFilter()); // apply actual user filter $extraQuery->registerRuntimeField(new Entity\ReferenceField( 'PROD_CRM_ORDER', '\Bitrix\Crm\Binding\OrderContactCompanyTable', $orderRef, array('join_type' => 'LEFT') )); $extraQuery->addSelect("PROD_CRM_ORDER.ID", "PROD_CRM_ORDER_ID"); $extraQuery->registerRuntimeField(new Entity\ReferenceField( 'PROD_CRM_ORDER_PRODUCT', '\Bitrix\Sale\Internals\BasketTable', [ '=this.PROD_CRM_ORDER.ORDER_ID' => 'ref.ORDER_ID' ], array('join_type' => 'LEFT') )); $extraQuery->whereIn('PROD_CRM_ORDER_PRODUCT.PRODUCT_ID', $productIds); if (is_array($productSource)) { if (in_array(self::PRODUCT_SOURCE_ORDERS_PAID, $productSource) && !in_array(self::PRODUCT_SOURCE_ORDERS_UNPAID, $productSource)) { $extraQuery->where('PROD_CRM_ORDER.ORDER.PAYED', true); } if (!in_array(self::PRODUCT_SOURCE_ORDERS_PAID, $productSource) && in_array(self::PRODUCT_SOURCE_ORDERS_UNPAID, $productSource)) { $extraQuery->where('PROD_CRM_ORDER.ORDER.PAYED', false); } } $result = []; $dealsAreRequired = empty($productSource) || array_intersect($productSource, [self::PRODUCT_SOURCE_DEALS_PROCESS, self::PRODUCT_SOURCE_DEALS_SUCCESS, self::PRODUCT_SOURCE_DEALS_FAILURE]); $ordersAreRequired = empty($productSource) || array_intersect($productSource, [self::PRODUCT_SOURCE_ORDERS_PAID, self::PRODUCT_SOURCE_ORDERS_UNPAID]); $dataTypeId = $this->getDataTypeId(); if ($dataTypeId == Type::CRM_ORDER_PRODUCT_CONTACT_ID && $ordersAreRequired) { if ($entityName === 'Contact') { $result[] = $extraQuery; } } elseif ($dataTypeId == Type::CRM_ORDER_PRODUCT_COMPANY_ID && $ordersAreRequired) { if ($entityName === 'Company') { $result[] = $extraQuery; } } elseif ($dataTypeId == Type::CRM_DEAL_PRODUCT_CONTACT_ID && $dealsAreRequired) { if ($entityName === 'Contact') { $result[] = $query; } } elseif ($dataTypeId == Type::CRM_DEAL_PRODUCT_COMPANY_ID && $dealsAreRequired) { if ($entityName === 'Company') { $result[] = $query; } } else { if ($dealsAreRequired) { $result[] = $query; } if ($ordersAreRequired) { $result[] = $extraQuery; } } return $result; } protected function getCrmReferencedEntityFilter($entityTypeName) { return $this->getCrmEntityFilter($entityTypeName, true); } protected function getCrmEntityFilter($entityTypeName, $isReferenced = false) { if ($this->crmEntityFilter === null) { $this->crmEntityFilter = Helper::getFilterByEntity( self::getUiFilterFields(), $this->getFieldValues(), array_keys(self::getCrmDocumentTypes()) ); } if (isset($this->crmEntityFilter[$entityTypeName])) { $filter = $this->crmEntityFilter[$entityTypeName]; } else { $filter = array(); } if ($isReferenced && count($filter) === 0) { return $filter; } $commonNames = ['ASSIGNED_BY_ID', 'EMAIL', 'PHONE', 'NAME']; if ($isReferenced) { $commonNames = ['ASSIGNED_BY_ID']; } foreach ($commonNames as $commonName) { $value = $this->getFieldValue($commonName); if (!$value) { continue; } if (in_array($commonName, ['EMAIL', 'PHONE', 'NAME'])) { $commonName = "%$entityTypeName.$commonName"; } else { $commonName = "=$entityTypeName.$commonName"; } $filter[$commonName] = $value; } if ($isReferenced) { return $filter; } foreach ($filter as $key => $value) { $pattern = "/^([\W]{0,2})$entityTypeName\./"; if (!preg_match($pattern, $key)) { continue; } unset($filter[$key]); $key = preg_replace($pattern, '$1', $key); $filter[$key] = $value; } return $filter; } protected static function getCrmDocumentTypes() { $types = array(\CCrmOwnerType::Deal); $list = array(); foreach ($types as $typeId) { $typeName = \CCrmOwnerType::resolveName($typeId); $typeCaption = \CCrmOwnerType::getDescription($typeId); $list[$typeName] = $typeCaption; } return $list; } /** * Get data count by type. * * @return array */ protected function getDataCountByType() { if (!$this->hasFieldValues()) { return array(); } return QueryCount::getUnionizedCount($this->getQueries(), $this->getDataTypeId()); } /** * Get data. * * @return array|\Bitrix\Main\DB\Result */ public function getData() { if (!$this->hasFieldValues()) { return array(); } $query = QueryData::getUnionizedQuery( $this->getQueries(), $this->getDataTypeId(), $this->getResultView()->getNav() ); return QueryData::getUnionizedData($query); } /** * Get personalize field list. * * @return array */ public static function getPersonalizeList() { return Loader::includeModule('crm') ? array_merge( Helper::getPersonalizeList(), Helper::buildPersonalizeList(\CCrmOwnerType::ContactName), Helper::buildPersonalizeList(\CCrmOwnerType::CompanyName) ) : Helper::getPersonalizeList(); } public static function getDealCategoryList() { return Loader::includeModule('crm') ? DealCategory::getSelectListItems(true) : []; } public static function getDealCategoryStageList() { return Loader::includeModule('crm') ? DealCategory::getFullStageList() : []; } /** * Get filter fields. * * @return array */ public static function getUiFilterFields(bool $checkAccessRights = true) { $list = [ [ 'id' => 'EMAIL', 'type' => 'string', 'sender_segment_filter' => '%EMAIL', 'sender_internal' => true ], [ 'id' => 'PHONE', 'type' => 'string', 'sender_segment_filter' => '%PHONE', 'sender_internal' => true ], [ 'id' => 'NAME', 'type' => 'string', 'sender_segment_filter' => '%NAME', 'sender_internal' => true ], [ 'id' => 'CLIENT_ID', 'type' => 'string', 'params' => array('hidden' => self::YES), "name" => 'ID', "default" => true, 'filter_callback' => ['\Bitrix\Sender\Integration\Crm\Connectors\Helper', 'getIdFilter'] ], ]; $list[] = array( "id" => "DOC_TYPE", "name" => Loc::getMessage('SENDER_INTEGRATION_CRM_CONNECTOR_CLIENT_FIELD_DOC_TYPE'), "type" => "list", "items" => self::getCrmDocumentTypes(), "sender_segment_filter" => false, "default" => true, ); $list[] = array( "id" => "CLIENT_TYPE", "name" => Loc::getMessage('SENDER_INTEGRATION_CRM_CONNECTOR_CLIENT_FIELD_CLIENT_TYPE'), "type" => "list", "items" => array( "" => Loc::getMessage( 'SENDER_INTEGRATION_CRM_CONNECTOR_CLIENT_FIELD_CLIENT_TYPE_NOT_SET', [ '%default%' => \CCrmOwnerType::getDescription(\CCrmOwnerType::Contact) . ", " . \CCrmOwnerType::getDescription(\CCrmOwnerType::Company), ] ), \CCrmOwnerType::ContactName => \CCrmOwnerType::getDescription(\CCrmOwnerType::Contact), \CCrmOwnerType::CompanyName => \CCrmOwnerType::getDescription(\CCrmOwnerType::Company), ), "sender_segment_filter" => false, "default" => true ); $list[] = array( "id" => "DEAL_DATE_CREATE", "name" => Loc::getMessage('SENDER_INTEGRATION_CRM_CONNECTOR_CLIENT_FIELD_DEAL_DATE_CREATE'), "type" => "date", "include" => [ AdditionalDateType::CUSTOM_DATE, AdditionalDateType::PREV_DAY, AdditionalDateType::NEXT_DAY, AdditionalDateType::MORE_THAN_DAYS_AGO, AdditionalDateType::AFTER_DAYS, ], "allow_years_switcher" => true, "default" => true ); $stageList = self::getDealCategoryStageList(); $list[] = array( "id" => "DEAL_STAGE_ID", "name" => Loc::getMessage('SENDER_INTEGRATION_CRM_CONNECTOR_CLIENT_FIELD_DEAL_STATUS_ID'), "type" => "list", 'params' => array('multiple' => self::YES), "items" => $stageList, "default" => true ); $list[] = array( "id" => "CONTACT_SOURCE_ID", "name" => Loc::getMessage('SENDER_INTEGRATION_CRM_CONNECTOR_CLIENT_FIELD_CONTACT_SOURCE_ID'), "type" => "list", 'params' => array('multiple' => self::YES), "items" => \CCrmStatus::GetStatusList('SOURCE'), "default" => true ); $list[] = array( 'id' => 'CLIENT_COMMUNICATION_TYPE', "name" => Loc::getMessage('SENDER_INTEGRATION_CRM_CONNECTOR_CLIENT_FIELD_COMMUNICATION_TYPE'), 'params' => array('multiple' => self::YES), 'default' => true, 'type' => 'list', 'items' => \CCrmFieldMulti::PrepareListItems(array( \CCrmFieldMulti::PHONE, \CCrmFieldMulti::EMAIL, \CCrmFieldMulti::IM )), 'filter_callback' => ['\Bitrix\Sender\Integration\Crm\Connectors\Helper', 'getCommunicationTypeFilter'] ); $list[] = array( "id" => "CLIENT_NO_PURCHASES_DATE", "name" => Loc::getMessage('SENDER_INTEGRATION_CRM_CONNECTOR_CLIENT_FIELD_NO_PURCHASES_DATE'), "type" => "date", "exclude" => [ \Bitrix\Main\UI\Filter\DateType::TOMORROW, \Bitrix\Main\UI\Filter\DateType::NEXT_DAYS, \Bitrix\Main\UI\Filter\DateType::NEXT_WEEK, \Bitrix\Main\UI\Filter\DateType::NEXT_MONTH, ], "default" => true, 'messages' => [ 'MAIN_UI_FILTER_FIELD_SUBTYPE_NONE' => '' ], 'filter_callback' => ['\Bitrix\Sender\Integration\Crm\Connectors\Helper', 'getNoPurchasesFilter'] ); if (Helper::isCrmSaleEnabled()) { $list[] = array( 'id' => 'CLIENT_PRODUCT_ID', "name" => Loc::getMessage("SENDER_INTEGRATION_CRM_CONNECTOR_CLIENT_FIELD_DEAL_PRODUCT_ID"), 'default' => true, 'type' => 'dest_selector', 'partial' => true, 'params' => array( 'multiple' => self::YES, 'apiVersion' => self::API_VERSION, 'context' => 'SENDER_FILTER_PRODUCT_ID', 'contextCode' => 'CRM', 'useClientDatabase' => self::NO, 'enableAll' => self::NO, 'enableDepartments' => self::NO, 'enableUsers' => self::NO, 'enableSonetgroups' => self::NO, 'allowEmailInvitation' => self::NO, 'allowSearchEmailUsers' => self::NO, 'departmentSelectDisable' => self::YES, 'addTabCrmProducts' => self::YES, 'enableCrm' => self::YES, 'enableCrmProducts' => self::YES, 'convertJson' => self::YES ), ); $list[] = array( 'id' => 'CLIENT_PRODUCT_SOURCE', "name" => Loc::getMessage('SENDER_INTEGRATION_CRM_CONNECTOR_CLIENT_FIELD_PRODUCT_SOURCE'), 'default' => true, 'type' => 'list', 'params' => array( 'multiple' => self::YES, ), 'items' => [ "" => Loc::getMessage('SENDER_INTEGRATION_CRM_CONNECTOR_CLIENT_FIELD_PRODUCT_SOURCE_ANY'), self::PRODUCT_SOURCE_ORDERS_PAID => Loc::getMessage('SENDER_INTEGRATION_CRM_CONNECTOR_CLIENT_FIELD_PRODUCT_SOURCE_ORDERS_PAID'), self::PRODUCT_SOURCE_ORDERS_UNPAID => Loc::getMessage('SENDER_INTEGRATION_CRM_CONNECTOR_CLIENT_FIELD_PRODUCT_SOURCE_ORDERS_UNPAID'), self::PRODUCT_SOURCE_DEALS_PROCESS => Loc::getMessage('SENDER_INTEGRATION_CRM_CONNECTOR_CLIENT_FIELD_PRODUCT_SOURCE_DEALS_PROCESS'), self::PRODUCT_SOURCE_DEALS_SUCCESS => Loc::getMessage('SENDER_INTEGRATION_CRM_CONNECTOR_CLIENT_FIELD_PRODUCT_SOURCE_DEALS_SUCCESS'), self::PRODUCT_SOURCE_DEALS_FAILURE => Loc::getMessage('SENDER_INTEGRATION_CRM_CONNECTOR_CLIENT_FIELD_PRODUCT_SOURCE_DEALS_FAILURE'), ], 'filter_callback' => ['\Bitrix\Sender\Integration\Crm\Connectors\Helper', 'productSourceFilter'] ); } else { $list[] = array( 'id' => 'DEAL_PRODUCT_ROW.PRODUCT_ID', "name" => Loc::getMessage("SENDER_INTEGRATION_CRM_CONNECTOR_CLIENT_FIELD_DEAL_PRODUCT_ID"), 'default' => true, 'type' => 'dest_selector', 'partial' => true, 'params' => array( 'multiple' => self::YES, 'apiVersion' => self::API_VERSION, 'context' => 'SENDER_FILTER_PRODUCT_ID', 'contextCode' => 'CRM', 'useClientDatabase' => self::NO, 'enableAll' => self::NO, 'enableDepartments' => self::NO, 'enableUsers' => self::NO, 'enableSonetgroups' => self::NO, 'allowEmailInvitation' => self::NO, 'allowSearchEmailUsers' => self::NO, 'departmentSelectDisable' => self::YES, 'addTabCrmProducts' => self::YES, 'enableCrm' => self::YES, 'enableCrmProducts' => self::YES, 'convertJson' => self::YES ) ); } $list[] = PhaseSemantics::getListFilterInfo( \CCrmOwnerType::Deal, array( 'id' => 'DEAL_STAGE_SEMANTIC_ID', "name" => Loc::getMessage('SENDER_INTEGRATION_CRM_CONNECTOR_CLIENT_FIELD_DEAL_STATUS_SEMANTIC_ID'), 'default' => true, 'params' => array('multiple' => self::YES) ), true ); $list[] = array( "id" => "CONTACT_POST", 'type' => 'string', "name" => Loc::getMessage('SENDER_INTEGRATION_CRM_CONNECTOR_CLIENT_FIELD_CONTACT_POST'), 'params' => array('multiple' => self::YES), "default" => false ); $list[] = array( "id" => "ASSIGNED_BY_ID", "name" => Loc::getMessage('SENDER_INTEGRATION_CRM_CONNECTOR_CLIENT_FIELD_ASSIGNED_BY_ID'), 'type' => 'dest_selector', 'params' => array( 'context' => 'SENDER_FILTER_ASSIGNED_BY_ID', 'multiple' => self::YES, 'contextCode' => 'U', 'enableAll' => self::NO, 'enableSonetgroups' => self::NO, 'allowEmailInvitation' => self::NO, 'allowSearchEmailUsers' => self::NO, 'departmentSelectDisable' => self::YES, 'isNumeric' => self::YES, 'prefix' => 'U' ), "sender_segment_filter" => false, "default" => false ); foreach ([\CCrmOwnerType::Company, \CCrmOwnerType::Contact, \CCrmOwnerType::Deal] as $entityTypeId) { $entityTypeCaption = \CCrmOwnerType::getDescription($entityTypeId); $entityTypeName = \CCrmOwnerType::resolveName($entityTypeId); $fieldId = "{$entityTypeName}_ASSIGNED_BY_ID"; $list[] = array( "id" => $fieldId, "name" => Loc::getMessage('SENDER_INTEGRATION_CRM_CONNECTOR_CLIENT_FIELD_ASSIGNED_BY_ID') . " ($entityTypeCaption)", 'type' => 'dest_selector', 'params' => array( 'context' => 'SENDER_FILTER_ASSIGNED_BY_ID', 'multiple' => self::YES, 'contextCode' => 'U', 'enableAll' => self::NO, 'enableSonetgroups' => self::NO, 'allowEmailInvitation' => self::NO, 'allowSearchEmailUsers' => self::NO, 'departmentSelectDisable' => self::YES, 'isNumeric' => self::YES, 'prefix' => 'U' ), //"sender_segment_filter" => false, "default" => false ); } $list[] = array( "id" => "CONTACT_BIRTHDATE", "name" => Loc::getMessage('SENDER_INTEGRATION_CRM_CONNECTOR_CLIENT_FIELD_CONTACT_BIRTHDATE'), 'type' => 'date', "include" => [ AdditionalDateType::CUSTOM_DATE, AdditionalDateType::PREV_DAY, AdditionalDateType::NEXT_DAY, AdditionalDateType::MORE_THAN_DAYS_AGO, AdditionalDateType::AFTER_DAYS, ], "allow_years_switcher" => true, "default" => false, ); //we need to filter able deals $list[] = array( 'id' => self::DEAL_CATEGORY_ID, 'name' => Loc::getMessage('SENDER_INTEGRATION_CRM_CONNECTOR_CLIENT_FIELD_DEAL_CATEGORY_ID_MSG_1'), 'params' => array('multiple' => self::YES), 'default' => true, 'type' => 'list', 'required' => true, 'valueRequired' => true, 'items' => self::getDealCategoryList(), 'filter_callback' => ['\Bitrix\Sender\Integration\Crm\Connectors\Helper', 'getDealCategoryFilter'] ); $list[] = array( "id" => "DEAL_TYPE_ID", "name" => Loc::getMessage('SENDER_INTEGRATION_CRM_CONNECTOR_CLIENT_FIELD_DEAL_TYPE_ID'), "type" => "list", 'params' => array('multiple' => self::YES), "items" => \CCrmStatus::GetStatusList('DEAL_TYPE'), "default" => false ); $list[] = array( "id" => "DEAL_OPPORTUNITY", "name" => Loc::getMessage('SENDER_INTEGRATION_CRM_CONNECTOR_CLIENT_FIELD_DEAL_OPPORTUNITY'), "type" => "number", "default" => false ); $list[] = array( "id" => "DEAL_CLOSEDATE", "name" => Loc::getMessage('SENDER_INTEGRATION_CRM_CONNECTOR_CLIENT_FIELD_DEAL_CLOSEDATE'), "type" => "date", "include" => [ AdditionalDateType::CUSTOM_DATE, AdditionalDateType::PREV_DAY, AdditionalDateType::NEXT_DAY, AdditionalDateType::MORE_THAN_DAYS_AGO, AdditionalDateType::AFTER_DAYS, ], "allow_years_switcher" => true, "default" => false ); $list[] = array( 'id' => 'COMPANY_COMPANY_TYPE', 'name' => Loc::getMessage('SENDER_INTEGRATION_CRM_CONNECTOR_CLIENT_FIELD_COMPANY_TYPE'), 'params' => array('multiple' => self::YES), 'default' => false, 'type' => 'list', 'items' => \CCrmStatus::GetStatusList('COMPANY_TYPE'), ); $list[] = array( 'id' => 'CONTACT_TYPE_ID', 'name' => Loc::getMessage('SENDER_INTEGRATION_CRM_CONNECTOR_CLIENT_FIELD_CONTACT_TYPE'), 'params' => array('multiple' => self::YES), 'default' => false, 'type' => 'list', 'items' => \CCrmStatus::GetStatusList('CONTACT_TYPE'), ); $list[] = array( 'id' => 'CONTACT_HONORIFIC', 'name' => Loc::getMessage('SENDER_INTEGRATION_CRM_CONNECTOR_CLIENT_FIELD_CONTACT_HONORIFIC'), 'params' => array('multiple' => self::YES), 'default' => false, 'type' => 'list', 'items' => \CCrmStatus::GetStatusList('HONORIFIC'), ); $list[] = array( 'id' => 'COMPANY_INDUSTRY', 'name' => Loc::getMessage('SENDER_INTEGRATION_CRM_CONNECTOR_CLIENT_FIELD_COMPANY_INDUSTRY'), 'params' => array('multiple' => self::YES), 'default' => false, 'type' => 'list', 'items' => \CCrmStatus::GetStatusList('INDUSTRY'), ); $entityTypes = array_merge( array( \CCrmOwnerType::ContactName, \CCrmOwnerType::CompanyName, ), array_keys(self::getCrmDocumentTypes()) ); foreach ($entityTypes as $entityTypeName) { $entityTypeId = \CCrmOwnerType::resolveId($entityTypeName); $entityTypeCaption = \CCrmOwnerType::getDescription($entityTypeId); $ufList = Helper::getFilterUserFields($entityTypeId, $checkAccessRights); foreach ($ufList as $item) { if (isset($item['name'])) { $item['name'] .= " ($entityTypeCaption)"; } elseif (isset($item['NAME'])) { $item['NAME'] .= " ($entityTypeCaption)"; } if (isset($item['id'])) { $item['id'] = $entityTypeName . "_" . $item['id']; } elseif (isset($item['ID'])) { $item['ID'] = $entityTypeName . "_" . $item['ID']; } $list[] = $item; } } return $list; } /** * Get filter presets. * * @return array */ public static function getUiFilterPresets() { $list = array( 'crm_client_all' => array( 'name' => Loc::getMessage('SENDER_INTEGRATION_CRM_CONNECTOR_CLIENT_PRESET_ALL'), 'sender_segment_name' => Loc::getMessage('SENDER_INTEGRATION_CRM_CONNECTOR_CLIENT_PRESET_SEGMENT_ALL'), 'fields' => array( self::FIELD_FOR_PRESET_ALL => self::YES, ) ), 'crm_client_deal_in_work' => array( 'name' => Loc::getMessage('SENDER_INTEGRATION_CRM_CONNECTOR_CLIENT_PRESET_DEAL_INW'), 'sender_segment_name' => Loc::getMessage('SENDER_INTEGRATION_CRM_CONNECTOR_CLIENT_PRESET_SEGMENT_DEAL_INW'), 'fields' => array( 'DEAL_STAGE_SEMANTIC_ID' => array(PhaseSemantics::PROCESS), ) ), 'crm_client_deal_won' => array( 'name' => Loc::getMessage('SENDER_INTEGRATION_CRM_CONNECTOR_CLIENT_PRESET_DEAL_WON'), 'sender_segment_name' => Loc::getMessage('SENDER_INTEGRATION_CRM_CONNECTOR_CLIENT_PRESET_SEGMENT_DEAL_WON'), 'fields' => array( 'DEAL_STAGE_SEMANTIC_ID' => array(PhaseSemantics::SUCCESS), ) ), 'crm_client_deal_loose' => array( 'name' => Loc::getMessage('SENDER_INTEGRATION_CRM_CONNECTOR_CLIENT_PRESET_DEAL_LOOSE'), 'sender_segment_name' => Loc::getMessage('SENDER_INTEGRATION_CRM_CONNECTOR_CLIENT_PRESET_SEGMENT_DEAL_LOOSE'), 'fields' => array( 'DEAL_STAGE_SEMANTIC_ID' => array(PhaseSemantics::FAILURE), ) ), 'crm_client_birthday' => array( 'name' => Loc::getMessage('SENDER_INTEGRATION_CRM_CONNECTOR_CLIENT_PRESET_BIRTH'), 'sender_segment_name' => Loc::getMessage('SENDER_INTEGRATION_CRM_CONNECTOR_CLIENT_PRESET_SEGMENT_BIRTH'), 'sender_segment_business_case' => true, 'fields' => array( 'CONTACT_BIRTHDATE_datesel' => 'NEXT_DAY', 'CONTACT_BIRTHDATE_days' => '5', 'CONTACT_BIRTHDATE_allow_year' => '0', 'CLIENT_TYPE' => \CCrmOwnerType::ContactName ) ), 'crm_client_aft_deal_clo' => array( 'name' => Loc::getMessage('SENDER_INTEGRATION_CRM_CONNECTOR_CLIENT_PRESET_AFTER_CLOSE_DEAL'), 'sender_segment_name' => Loc::getMessage('SENDER_INTEGRATION_CRM_CONNECTOR_CLIENT_PRESET_SEGMENT_AFTER_CLOSE_DEAL'), 'sender_segment_business_case' => true, 'fields' => array( 'DEAL_CLOSEDATE_datesel' => 'PREV_DAY', 'DEAL_CLOSEDATE_days' => "30", 'DEAL_CLOSEDATE_allow_year' => '1', ) ), ); foreach (Holiday::getList() as $holiday) { $code = $holiday->getCode(); $name = $holiday->getName( Loc::getMessage('SENDER_INTEGRATION_CRM_CONNECTOR_CLIENT_PRESET_HOLIDAY'), '%holiday_name%' ); $list["crm_client_$code"] = [ 'name' => $name, 'sender_segment_name' => $name, 'sender_segment_business_case' => true, 'fields' => [ 'DEAL_DATE_CREATE_datesel' => 'RANGE', 'DEAL_DATE_CREATE_from' => $holiday->getDateFrom()->toString(), 'DEAL_DATE_CREATE_to' => $holiday->getDateTo()->toString(), 'DEAL_DATE_CREATE_allow_year' => '0', ] ]; } return $list; } /** * Return true if support view of result. * * @return bool */ public function isResultViewable() { return true; } protected function onInitResultView() { $this->getResultView() ->setCallback( ResultView::ColumnModifier, function () { Asset::getInstance()->addJs('/bitrix/js/crm/common.js'); } ) ->setCallback( ResultView::Draw, function (array &$row) { (new Helper())->onResultViewDraw($row); } ); } protected function getProductSkuIds($productIds) { if (!Loader::includeModule("catalog")) return []; return array_reduce( \CCatalogSKU::getOffersList($productIds), function($ids, $items) { $ids = array_merge( $ids, array_map( function($item) { return $item['ID']; }, $items) ); return $ids; }, []); } public function getUiFilterId() { $code = str_replace('_', '', $this->getCode()); return $this->getId() . '_--filter--'.$code.'--'; } /** * Get fields for statistic * @return array */ public function getStatFields() { return ['CLIENT_PRODUCT_ID', 'CLIENT_NO_PURCHASES_DATE']; } }