НАЧАЛО >> Workflow >> Руководство программиста Workflow📄 Скачать в DOCX
Прикладной модуль не должен дублировать engine Workflow. Его задача - предоставить доменную конфигурацию и точки расширения:
.ws и .wss для he3;__call/Workflow;.page для viewType=page; списки, карточки, формы создания и доски открываются через Workflow/Show.Программный запуск перехода выполняется через Workflow::ApplyRecordTransition().
$workflow = UseModule('Workflow');
$project = UseModule('WorkflowProject')->GetProjectByKey('PROJECT');
$db = UseModule('i128f')->GetDb('I128F');
$result = $workflow->ApplyRecordTransition(
$db,
$record,
$project,
'',
'finish',
array('comment' => 'Ответ отправлен')
);
Если переход выбирается по целевому статусу, передайте целевой статус вместо пустой строки. Если переход выбирается по ключу, передайте ключ в параметре $transitionId.
Перед показом кнопки, запуском API-действия или массовой операцией используйте диагностический preflight:
$workflowModule = UseModule('Workflow');
$transition = $workflowModule->FindRecordTransition($record, $project, '', 'finish');
if ($transition instanceof ObjectDataWorkflowTransition) {
$explain = $workflowModule->ExplainRecordTransition($db, $record, $project, $transition);
} else {
$explain = array('allowed' => false, 'message' => 'Переход workflow недоступен');
}
if (!$explain['allowed']) {
echo $explain['message'];
}
Для проверки без сохранения записи и без выполнения post-functions используйте Workflow::DryRunRecordTransition(). Dry-run возвращает тот же diagnosticCode, будущий workflow-state и признак wouldChangeRecord.
Workflow-команда реализуется как __call-функция прикладного модуля в папке __call/Workflow. Класс наследуется от ObjectModuleExternalFunctionWorkflow и реализует Exec(WorkflowContext $ctx): WorkflowCommandResult.
Workflow строит список доступных команд самостоятельно: перебирает .inc-файлы в __call/Workflow, вычисляет метод по имени файла и читает описание из класса команды. Ключ команды имеет вид Module.CommandName; для вложенных папок путь превращается в точки, например Module.Group.CommandName.
class fncall_Module_Workflow_CommandName extends ObjectModuleExternalFunctionWorkflow
{
protected array $PrimaryTypes = array('MODULE_RECORD_TYPE');
protected array $Params = array(
'user' => array('Source' => 'context', 'Key' => 'userLogin'),
);
function GetTitle()
{
return 'Записать исполнителя';
}
function GetDescription()
{
return 'Записывает в текущую запись логин пользователя, выполняющего переход workflow.';
}
public function Exec(WorkflowContext $ctx): WorkflowCommandResult
{
$record = $ctx->GetRecord();
$user = $ctx->GetParam('user', '');
$record->SetSubField(100, 1, 'A', $user);
return $this->Ok();
}
}
PrimaryTypes ограничивает типы записей v920, для которых команда может применяться. Если массив пустой, команда считается общей. Params задает схему параметров post-function; параметры нормализуются перед вызовом. Поддерживаются источники:
| Source | Назначение |
|---|---|
input |
значение берется из данных перехода или формы |
const |
значение берется из конфигурации post-function |
context |
значение берется из WorkflowContext |
field |
значение берется из поля текущей записи |
WorkflowContext передается в каждую command post-function.
| Метод | Что возвращает |
|---|---|
GetDb() |
текущая БД |
GetRecord() |
рабочая копия записи |
GetOriginalRecord() |
исходная копия записи до перехода |
GetWorkflow() |
объект workflow |
GetProject() |
объект проекта, если переход выполняется в проекте |
GetWorkflowOwner() |
владелец состояния |
GetTransition() |
выполняемый переход |
GetEffect() |
текущая post-function |
GetParams() |
нормализованные параметры команды |
GetInput() |
входные данные формы или действия |
GetUserSid() |
SID пользователя |
GetUserLogin() |
логин пользователя |
GetFromStatus() |
исходный статус |
GetToStatus() |
новый статус |
Команда должна возвращать WorkflowCommandResult::ok() или WorkflowCommandResult::error(). При ошибке Workflow откатывает изменения записи и не сохраняет переход.
Для типа gbl в переходе указывается MNU whitelist и ключ сценария. Описание пункта MNU должно указывать имя .gbl-файла. Workflow загружает сценарий из БД, подставляет JSON-параметры через GlobalCorrection::ApplyParams() и выполняет его над рабочей копией записи.
GBL удобен для простых массовых преобразований записи, но сложную доменную логику лучше оформлять command-функцией.
Форматы используются в нескольких местах:
| Место | Что должен вернуть формат |
|---|---|
| condition перехода | разрешающее или запрещающее значение |
| проверка доступа представления | разрешающее или запрещающее значение |
| колонка списка | HTML ячейки |
| секция карточки | HTML блока карточки |
| заголовок страницы | дополнительный HTML-блок перед списком или карточкой |
Формат ИРБИС 128 должен лежать в контейнере, указанном в настройке представления или определяемом типом записи. Для условий перехода сначала используется Format128 с параметрами workflow.
Верхнюю навигацию и панель фильтров не нужно писать отдельным форматом прикладного модуля. Состав меню задается в WorkflowViewScheme, параметры отображения пункта - в WorkflowView, а элементы фильтрации берутся из WorkflowFilter.
Обычная пользовательская страница проекта вызывается единым маршрутом:
?id=Workflow/Show&project=PROJECT&recordType=MY_RECORD_TYPE&pageKey=list
Если требуется программно встроить конкретный renderer, прикладный код может вызвать WorkflowView напрямую:
echo UseModule('WorkflowView')->Page_RenderConfiguredPage(
UseModule('MyModule')->GetCurrentProjectKey(),
'MY_RECORD_TYPE',
'list',
'I128F'
);
Для внешней страницы, например специального отчета, можно вывести только общую навигацию проекта:
$workflowView = UseModule('WorkflowView');
$content = $workflowView->RenderConfiguredNavigation(
UseModule('MyModule')->GetCurrentProjectKey(),
'MY_RECORD_TYPE',
'Ask',
'I128F'
);
echo $workflowView->Page_RenderPageContent($content . $formHtml);
Чтобы такая страница появилась в навигации, добавьте для нее WorkflowView типа page, включите pageKey -> viewKey в WorkflowViewScheme и задайте у представления группу навигации.
Поиск конкретной записи выполняется через настройки идентификатора в WorkflowProject: поле, подполе и поисковый префикс.
Модуль может поставлять JSON с workflow-конфигурацией. Рекомендуемый состав:
Для подготовки JSON можно настроить проект через интерфейс и воспользоваться экспортом проекта в WorkflowProject.
Workflow::GetWorkflowImpactAnalysis() показывает, какие проекты, статусы, переходы, экраны, фильтры, представления и материализованные состояния записей связаны с workflow. Используйте его перед удалением или значимым изменением workflow.
Модули Workflow, WorkflowProject, WorkflowStatus и WorkflowTransition реализуют HealthCheck_Self(). Эти проверки не заменяют общесистемный HealthCheck, но дают модулю-владельцу простой contract-test: доступность зависимых Workflow*-модулей, корректность модели записи, описаний, цветов статусов, маршрутов переходов и реестра command post-functions.
Не привязывайте engine Workflow к конкретному модулю. Если нужна доменная логика, используйте:
WorkflowViewScheme, параметров отображения в WorkflowView и фильтров в WorkflowFilter;Такой подход позволяет применять Workflow к разным типам записей, например к RQST или новым прикладным сущностям.