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

CRM

Фабрики

Рабочая справка по фабрикам CRM в коробочном Bitrix24: получение фабрики, getItem, getItems, createItem, операции и настройки операций.

Фабрика — удобная точка входа для работы с CRM-сущностью через PHP. Через неё можно получать элементы, создавать новые, изменять существующие и запускать операции CRM.

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

Фабрики относятся к универсальному API CRM. Один и тот же подход подходит для сделок, лидов, контактов, компаний и смарт-процессов.

Что такое фабрика

Фабрика знает, как работать с конкретным типом CRM-сущности. Например, фабрика сделок работает со сделками, фабрика компаний — с компаниями, а фабрика смарт-процесса — с элементами этого смарт-процесса.

Через фабрику обычно делают такие операции:

  • получить элемент по ID;
  • получить список элементов по фильтру;
  • создать объект нового элемента;
  • получить операцию добавления, изменения или удаления;
  • получить описание полей, стадий и настроек типа.

Типы CRM-сущностей

В getFactory() передаётся entityTypeId. Для стандартных сущностей лучше использовать константы, а для смарт-процесса — его числовой ID.

Сущность Константа Числовое значение
Лид CCrmOwnerType::Lead 1
Сделка CCrmOwnerType::Deal 2
Контакт CCrmOwnerType::Contact 3
Компания CCrmOwnerType::Company 4
Смарт-процесс Нет общей константы Например, 1044

Получить фабрику

Фабрика получается через контейнер сервисов. Если фабрика не найдена, метод вернёт null, поэтому это лучше проверять сразу.

<?php

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

const CRM_ENTITY_TYPE_ID = \CCrmOwnerType::Deal;

Loader::includeModule('crm');

/**
 * Получает фабрику CRM-сущности.
 */
function fetchCrmFactory(int $entity_type_id)
{
    $container = Service\Container::getInstance();

    return $container->getFactory($entity_type_id);
}

$factory = fetchCrmFactory(CRM_ENTITY_TYPE_ID);

if ($factory === null) {
    echo 'Фабрика не найдена';
    return;
}

echo $factory->getEntityDescription();

Получение данных

Через фабрику можно получить один элемент или список элементов с фильтром, сортировкой и ограничением.

Получить элемент по ID

getItem() возвращает объект элемента CRM. Если элемент не найден, будет null.

<?php

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

const CRM_ENTITY_TYPE_ID = \CCrmOwnerType::Deal;

Loader::includeModule('crm');

/**
 * Получает элемент CRM по ID.
 */
function fetchCrmItem(int $entity_type_id, int $item_id)
{
    $factory = Service\Container::getInstance()->getFactory($entity_type_id);

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

    return $factory->getItem($item_id);
}

$item = fetchCrmItem(CRM_ENTITY_TYPE_ID, $item_id);

if ($item === null) {
    echo 'Элемент не найден';
    return;
}

print_r($item->toArray());

Получить список элементов

В getItems() используются привычные параметры: filter, select, order, limit, offset.

<?php

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

const CRM_ENTITY_TYPE_ID = \CCrmOwnerType::Deal;
const ITEM_LIMIT = 100;

Loader::includeModule('crm');

/**
 * Получает список CRM-элементов.
 */
function fetchCrmItems(int $entity_type_id, array $filter): array
{
    $factory = Service\Container::getInstance()->getFactory($entity_type_id);

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

    return $factory->getItems([
        'select' => [
            'ID',
            'TITLE',
            'STAGE_ID',
            'ASSIGNED_BY_ID',
        ],
        'filter' => $filter,
        'order' => [
            'ID' => 'ASC',
        ],
        'limit' => ITEM_LIMIT,
    ]);
}

$items = fetchCrmItems(
    CRM_ENTITY_TYPE_ID,
    [
        '>ID' => 15,
    ]
);

foreach ($items as $item) {
    print_r($item->toArray());
}

Для массовой обработки лучше идти порциями: например, фильтром >ID и сортировкой по ID.

Получить значения полей

Элемент можно превратить в массив через toArray() или getData(). Отдельное поле можно получить через get().

$item_array = $item->toArray();

$item_data = $item->getData();

$title = $item->get('TITLE');

$stage_id = $item->get('STAGE_ID');

$custom_value = $item->get('UF_CRM_1234567890');

Для некоторых стандартных полей есть именованные методы, например getTitle(), setTitle(), getStageId(), setStageId(). Но универсальный вариант через get() и set() проще переносится между типами сущностей.

Изменение данных

Создать или изменить объект элемента недостаточно. Чтобы изменения попали в CRM, нужно запустить операцию или сохранить элемент напрямую.

Создать элемент

createItem() создаёт объект элемента в памяти. Для записи в CRM запускаем операцию добавления.

<?php

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

const CRM_ENTITY_TYPE_ID = \CCrmOwnerType::Deal;

Loader::includeModule('crm');

/**
 * Добавляет CRM-элемент.
 */
function addCrmItem(int $entity_type_id, array $item_fields): array
{
    $factory = Service\Container::getInstance()->getFactory($entity_type_id);

    if ($factory === null) {
        return [
            'is_success' => false,
            'item_id' => 0,
            'error_messages' => ['Фабрика не найдена'],
        ];
    }

    $item = $factory->createItem($item_fields);

    $operation = $factory->getAddOperation($item);
    $operation_result = $operation->launch();

    return [
        'is_success' => $operation_result->isSuccess(),
        'item_id' => (int) $item->getId(),
        'error_messages' => $operation_result->getErrorMessages(),
    ];
}

$item_fields = [
    'TITLE' => 'Новая сделка',
    'ASSIGNED_BY_ID' => 1,
];

$add_result = addCrmItem(CRM_ENTITY_TYPE_ID, $item_fields);

print_r($add_result);

Изменить элемент

Сначала получаем элемент, меняем поля через set(), затем запускаем операцию обновления.

<?php

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

const CRM_ENTITY_TYPE_ID = \CCrmOwnerType::Deal;

Loader::includeModule('crm');

/**
 * Изменяет поля CRM-элемента.
 */
function updateCrmItem(int $entity_type_id, int $item_id, array $item_fields): array
{
    $factory = Service\Container::getInstance()->getFactory($entity_type_id);

    if ($factory === null) {
        return [
            'is_success' => false,
            'error_messages' => ['Фабрика не найдена'],
        ];
    }

    $item = $factory->getItem($item_id);

    if ($item === null) {
        return [
            'is_success' => false,
            'error_messages' => ['Элемент не найден'],
        ];
    }

    foreach ($item_fields as $field_id => $field_value) {
        $item->set($field_id, $field_value);
    }

    $operation = $factory->getUpdateOperation($item);
    $operation_result = $operation->launch();

    return [
        'is_success' => $operation_result->isSuccess(),
        'error_messages' => $operation_result->getErrorMessages(),
    ];
}

$update_result = updateCrmItem(
    CRM_ENTITY_TYPE_ID,
    $item_id,
    [
        'TITLE' => 'Новое название',
        'STAGE_ID' => 'NEW',
    ]
);

print_r($update_result);

Удалить элемент

Для удаления получаем элемент и запускаем операцию удаления.

<?php

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

const CRM_ENTITY_TYPE_ID = \CCrmOwnerType::Deal;

Loader::includeModule('crm');

/**
 * Удаляет CRM-элемент.
 */
function deleteCrmItem(int $entity_type_id, int $item_id): array
{
    $factory = Service\Container::getInstance()->getFactory($entity_type_id);

    if ($factory === null) {
        return [
            'is_success' => false,
            'error_messages' => ['Фабрика не найдена'],
        ];
    }

    $item = $factory->getItem($item_id);

    if ($item === null) {
        return [
            'is_success' => false,
            'error_messages' => ['Элемент не найден'],
        ];
    }

    $operation = $factory->getDeleteOperation($item);
    $operation_result = $operation->launch();

    return [
        'is_success' => $operation_result->isSuccess(),
        'error_messages' => $operation_result->getErrorMessages(),
    ];
}

$delete_result = deleteCrmItem(CRM_ENTITY_TYPE_ID, $item_id);

print_r($delete_result);

Операции

Операция — это не просто сохранение в таблицу. Это запуск CRM-логики вокруг добавления, изменения или удаления элемента.

Зачем нужны операции

Если использовать прямой $item->save(), можно обойти часть CRM-логики. Если нужны проверки, история, таймлайн, роботы и бизнес-процессы, лучше использовать операции фабрики.

Метод Для чего нужен
getAddOperation() Добавление элемента.
getUpdateOperation() Изменение элемента.
getDeleteOperation() Удаление элемента.
getCopyOperation() Копирование элемента.
getConversionOperation() Конвертация, если она поддерживается конкретной сущностью.

Настройки операций

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

Что управляет Включить Выключить
Проверка прав enableCheckAccess() disableCheckAccess()
Проверка полей enableCheckFields() disableCheckFields()
Обязательные пользовательские поля enableCheckRequiredUserFields() disableCheckRequiredUserFields()
Проверка запущенных БП enableCheckWorkflows() disableCheckWorkflows()
Бизнес-логика полей enableFieldProcession() disableFieldProcession()
История изменений enableSaveToHistory() disableSaveToHistory()
Действия до сохранения enableBeforeSaveActions() disableBeforeSaveActions()
Действия после сохранения enableAfterSaveActions() disableAfterSaveActions()
Бизнес-процессы enableBizProc() disableBizProc()
Роботы enableAutomation() disableAutomation()
$operation = $factory->getUpdateOperation($item);

$operation
    ->disableCheckWorkflows()
    ->disableCheckRequiredUserFields()
    ->disableBizProc()
    ->disableAutomation();

$operation_result = $operation->launch();

if (!$operation_result->isSuccess()) {
    print_r($operation_result->getErrorMessages());
}

Контекст пользователя

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

<?php

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

const CRM_ENTITY_TYPE_ID = \CCrmOwnerType::Deal;

Loader::includeModule('crm');

/**
 * Создаёт сделку от имени пользователя.
 */
function addDealWithUserContext(array $deal_fields, int $user_id): array
{
    $factory = Service\Container::getInstance()->getFactory(CRM_ENTITY_TYPE_ID);

    if ($factory === null) {
        return [
            'is_success' => false,
            'deal_id' => 0,
            'error_messages' => ['Фабрика сделок не найдена'],
        ];
    }

    $context = new Service\Context();
    $context->setUserId($user_id);

    $item = $factory->createItem($deal_fields);

    $operation = $factory->getAddOperation($item, $context);
    $operation_result = $operation->launch();

    return [
        'is_success' => $operation_result->isSuccess(),
        'deal_id' => (int) $item->getId(),
        'error_messages' => $operation_result->getErrorMessages(),
    ];
}

$add_result = addDealWithUserContext(
    [
        'TITLE' => 'Сделка из скрипта',
        'ASSIGNED_BY_ID' => $user_id,
    ],
    $user_id
);

print_r($add_result);

Источники