← Назад к справке

CRM

Конвертация лидов

Рабочая справка по конвертации лидов в коробочном Bitrix24 через PHP: сделка, контакт, компания, Automation Converter и LeadConversionWizard.

Конвертация лида — это создание сделки, контакта и/или компании на основании лида. Это не обычное изменение поля STATUS_ID, а отдельный CRM-сценарий со своими проверками, связями и результатами.

Общее понимание

Конвертацию лучше рассматривать отдельно от обычного обновления лида. При конвертации CRM создаёт новые сущности и связывает их с исходным лидом.

Что создаётся из лида

Из лида можно создать контакт, компанию и сделку. Набор доступных результатов зависит от типа лида, прав пользователя и настроек CRM.

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

Обычный и повторный лид

Для обычного лида можно создавать контакт, компанию и сделку. Для повторного лида доступный набор результатов может быть ограничен: на практике он часто конвертируется только в сделку, потому что клиент уже есть в CRM.

Если код работает не так, как ожидалось, сначала стоит проверить: это обычный лид или повторный, какие права у пользователя и какие обязательные поля включены в CRM.

Простая конвертация

Самый короткий вариант — использовать \Bitrix\Crm\Automation\Converter\Factory. Он удобен для типовых сценариев.

Лид в сделку и контакт

Пример создаёт сделку в указанной воронке и контакт на основании лида. После выполнения результат регистрируется через registerConversionResult().

<?php

use Bitrix\Main\Loader;
use Bitrix\Crm\Automation;

const LEAD_ENTITY_TYPE_ID = \CCrmOwnerType::Lead;
const DEAL_ENTITY_TYPE_ID = \CCrmOwnerType::Deal;
const CONTACT_ENTITY_TYPE_ID = \CCrmOwnerType::Contact;

Loader::includeModule('crm');

/**
 * Конвертирует лид в сделку и контакт.
 */
function convertLeadToDealAndContact(int $lead_id, int $user_id, int $deal_category_id): array
{
    try {
        $converter = Automation\Converter\Factory::create(
            LEAD_ENTITY_TYPE_ID,
            $lead_id
        );

        $converter->enableActivityCompletion(true);

        $converter->setTargetItem(
            DEAL_ENTITY_TYPE_ID,
            [
                'categoryId' => $deal_category_id,
            ]
        );

        $converter->setTargetItem(
            CONTACT_ENTITY_TYPE_ID,
            []
        );

        $conversion_result = $converter->execute([
            'USER_ID' => $user_id,
        ]);

        Automation\Factory::registerConversionResult(
            LEAD_ENTITY_TYPE_ID,
            $lead_id,
            $conversion_result
        );

        return [
            'is_success' => $conversion_result->isSuccess(),
            'error_messages' => $conversion_result->getErrorMessages(),
        ];
    } catch (\Throwable $exception) {
        return [
            'is_success' => false,
            'error_messages' => [$exception->getMessage()],
        ];
    }
}

$conversion_result = convertLeadToDealAndContact(
    $lead_id,
    $user_id,
    $deal_category_id
);

print_r($conversion_result);

Лид в сделку, контакт и компанию

Если нужно создать сразу три сущности, добавляем компанию как ещё один целевой элемент.

<?php

use Bitrix\Main\Loader;
use Bitrix\Crm\Automation;

const LEAD_ENTITY_TYPE_ID = \CCrmOwnerType::Lead;
const DEAL_ENTITY_TYPE_ID = \CCrmOwnerType::Deal;
const CONTACT_ENTITY_TYPE_ID = \CCrmOwnerType::Contact;
const COMPANY_ENTITY_TYPE_ID = \CCrmOwnerType::Company;

Loader::includeModule('crm');

/**
 * Конвертирует лид в сделку, контакт и компанию.
 */
function convertLeadToDealContactCompany(int $lead_id, int $user_id, int $deal_category_id): array
{
    try {
        $converter = Automation\Converter\Factory::create(
            LEAD_ENTITY_TYPE_ID,
            $lead_id
        );

        $converter->enableActivityCompletion(true);

        $converter->setTargetItem(
            DEAL_ENTITY_TYPE_ID,
            [
                'categoryId' => $deal_category_id,
            ]
        );

        $converter->setTargetItem(
            CONTACT_ENTITY_TYPE_ID,
            []
        );

        $converter->setTargetItem(
            COMPANY_ENTITY_TYPE_ID,
            []
        );

        $conversion_result = $converter->execute([
            'USER_ID' => $user_id,
        ]);

        Automation\Factory::registerConversionResult(
            LEAD_ENTITY_TYPE_ID,
            $lead_id,
            $conversion_result
        );

        return [
            'is_success' => $conversion_result->isSuccess(),
            'error_messages' => $conversion_result->getErrorMessages(),
        ];
    } catch (\Throwable $exception) {
        return [
            'is_success' => false,
            'error_messages' => [$exception->getMessage()],
        ];
    }
}

$conversion_result = convertLeadToDealContactCompany(
    $lead_id,
    $user_id,
    $deal_category_id
);

print_r($conversion_result);

Мастер конвертации

Более подробный вариант — собрать конфигурацию конвертации и запустить LeadConversionWizard.

LeadConversionWizard

Этот вариант длиннее, но позволяет явно управлять целевыми сущностями, синхронизацией пользовательских полей, проверкой бизнес-процессов и завершением дел.

<?php

use Bitrix\Main\Loader;
use Bitrix\Crm\Conversion;
use Bitrix\Crm\Synchronization;

const LEAD_ENTITY_TYPE_ID = \CCrmOwnerType::Lead;
const DEAL_ENTITY_TYPE_ID = \CCrmOwnerType::Deal;
const CONTACT_ENTITY_TYPE_ID = \CCrmOwnerType::Contact;

Loader::includeModule('crm');

/**
 * Активирует результат конвертации.
 */
function activateConversionItem($conversion_config, int $entity_type_id, array $init_data = []): void
{
    $conversion_item = $conversion_config->getItem($entity_type_id);

    if ($conversion_item === null) {
        return;
    }

    $conversion_item->setActive(true);
    $conversion_item->enableSynchronization(true);

    if (!empty($init_data)) {
        $conversion_item->setInitData($init_data);
    }
}

/**
 * Синхронизирует пользовательские поля для активных результатов конвертации.
 */
function synchronizeLeadConversionUserFields($conversion_config): void
{
    foreach ($conversion_config->getItems() as $conversion_item) {
        $dst_entity_type_id = (int) $conversion_item->getEntityTypeID();

        $should_synchronize = Synchronization\UserFieldSynchronizer::needForSynchronization(
            LEAD_ENTITY_TYPE_ID,
            $dst_entity_type_id
        );

        if (!$should_synchronize) {
            continue;
        }

        if ($conversion_item->isSynchronizationEnabled()) {
            Synchronization\UserFieldSynchronizer::synchronize(
                LEAD_ENTITY_TYPE_ID,
                $dst_entity_type_id
            );
        } else {
            Synchronization\UserFieldSynchronizer::markAsSynchronized(
                LEAD_ENTITY_TYPE_ID,
                $dst_entity_type_id
            );
        }
    }
}

/**
 * Конвертирует лид через LeadConversionWizard.
 */
function convertLeadWithWizard(int $lead_id, int $user_id, int $deal_category_id): array
{
    $context_data = [
        'USER_ID' => $user_id,
    ];

    $conversion_config = new Conversion\LeadConversionConfig();

    activateConversionItem(
        $conversion_config,
        CONTACT_ENTITY_TYPE_ID,
        [
            'defaultName' => 'Новый контакт',
        ]
    );

    activateConversionItem(
        $conversion_config,
        DEAL_ENTITY_TYPE_ID,
        [
            'categoryId' => $deal_category_id,
        ]
    );

    $conversion_wizard = new Conversion\LeadConversionWizard(
        $lead_id,
        $conversion_config
    );

    $conversion_wizard->enableUserFieldCheck(false);
    $conversion_wizard->enableBizProcCheck(false);
    $conversion_wizard->setSkipBizProcAutoStart(true);
    $conversion_wizard->enableActivityCompletion(true);

    synchronizeLeadConversionUserFields($conversion_config);

    $is_success = $conversion_wizard->execute($context_data);

    return [
        'is_success' => $is_success,
        'result_data' => $is_success ? $conversion_wizard->getResultData() : [],
        'error_message' => $is_success ? '' : $conversion_wizard->getErrorText(),
    ];
}

$conversion_result = convertLeadWithWizard(
    $lead_id,
    $user_id,
    $deal_category_id
);

print_r($conversion_result);

Проверить результат

После успешной конвертации через мастер результат можно получить через getResultData(). При ошибке полезнее всего смотреть getErrorText().

$conversion_result = convertLeadWithWizard(
    $lead_id,
    $user_id,
    $deal_category_id
);

if ($conversion_result['is_success']) {
    print_r($conversion_result['result_data']);
} else {
    echo $conversion_result['error_message'];
}

Связи после конвертации

После конвертации созданные сущности должны быть связаны с исходным лидом и друг с другом.

LEAD_ID в созданных сущностях

В сделке, контакте и компании может использоваться поле LEAD_ID. Оно показывает, на основании какого лида была создана сущность.

Заполнять LEAD_ID прямым SQL-запросом не стоит. Если нужно связать уже существующую сущность с лидом, лучше использовать API соответствующей сущности, а не править таблицу напрямую.

Получить созданные сущности

Если после конвертации нужно найти созданные элементы, можно искать по LEAD_ID. Ниже пример для сделок.

<?php

use Bitrix\Main\Loader;
use Bitrix\Crm\Service;

const DEAL_ENTITY_TYPE_ID = \CCrmOwnerType::Deal;

Loader::includeModule('crm');

/**
 * Получает сделки, созданные на основании лида.
 */
function fetchDealsByLeadId(int $lead_id): array
{
    $factory = Service\Container::getInstance()->getFactory(DEAL_ENTITY_TYPE_ID);

    if ($factory === null) {
        return [];
    }

    return $factory->getItems([
        'select' => [
            'ID',
            'TITLE',
            'LEAD_ID',
            'STAGE_ID',
            'CATEGORY_ID',
        ],
        'filter' => [
            '=LEAD_ID' => $lead_id,
        ],
        'order' => [
            'ID' => 'DESC',
        ],
    ]);
}

$deal_items = fetchDealsByLeadId($lead_id);

foreach ($deal_items as $deal_item) {
    print_r($deal_item->toArray());
}

Источники