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

Бизнес-процесс над элементом списка - поля, раздел, PHP-код

Читаем поля документа в бизнес-процессе, добираем то, чего в них нет, и разбираемся с полями типа «список».

Решение

Получаем раздел элемента действием PHP-код:

// третий элемент идентификатора документа - это номер самого элемента
$element = CIBlockElement::GetList([], ['ID' => $this->GetDocumentId()[2]],
false, false, ['ID', 'IBLOCK_SECTION_ID'])->Fetch();
$section = CIBlockSection::GetByID($element['IBLOCK_SECTION_ID'])->Fetch();
$this->SetVariable('SectionName', $section['NAME'] ?? '');

Идентификатор документа приходит массивом из трёх частей: модуль, тип документа и сам идентификатор. Третий элемент и есть то, что нужно передавать в выборки.

Читаем поле типа «список» и приводим к подписи:

$value = $this->GetVariable('Status'); // здесь идентификатор значения
$enum = CIBlockPropertyEnum::GetByID($value);
$this->SetVariable('StatusText', $enum['VALUE'] ?? '');

В переменной лежит идентификатор, а не текст. Условие, сравнивающее её со строкой, не сработает никогда, и процесс тихо уйдёт по ветке «иначе».

Ставим задачу участнику и разбираем результат:

// поле задачи «Ответственный» принимает массив вида ['user_12', 'group_5']
$this->SetVariable('Approver', ['user_' . $userId]);

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

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

CBPDocument::StartWorkflow(
$templateId,
['lists', 'BizprocDocument', $elementId], // тип документа и его идентификатор
['Approver' => ['user_' . $userId]], // параметры запуска
$errors
);

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

Смотрим, какие процессы уже идут по документу:

$running = CBPStateService::GetDocumentStates(['lists', 'BizprocDocument', $elementId]);
foreach ($running as $state) {
printf("%-28s шаблон=%s состояние=%s\n",
$state['TEMPLATE_NAME'], $state['TEMPLATE_ID'], $state['STATE_TITLE']);
}

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

Читаем журнал экземпляра при разборе:

$log = CBPTrackingService::GetList([], ['WORKFLOW_ID' => $workflowId], false, false,
['MODIFIED', 'ACTION_NAME', 'ACTION_NOTE']);
while ($row = $log->Fetch()) {
printf("%s %-24s %s\n", $row['MODIFIED'], $row['ACTION_NAME'], $row['ACTION_NOTE']);
}

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

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

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

Условие по полю типа «список» никогда не выполняется.

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

Правка шаблона не подействовала на идущий процесс.

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

Переменная типа «список» не сохраняется из PHP-кода.

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

Процесс не видит раздел элемента.

Раздел не входит в поля документа. Его добирают действием PHP-код по идентификатору элемента и кладут в переменную процесса.

Задача ушла не тому.

В поле ответственного передан идентификатор без префикса. Модуль ждёт строку вида user_12 или group_5, а голое число трактует иначе.

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

Что доступно внутри действия PHP-код?

Всё API платформы: код выполняется на сервере в контексте процесса. Через $this доступны переменные процесса и идентификатор документа, остальное берут обычными вызовами.

Как получить элементы списка, не зная их идентификаторов?

Обычной выборкой по инфоблоку списка с нужным фильтром. Списки хранятся в инфоблоках, и весь их API - это API инфоблоков.

Можно ли динамически заполнить варианты у переменной-списка?

Штатно варианты задаются при объявлении переменной. Динамический набор делают строковой переменной и своим действием выбора либо отдельным справочником в списке.

Как узнать, кому делегирована задача?

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

Смежное

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