Перейти к содержимому

Запуск бизнес-процесса из кода - шаблон, документ, повторы

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

Решение

Находим шаблон по типу документа:

\Bitrix\Main\Loader::includeModule('bizproc');
$documentType = ['lists', 'BizprocDocument', 'iblock_' . $iblockId];
$res = CBPWorkflowTemplateLoader::GetList([], ['DOCUMENT_TYPE' => $documentType],
false, false, ['ID', 'NAME']);
while ($tpl = $res->GetNext()) { printf("%s %s\n", $tpl['ID'], $tpl['NAME']); }

Шаблоны привязаны к типу документа, а не к сущности вообще. Тип собирается из модуля, класса документа и сущности, и шаблон от другого инфоблока к вашему документу не подойдёт.

Собираем идентификатор документа:

$documentId = ['lists', 'BizprocDocument', $elementId];
// для элементов инфоблока класс документа другой:
// ['iblock', 'CIBlockDocument', $elementId]
// перепутанный класс даёт «шаблон не найден» при существующем шаблоне

Документ адресуется тройкой значений, а не одним номером. Одна и та же запись в разных модулях выглядит по-разному, и именно это чаще всего мешает запуску из кода.

Запускаем процесс с параметрами:

$errors = [];
$workflowId = CBPDocument::StartWorkflow($templateId, $documentId,
['Comment' => 'запуск из обмена'], $errors);
if ($errors) {
AddMessage2Log(print_r($errors, true), 'vendor.shop'); // молчать здесь нельзя
}

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

Проверяем, не идёт ли процесс уже:

$states = CBPStateService::GetDocumentStates($documentId);
if ($states) {
return; // процесс по этому документу уже запущен, второй не нужен
}
// в агенте это обязательная проверка: он приходит каждые несколько минут
// служба состояний возвращает только запущенные экземпляры процессов
// у CBPDocument::GetDocumentStates к ним подмешаны доступные шаблоны

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

Запуск из агента идёт от имени системы, а не сотрудника. Всё, что процесс делает с правами, стоит проверить именно в таком запуске: под администратором работает и то, что у менеджера не работает.

Тяжёлую работу в процессе, запущенном по расписанию, разбивают на порции. Агент с многочасовым процессом внутри однажды встречает следующий свой запуск и начинает всё заново.

Запуск из кода не отменяет настроек автозапуска шаблона. Шаблон, запускающийся при изменении документа, сработает и от вашей правки, поэтому оба пути проверяют вместе.

Типичные проблемы

Запуск возвращает ошибку про отсутствующий шаблон.

Класс документа в идентификаторе не тот, что у шаблона. Списки и инфоблоки используют для этого совершенно разные классы своих документов.

Процесс не запустился, а код отработал молча.

Массив ошибок запуска нигде в коде не проверяется и просто молча теряется. Его читают сразу после вызова и пишут в журнал.

На одном документе висит десяток процессов.

Агент запускает процесс заново при каждом своём очередном проходе по этим документам. Перед запуском проверяют уже идущие процессы документа.

В агенте процесс работает иначе, чем из интерфейса.

Запуск идёт от имени системы, а не сотрудника с его правами. Права стоит проверять именно в таком фоновом запуске, а не в интерфейсе.

Агент перестал доходить до конца.

Внутри него идёт долгий процесс, не разбитый на порции. Такие задачи делают шагами с сохранением позиции.

Частые вопросы

Как узнать идентификатор нужного шаблона?

Выборкой шаблонов по типу документа. Имя шаблона для запуска не используется.

Как остановить запущенный процесс?

Отдельным вызовом остановки по номеру процесса и документу. Ошибки при этом приходят так же, отдельным аргументом.

Как передать в процесс свои значения?

Третьим аргументом запуска по кодам параметров шаблона. Коды берут из самого шаблона.

Почему автозапуск не сработал от правки из кода?

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

Смежное

Первоисточник