Конвертация - это превращение одного элемента CRM в другие элементы CRM.
Элемент на котором выполняется конвертация мы будем называть конвертируемым элементом, а элементы получившиеся в результате конвертации - результат конвертации. Существует альтернативное название для конвертации - “создание на основании”, в рамках статьи мы будем предполагать что это синонимы.
Конвертируемые элементы
На момент написания статьи конвертируемыми элементами может выступать только Лид, Сделка и Предложение, причем существуют различные модификаторы конвертации которые влияют на доступный набор результатов.
В системе зарегистрировано 3 конвертационных модификатора:
- Ограничение по сущностям
- Только для лида: специализированный модификатор на основании типа (обычный и повторный).
- Генерируемый на основании ролевой карты
Модификатор ограничения по сущностям является общим модификатором который указывает на основании конвертируемого элемента какие результаты конвертации могут быть получены.
- На основании лида можно создать: Контакт, Компанию, Сделку.
- На основании Сделки: Счет и Предложение.
- На основании Предложения: Счет и Сделку.
Специализированный модификатор проверяет тип лида и в случае если конвертируемый лид является повторным то на его основании можно создать только сделку.
Модификатор генерируемый на основании ролевой карты собирает максимальные права данного пользователя на создание сущностей и разрешает конвертацию только в те сущности на которые у текущего пользователя есть права добавления. Так, например, если у пользователя нет прав на создание сделки, то Лид нельзя будет конвертировать в Сделку, но будет возможность конвертировать в Контакт / Компанию и их вариации.
Если смотреть в суть вещей, то и процесс создания одного элемента на основании другого и процесс создания подобных связей без непосредственного создания новых сущностей является конвертацией и чтобы различать их в рамках статьи мы будем рассматривать как 2 независимых процесса:
- Конвертация - как создание результатов на основании конвертируемого элемента
- Псевдоконвертация - как создание связей для уже существующих элементов.
Непосредственные классы отвечающие за работу конвертации располагаются в пространстве имен \Bitrix\Crm\Conversion
. В дальнейшем мы будем предполагать что это пространство имен и классы из него подключены в use
-разделе.
Конвертационные схемы
Теперь когда мы рассмотрели основные моменты, мы можем перейти к рассмотрению конвертационных схем - технических описания как именно нужно конвертировать конвертируемый элемент в результаты.
Конвертационные схемы хранятся в таблице b_crm_conv_map
(\Bitrix\Crm\Conversion\Entity\EntityConversionMapTable
), однако работать напрямую с таблицей не рекомендуется.
Конвертационная схема состоит из следующих полей (описание таблицы):
Поле | Тип | Описание | Примечание |
---|---|---|---|
SRC_TYPE_ID | int(1) / tinyint(1) unsigned | Идентификатор типа конвертируемого элемента | см. \CCrmOwnerType |
DST_TYPE_ID | int(1) / tinyint(1) unsigned | Идентификатор типа результата конвертации | см. \CCrmOwnerType |
LAST_UPDATED | datetime | Дата последнего обновления конвертационной схемы | |
DATA | longtext | Сериализованная конвертационная карта | |
RELATION_TYPE | varchar(20) | Тип конвертации | По-умолчанию CONVERSION |
IS_CHILDREN_LIST_ENABLED | char(1) | Доступность в списке связей | по-умолчанию Y |
Отдельно стоит остановиться на нововведениях: механизм Смарт-процессов позволяет привязывать созданный Смарт-процесс к элементам. Для реализации этой возможности были добавлены столбцы RELATION_TYPE
и IS_CHILDREN_LIST_ENABLED
.
RELATION_TYPE
- тип связи конвертационной схемы. В настоящий момент допустимы только 2 значения: \Bitrix\Crm\Relation\RelationType::CONVERSION
(конвертация) и \Bitrix\Crm\Relation\RelationType::BINDING
(связь).
IS_CHILDREN_LIST_ENABLED
- флаг обозначающий необходимость добавить список со связанными элементами в карточку конвертируемой сущности.
Отдельно стоит отметить, что при типе конвертационной схеме связь, заполнение сериализованной конвертационной карты не требуется.
Сама сериализованная конвертационная карта состоит из полей:
-
srcEntityTypeID
- индентификатор типа конвертируемого элемента (\CCrmOwnerType) -
dstEntityTypeID
- идентификатор типа результата конвертации -
time
- дата генерации конвертационной схемы -
items
- набор инструкций по конвертации поля конвертируемого элемента
Не трудно заметить что поля
srcEntityTypeID
,dstEntityTypeID
иtime
копирую поведение полей базы данныхSRC_TYPE_ID
,DST_TYPE_ID
иLAST_UPDATED
соответственно. Это не ошибка, а необходимость для быстрого извлечения и удобства при разработке в публичной части.
Каждая инструкция по конвертации поля состоит из следующего набора полей:
-
srcField
- код поля в конвертируемом элементе -
dstField
- код поля в элементе результата конвертации -
altSrcFields
- набор кодов полей, откуда будет произведена попытка получения значений, в случае если вsrcField
не будет значения. -
isLocked
- флаг указывающий на то, что изменение элемента в публичной части при вызове формы невозможен (поле будет заблокировано) -
isRequired
- флаг указывающий на то, что заполнение этого поля обязательно при конвертации.
Не стоит обольщаться наличием флагов
isLocked
иisRequired
их значения в конверсионной карте никак не обрабатываются, поэтому не имеет значения установите вы параметры в true или false, так как результат будет одинаковый.
При создании конвертационных схем битрикс использует автоматический механизм, который состоит из двух частей:
- Строго определенной стандартной частью
- Работой с пользовательскими полями
Таким образом для стандартных полей конвертируемой сущности у битрикса есть строго определенная часть которая указывает в какие именно поля результата необходимо переносить значения.
Для работы с пользовательскими полями битрикс использует механизм синхронизации полей, когда имеющиеся пользовательские поля в лиде будут созданы во всех результатах конвертации. Например, если работе с CRM в Лиде вы создали дополнительное поле “Тема обращения”, то данное поле при конвертации в Сделку+Контакт будет создано И в сделке И в контакте, хотя семантически оно может быть там совершенно не нужно. Перенос полей происходит по принципу 1к1, т.е. если поле с таким кодом существует и в лиде и в сделке, то в сделке это поле не будет создано, а будет проставлена связь между полями.
До версии битрикса 20 включительно подобной схеме были подвержены все пользовательские поля, однако после обрабатываются только поля у которых в коде присутствует префикс
UF_CRM_
.
Простой способ конвертации
Наиболее простым способом конвертации является использование средств автоматизации предоставляемых в пространстве имен \Bitrix\Crm\Automation\Converter
.
Описанный класс настолько прост, что не имеет смысла описывать его возможности технически. Рассмотрим пример кода который должен на основании лида (ID:1) от лица пользователя (ID:1) конвертировать в сделку определенного направления (ID:1) и контакт.
use \Bitrix\Crm\Automation;
/**
* Income lead id
* @var integer
*/
$leadId = 1;
/**
* User id who start convertation
* @var integer
*/
$convertUserId = 1;
/**
* Deal category id
* @var integer
*/
$dealCategoryId = 1;
/**
* True if need to complete all activities after convertation process
* @var boolean
*/
$completeActivityAfterConveration = true;
try
{
$converter = Automation\Converter\Factory::create(
\CCrmOwnerType::Lead,
$leadId
);
$converter->enableActivityCompletion($completeActivityAfterConveration);
$converter->setTargetItem(
\CCrmOwnerType::Deal,
['categoryId' => (int)$dealCategoryId]
);
$converter->setTargetItem(
\CCrmOwnerType::Contact,
[]
);
$conversionResult = $converter->execute([
'USER_ID' => $convertUserId
]);
/**
* Register convertation relations
*/
Automation\Factory::registerConversionResult(
\CCrmOwnerType::Lead,
$leadId,
$conversionResult
);
if(!$conversionResult->isSuccess())
{
throw new \Exception(
"Conversion error: "
.implode(', ', $conversionResult->getErrorMessages())
);
}
}
catch (\Throwable $e)
{
var_dump($e);
}
Конвертационный процесс
Технически конвертация сводится к последовательности действий выполняемых для определенной сущности:
- Создание конфигурации (Наследник
EntityConversionConfig
) - Создание мастера (Наследник
EntityConversionWizard
) - Установка необходимых параметров конвертации
- Запуск мастера конвертации
Конвертация лида
Выполним конвертацию ранее описанного примера явно, не используя конструкции предоставляемые автоматизацией crm.
use \Bitrix\Crm\Conversion,
\Bitrix\Crm\Synchronization
;
/**
* Converted lead id
* @var integer
*/
$leadId = 1;
/**
* User id who start convertation
* @var integer
*/
$convertUserId = 1;
/**
* Deal category id
* @var integer
*/
$dealCategoryId = 1;
/**
* Execution context
* @var array
*/
$contextData = [
'USER_ID' => $convertUserId
];
$conversionConfig = new Conversion\LeadConversionConfig();
/**
* Disable user field check to prevent create exceptions
*/
$conversionConfig->enablePermissionCheck(false);
// For contact
$item = $conversionConfig->getItem( \CCrmOwnerType::Contact );
if ($item)
{
// Activate convertation to contact
$item->setActive(true);
// Enable syncronization fields
$item->enableSynchronization(true);
// Setup initial data. Accepted only 'defaultName'
$item->setInitData([
'defaultName' => 'Default contact name',
]);
}
unset($item);
// For deal in category
$item = $conversionConfig->getItem( \CCrmOwnerType::Deal );
if ($item)
{
// Activate convertation to contact
$item->setActive(true);
// Enable syncronization fields
$item->enableSynchronization(true);
// Setup initial data. Accepted only 'categoryId'
$item->setInitData([
'categoryId' => (int) $dealCategoryId,
]);
}
unset($item);
$conversionWizard = new Conversion\LeadConversionWizard(
$leadId,
$conversionConfig
);
/**
* Disable user field synchronization.
*/
$conversionWizard->enableUserFieldCheck(false);
/**
* Disable workflow new entity check.
* If exist workflow with autostart option and parameters
* wizard throws an error
*/
$conversionWizard->enableBizProcCheck(false);
/**
* If crm lead entity exist bizproc with option autostart when update
* need start this workflows?
*/
$conversionWizard->setSkipBizProcAutoStart(true);
/**
* Need to complete all activities after convertation process
*/
$conversionWizard->enableActivityCompletion(true);
/**
* Process user field synchronization to prevent the fields from diverging
*/
$srcEntityTypeId = \CCrmOwnerType::Lead;
foreach ($conversionConfig->getItems() as $item)
{
$dstEntityTypeId = (int)$item->getEntityTypeID();
if( !Synchronization\UserFieldSynchronizer::needForSynchronization(
$srcEntityTypeId,
$dstEntityTypeId
))
{
continue;
}
if ($item->isSynchronizationEnabled())
{
Synchronization\UserFieldSynchronizer::synchronize(
$srcEntityTypeId,
$dstEntityTypeId
);
}
else
{
Synchronization\UserFieldSynchronizer::markAsSynchronized(
$srcEntityTypeId,
$dstEntityTypeId
);
}
}
if ( !$conversionWizard->execute($contextData) )
{
/**
* Caught some error. You can see error text (string)
* with '$conversionWizard->getErrorText()'
*/
}
else
{
/**
* Ok. You can get result data from
* $conversionWizard->getResultData()
*/
}
Конвертационные связи
Помимо выполнения конвертационного процесса существует и псевдоконцвертация, т.е. создание связей без создания элементов. В разных сущностях этот процесс характеризуется своими особенностями.
Поле
LEAD_ID
является универсальным для Сделок, Контактов и Компаний, однако это совершенно не значит что механизм его обработки одинаковый. Не пытайтесь заполнить этот поле в СУБД через SQL запрос! Используйтестарое
api для его заполнения.
Если получилась такая ситуация, что поле LEAD_ID
в какой-либо сущности было заполнено прямым SQL-запросом, то для данного лида необходимо пересчитать статистические данные методом:
use \Bitrix\Crm\Statistics;
Statistics\LeadConversionStatisticsEntry::processBindingsChange($leadID);
Таким образом, для того чтобы проставить связи между существующими Контактом, Компанией или Сделкой с лидом достаточно просто обновить данный соответствующей сущности добавив в поле LEAD_ID
идентификатор лида.