Бизнес-процессы
События бизнес-процессов
Рабочая справка по событиям бизнес-процессов: внешние события workflow, SendExternalEvent и запуск процессов от событий документа.
В бизнес-процессах слово «событие» может означать разные вещи: событие документа, которое запускает процесс, или внешнее событие, которое продолжает уже запущенный workflow.
Общее понимание
Сначала нужно разделить запуск процесса и продолжение уже запущенного процесса.
Какие события бывают
| Тип | Что делает | Пример |
|---|---|---|
| Событие документа | Запускает бизнес-процесс при создании или изменении документа. | Создали сделку — стартовал шаблон БП. |
| Внешнее событие workflow | Продолжает уже запущенный процесс, который ждёт событие. | Процесс ждёт ответ внешней системы. |
| Событие CRM | PHP-обработчик реагирует на изменение CRM-сущности. | OnAfterCrmDealUpdate запускает нужный БП. |
Внешнее событие workflow
Если процесс уже запущен и остановлен на ожидании внешнего события, его можно
продолжить через CBPDocument::SendExternalEvent().
Для этого нужно знать workflow_id запущенного процесса и имя события,
которое ждёт действие внутри шаблона.
Отправка события
Внешнее событие отправляется в конкретный workflow.
SendExternalEvent
\Bitrix\Main\Loader::includeModule('bizproc');
/**
* Отправляет внешнее событие в бизнес-процесс.
*/
function sendWorkflowExternalEvent(
string $workflow_id,
string $event_name,
array $event_parameters = []
): array {
$error_messages = [];
\CBPDocument::SendExternalEvent(
$workflow_id,
$event_name,
$event_parameters,
$error_messages
);
return [
'is_success' => empty($error_messages),
'error_messages' => $error_messages,
];
}
$send_result = sendWorkflowExternalEvent(
$workflow_id,
'ExternalSystemAnswer',
[
'status' => 'success',
'external_id' => 123,
]
);
print_r($send_result); Параметры события
Параметры внешнего события зависят от того, как настроено действие ожидания события в шаблоне. Для диагностики лучше сначала передавать простой массив и писать результат в журнал процесса.
$event_parameters = [
'result_text' => 'Согласовано внешней системой',
'result_code' => 'APPROVED',
'external_user_id' => 15,
];
$send_result = sendWorkflowExternalEvent(
$workflow_id,
'ExternalApproveEvent',
$event_parameters
);
if (!$send_result['is_success']) {
AddMessage2Log(
[
'message' => 'Ошибка отправки внешнего события',
'result' => $send_result,
],
'bizproc_event'
);
} События документа
Если нужно запустить процесс при событии CRM, проще связать обработчик CRM-события и
CBPDocument::StartWorkflow().
Запуск при изменении CRM
Пример регистрирует обработчик изменения сделки и запускает нужный шаблон бизнес-процесса.
<?php
use Bitrix\Main\EventManager;
const WORKFLOW_TEMPLATE_ID = 123;
/**
* Регистрирует обработчик изменения сделки.
*/
function registerDealUpdateWorkflowStartHandler(): void
{
EventManager::getInstance()->addEventHandlerCompatible(
'crm',
'OnAfterCrmDealUpdate',
'handleDealUpdateWorkflowStart'
);
}
/**
* Запускает бизнес-процесс после изменения сделки.
*/
function handleDealUpdateWorkflowStart(array &$deal_fields): void
{
$deal_id = isset($deal_fields['ID']) ? (int) $deal_fields['ID'] : 0;
if ($deal_id <= 0) {
return;
}
\Bitrix\Main\Loader::includeModule('bizproc');
$error_messages = [];
\CBPDocument::StartWorkflow(
WORKFLOW_TEMPLATE_ID,
[
'crm',
'CCrmDocumentDeal',
'DEAL_' . $deal_id,
],
[],
$error_messages
);
if (!empty($error_messages)) {
AddMessage2Log(
[
'message' => 'Ошибка запуска БП из события сделки',
'deal_id' => $deal_id,
'errors' => $error_messages,
],
'bizproc_event'
);
}
}
registerDealUpdateWorkflowStartHandler(); Связь с запуском БП
Если обработчик события сам меняет ту же CRM-сущность, нужно добавить защиту от повторного запуска, иначе можно получить цикл: событие → запуск кода → изменение сущности → событие снова.
/**
* Обрабатывает изменение сделки с защитой от повторного запуска.
*/
function handleSafeDealUpdateWorkflowStart(array &$deal_fields): void
{
static $is_handler_running = false;
if ($is_handler_running) {
return;
}
$is_handler_running = true;
try {
handleDealUpdateWorkflowStart($deal_fields);
} finally {
$is_handler_running = false;
}
}