Руководство программиста Workflow


НАЧАЛО >> Workflow >> Руководство программиста Workflow📄 Скачать в DOCX


1. Роль прикладного модуля

Прикладной модуль не должен дублировать engine Workflow. Его задача - предоставить доменную конфигурацию и точки расширения:

2. Запуск перехода

Программный запуск перехода выполняется через 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.

3. Workflow-команды

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 значение берется из поля текущей записи

4. WorkflowContext

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 откатывает изменения записи и не сохраняет переход.

5. GBL post-function

Для типа gbl в переходе указывается MNU whitelist и ключ сценария. Описание пункта MNU должно указывать имя .gbl-файла. Workflow загружает сценарий из БД, подставляет JSON-параметры через GlobalCorrection::ApplyParams() и выполняет его над рабочей копией записи.

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

6. Форматы

Форматы используются в нескольких местах:

Место Что должен вернуть формат
condition перехода разрешающее или запрещающее значение
проверка доступа представления разрешающее или запрещающее значение
колонка списка HTML ячейки
секция карточки HTML блока карточки
заголовок страницы дополнительный HTML-блок перед списком или карточкой

Формат ИРБИС 128 должен лежать в контейнере, указанном в настройке представления или определяемом типом записи. Для условий перехода сначала используется Format128 с параметрами workflow.

Верхнюю навигацию и панель фильтров не нужно писать отдельным форматом прикладного модуля. Состав меню задается в WorkflowViewScheme, параметры отображения пункта - в WorkflowView, а элементы фильтрации берутся из WorkflowFilter.

7. Универсальные страницы

Обычная пользовательская страница проекта вызывается единым маршрутом:

?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: поле, подполе и поисковый префикс.

8. Системный JSON модуля

Модуль может поставлять JSON с workflow-конфигурацией. Рекомендуемый состав:

Для подготовки JSON можно настроить проект через интерфейс и воспользоваться экспортом проекта в WorkflowProject.

9. Диагностика и приемка

Workflow::GetWorkflowImpactAnalysis() показывает, какие проекты, статусы, переходы, экраны, фильтры, представления и материализованные состояния записей связаны с workflow. Используйте его перед удалением или значимым изменением workflow.

Модули Workflow, WorkflowProject, WorkflowStatus и WorkflowTransition реализуют HealthCheck_Self(). Эти проверки не заменяют общесистемный HealthCheck, но дают модулю-владельцу простой contract-test: доступность зависимых Workflow*-модулей, корректность модели записи, описаний, цветов статусов, маршрутов переходов и реестра command post-functions.

10. Совместимость

Не привязывайте engine Workflow к конкретному модулю. Если нужна доменная логика, используйте:

Такой подход позволяет применять Workflow к разным типам записей, например к RQST или новым прикладным сущностям.