Блог Горошко Андрея Bitrix24,PHP Конвертируемые элементы: Подробное руководство

Конвертируемые элементы: Подробное руководство

Оптимизация производительности и безопасности — залог успешного проекта на 1С-Битрикс. Данный материал посвящен практическому применению «Конвертируемые элементы: Подробное руководство». Мы подготовили подробный разбор принципов работы и развернутые примеры интеграции.

Конвертация — это превращение одного элемента CRM в другие элементы CRM.

Элемент на котором выполняется конвертация мы будем называть конвертируемым элементом, а элементы получившиеся в результате конвертации — результат конвертации. Существует альтернативное название для конвертации — «создание на основании», в рамках статьи мы будем предполагать что это синонимы.

Конвертируемые элементы

На момент написания статьи конвертируемыми элементами может выступать только Лид, Сделка и Предложение, причем существуют различные модификаторы конвертации которые влияют на доступный набор результатов.

В системе зарегистрировано 3 конвертационных модификатора:

  • Ограничение по сущностям
  • Только для лида: специализированный модификатор на основании типа (обычный и повторный).
  • Генерируемый на основании ролевой карты

Модификатор ограничения по сущностям является общим модификатором который указывает на основании конвертируемого элемента какие результаты конвертации могут быть получены.

  • На основании лида можно создать: Контакт, Компанию, Сделку.
  • На основании Сделки: Счет и Предложение.
  • На основании Предложения: Счет и Сделку.

Специализированный модификатор проверяет тип лида и в случае если конвертируемый лид является повторным то на его основании можно создать только сделку.

Модификатор генерируемый на основании ролевой карты собирает максимальные права данного пользователя на создание сущностей и разрешает конвертацию только в те сущности на которые у текущего пользователя есть права добавления. Так, например, если у пользователя нет прав на создание сделки, то Лид нельзя будет конвертировать в Сделку, но будет возможность конвертировать в Контакт / Компанию и их вариации.

Если смотреть в суть вещей, то и процесс создания одного элемента на основании другого и процесс создания подобных связей без непосредственного создания новых сущностей является конвертацией и чтобы различать их в рамках статьи мы будем рассматривать как 2 независимых процесса:

  • Конвертация — как создание результатов на основании конвертируемого элемента
  • Псевдоконвертация — как создание связей для уже существующих элементов.

Непосредственные классы отвечающие за работу конвертации располагаются в пространстве имен \Bitrix\Crm\Conversion. В дальнейшем мы будем предполагать что это пространство имен и классы из него подключены в use-разделе.

Конвертационные схемы

Теперь когда мы рассмотрели основные моменты, мы можем перейти к рассмотрению конвертационных схем — технических описания как именно нужно конвертировать конвертируемый элемент в результаты.

Конвертационные схемы хранятся в таблице b_crm_conv_map (\Bitrix\Crm\Conversion\Entity\EntityConversionMapTable), однако работать напрямую с таблицей не рекомендуется.

Конвертационная схема состоит из следующих полей (описание таблицы):

ПолеТипОписаниеПримечание
SRC_TYPE_IDint(1) / tinyint(1) unsignedИдентификатор типа конвертируемого элементасм. \CCrmOwnerType
DST_TYPE_IDint(1) / tinyint(1) unsignedИдентификатор типа результата конвертациисм. \CCrmOwnerType
LAST_UPDATEDdatetimeДата последнего обновления конвертационной схемы
DATAlongtextСериализованная конвертационная карта
RELATION_TYPEvarchar(20)Тип конвертацииПо-умолчанию CONVERSION
IS_CHILDREN_LIST_ENABLEDchar(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, так как результат будет одинаковый.

При создании конвертационных схем битрикс использует автоматический механизм, который состоит из двух частей:
1. Строго определенной стандартной частью
2. Работой с пользовательскими полями

Таким образом для стандартных полей конвертируемой сущности у битрикса есть строго определенная часть которая указывает в какие именно поля результата необходимо переносить значения.

Для работы с пользовательскими полями битрикс использует механизм синхронизации полей, когда имеющиеся пользовательские поля в лиде будут созданы во всех результатах конвертации. Например, если работе с 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 идентификатор лида.

💡 Экспертное мнение и рекомендации

Практические рекомендации:

  • При написании кастомных компонентов для «Конвертируемые элементы: Подробное руководство» всегда разделяйте бизнес-логику и представление (шаблон).
  • Используйте отладку SQL-запросов через конструкцию $wpdb->last_query или стандартный трекер Битрикса, чтобы контролировать нагрузку.

Похожая задача в бизнесе?

Помогу автоматизировать процессы и внедрить ИИ

Меня зовут Андрей Горошко. Я Full-stack разработчик и эксперт по 1С-Битрикс. Настраиваю CRM Битрикс24, разрабатываю защищенные API и создаю умных ИИ-агентов для автоматизации рутины.

Related Post

ИконкаИконка

Каждый PHP-разработчик, работающий с экосистемой Bitrix Framework, должен глубоко понимать работу её ключевых компонентов. В этой статье мы проведем подробный аудит темы «Иконка», проанализируем лучшие практики и покажем, как правильно

Как использовать метод SDK access.name в Битрикс24Как использовать метод SDK access.name в Битрикс24

При разработке и поддержке проектов на платформе 1С-Битрикс критически важно использовать современные стандарты D7 API. В этом руководстве мы детально изучим тему «Как использовать метод SDK access.name в Битрикс24», разберем

Получить список заказов из источников sale.tradeBinding.listПолучить список заказов из источников sale.tradeBinding.list

Эффективная интеграция и кастомизация функционала в Битрикс24 часто требует работы на уровне API. Сегодня мы подробно рассмотрим «Получить список заказов из источников sale.tradeBinding.list». Вы узнаете экспертные методики работы с sale.tradeBinding.list