Перейти к содержанию

Маршруты документов

Введение в маршруты

Подсистема Маршруты документов предназначена для простой настройки в табличном виде маршрутов прохождения и обработки документов. Её основная цель - чтобы администраторы могли самостоятельно настраивать сложные маршруты документов (бизнес-процессы), не привлекая специалистов по внедрению.

Основные особенности и возможности подсистемы маршрутов:

  • Подсистема маршрутов входит в базовую поставку платформы и отдельно не лицензируется.
  • Сразу в базовой поставке есть возможность пользователям самостоятельно настраивать маршрут согласования документа.
  • В платформе есть набор типов этапов, с помощью которых можно строить сложные маршруты обработки документов.

    Note

    Есть возможность разработки собственных типов этапов.

  • В подсистеме маршрутов есть масса возможностей по гибкой настройке прав доступа: на добавление новых этапов в маршрут обработки карточки документа, на перемещение, удаление и редактирование автоматически добавленных в маршрут этапов.

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

Как подключить подсистему маршрутов для типа карточки/типа документа описано в разделе Использование маршрутов.

Note

Процессы обработки документов в платформе также можно настраивать с помощью другого модуля - графического конструктора бизнес-процессов.

Основные компоненты подсистемы маршрутов

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

  • Этап маршрута - основной элемент построения маршрута (на скрине выше этап - это строка таблицы маршрута документа). Этапы могут быть различных типов, предназначенные для различных целей. С платформой поставляется большой набор этапов для различных целей, например этапы для согласования, исполнения, смены состояния и т.д. С их помощью можно простыми средствами построить сложные последовательности действий. Также можно создавать собственные типы этапов (для этого требуется программирование), которые будут прозрачно встроены в общую систему.

Компоненты, настраиваемые администратором

  • Шаблон этапа - это специальная карточка, которая содержит в себе один или несколько заранее настроенных этапов маршрута. Подсистема строит маршрут документа, собирая этапы из различных шаблонов. Карточка содержит целый ряд настроек, управляющих правилами подстановки или пропуска этого шаблона по различным условиям. У каждого этапа в составе карточки шаблона также есть ряд настроек, позволяющих управлять его подстановкой в маршрут, а также организовывать различные действия при выполнении этапа.
  • Группа шаблонов - это также специальная карточка, объединяющая несколько шаблонов этапов в одну группу, и позволяющая управлять их подстановкой и выполнением в маршруте как единым целым. Маршрут любой карточки будет состоять из одной или нескольких групп, выполняемых последовательно.
  • Кнопка процесса - это карточка, позволяющая описывать новые кнопки (тайлы) в меню системы (это могут быть как глобальные кнопки - т.е. доступные в меню всегда, так и контекстные - доступные в меню только когда открыта карточка соответствующего типа). С кнопкой можно связать группу шаблонов, которая должна выполниться по ее нажатию или указать дополнительные параметры управления процессом.
  • Сценарии (скрипты) - при помощи простых скриптов можно чрезвычайно сильно расширить возможности подсистемы маршрутов. Для скриптов используется синтаксис C#, и в различных объектах системы с их помощью можно модифицировать маршруты и их поведение, манипулировать данными карточек, организовывать циклы и сложные связи между различными этапам, управлять условиями подставки и пропуска этапов. Далее будет приведено большое количество примеров таких условий и скриптов, с помощью которых можно будет убедиться, что это не сложно. Обычный администратор, владеющий базовыми навыками скриптинга, легко сможет использовать их в работе.
  • Методы расширений - это карточка, позволяющая определить библиотеку различных вспомогательных методов (скриптов), которые в дальнейшем использовать в скриптах и условиях. Методы расширений позволяют сильно упростить скрипты и не дублировать одинаковые действия.

Виды процессов маршрутов, расчет маршрута и его выполнение

Существуют два вида процессов маршрутов: основной процесс и второстепенный процесс.

  • Основной процесс – это главный процесс маршрута по карточке. Он отображается на вкладке Маршрут карточки.
  • Второстепенный или вторичный процесс – это процессы, которые стартуют по различным внешним событиям, в основном по тайлам. Эти процессы обычно синхронные - они запускаются, выполняют какие-то действия (меняют состояние, выполняют переход в основном процессе и т.д.) и завершаются. Но могут быть и вторичные процессы, которые отправляют задания и, соответственно, “замирают” и ждут завершения заданий для своего завершения. Такие процессы называются асинхронными. Вторичные процессы не видны на вкладке маршрут, и, соответственно, не могут быть явным образом изменены пользователем.

Также различают два вида процессов по синхронности этапов, входящих в маршрут:

  • Асинхронный процесс – процесс, некоторые этапы которого асинхронные, т.е. не могут выполниться сразу, а ждут чего-то от пользователя или внешней системы. Например, отправка задания – это асинхронный этап. Система отравляет задание и ждет, когда пользователь завершит его. Только тогда процесс идет дальше.

  • Синхронный процесс – это процесс, все этапы которого выполняются сразу же. Такой процесс рассчитывается и выполняется целиком в памяти.

Расчет маршрута или его части выполняется в следующих ситуациях:

  • Запуск процесса. В этом случае система полностью строит маршрут – вычисляет последовательность групп, и в них последовательность этапов (через шаблоны этапов). Подробно все эти ситуации описаны ниже.
  • “Вход” в группу. Когда при выполнении процесса маршрут дошел до какой-то группы, то перед началом выполнения система перестраивает группу.

    Note

    В базовой поставке платформы маршрут настроен таким образом, что при несогласовании документа выполняется возврат в начало маршрута на этап “Доработка”. В данном случае возврат на доработку является частным случаем “входа” в группу и поэтому перед формированием задания доработки будет выполнен пересчет маршрута.

  • При достижении этапа “Пересчёт маршрута”. Если в состав какой-нибудь группы входит этап “Пересчёт маршрута”, то при выполнении этого этапа система полностью пересчитает состав текущей группы после этапа “Пересчёт маршрута”.

  • При нажатии кнопки “Пересчитать маршрут” на вкладке “Маршрут”.

При расчете маршрута основного процесса система включает в маршрут:

  • Группы, не связанные с кнопками/тайлами и удовлетворяющие ограничениям при пересчёте:

    • Тип соответствует типу текущей карточки/документа.
    • Роль соответствует одному из значений: владельцу текущего процесса, если он задан, иначе инициатору текущего процесса, если он задан, иначе текущему сотруднику.
  • Затем выполняются сценарии инициализации всех групп (построение маршрута).

  • Затем выполняются условия включения группы в маршрут (построение маршрута), у подтвержденных групп, которые останутся в маршруте (условие истинно), устанавливается флаг Confirmed = true в контексте.
  • Затем для каждой подтвержденной группы (условие включения в маршрут истинно) по очереди:

    • Вычисляются шаблоны этапов, которые включены в эту группу И которые по типу документа И роли соответствуют текущему типу документа и сотруднику – владельцу текущего процесса, если задан, иначе инициатору текущего процесса, если задан, иначе текущему сотруднику.
    • Выполняются сценарии инициализации этих шаблонов этапов.
    • Выполняются условия включения в маршрут этих шаблонов этапов. У подтвержденных шаблонов, этапы которых останутся в маршруте (условие истинно), устанавливается флаг IKrScript.Confirmed = true в контексте.
    • Строится маршрут по этой группе по подтвержденным этапам.
    • Выполняются сценарии постобработки для всех шаблонов, в т.ч. неподтвержденных.
  • Затем для всех групп выполняются сценарии постобработки (построение маршрута), в том числе для неподтвержденных.

  • Далее система приступает к выполнению первой группы маршрута с выполнением ее пересчёта. Пересчёт группы выполняется по тем же правилам, что и для всего маршрута.

Example

В маршруте участвуют три группы: Группа 0 (условие ложно), Группа 1 (условие истинно), Группа 2 (условие истинно). Терминология:

  • Before - сценарий инициализации группы или шаблона этапа
  • Condition - условия включения в маршрут (построение маршрута) группы или шаблона этапа
  • After - сценарий постобработки группы (построение маршрута) или шаблона этапа
  1. Выполняем Before для всех трех групп.
  2. Выполняем Condition для всех групп.

    2.0. Не берем шаблоны для группы 0, т.к. Condition = false.
    2.1. Берем шаблоны для группы 1.
    2.1.1. Выполняем Before для всех шаблонов группы 1.
    2.1.2. Выполняем Condition для всех шаблонов группы 1.
    2.1.3. Строим маршрут для группы 1 на основе подтвержденных в п 2.1.2.
    2.1.4. Выполняем After для всех шаблонов группы 1. Маршрут, построенный в 2.1.3, доступен в контексте.
    2.2 Берем шаблоны для группы 2.
    2.2.1. Выполняем Before для всех шаблонов группы 2.
    2.2.2. Выполняем Condition для всех шаблонов группы 2.
    2.2.3. Строим маршрут для группы 2 на основе подтвержденных в п 2.2.2.
    2.2.4. Выполняем After для всех шаблонов группы 2. Маршрут, построенный в 2.2.3 доступен в контексте.

  3. Выполняем After для всех трех групп. На этом моменте доступен полный маршрут по всем группам.

При расчете маршрута вторичного процесса, связанного с кнопкой/тайлом, система включает в маршрут:

  • Группы, которые непосредственно связаны с этим тайлом И

    • проверяется вхождение текущего сотрудника в роли, указанные в поле Роли группы;
    • если тайл глобальный, то поле Тип документа группы игнорируется;
    • если тайл контекстный, то в маршрут попадают только группы, у которых в поле Тип документа присутствует тип текущего документа.

Далее маршрут считается по общим правилам.

Пересчёт группы при начале ее выполнения выполняется системой по аналогии с полным перестроением маршрута:

  • Сначала выполняется сценарий инициализации (построение маршрута) группы.
  • Затем выполняется условие включения в маршрут (построение маршрута) группы:

    • если условие истинно, то вычисляются шаблоны этапов, которые включены в эту группу И которые по типу документа И роли соответствуют текущему типу документа и сотруднику - владельцу текущего процесса, если задан, иначе инициатору текущего процесса, если задан, иначе текущему сотруднику;
    • выполняются сценарии инициализации этих шаблонов этапов;
    • выполняются условия включения в маршрут этих шаблонов этапов. У подтвержденных шаблонов, этапы которых останутся в маршруте (условие истинно), устанавливается флаг IKrScript.Confirmed = true в контексте;
    • строится маршрут по этой группе по подтвержденным этапам;
    • выполняются сценарии постобработки для всех шаблонов, в т.ч. неподтвержденных.
  • Затем для группы выполняется сценарий постобработки (построение маршрута).

  • Далее система приступает к выполнению этой группы маршрута.

Владелец процесса – это персональная роль, от имени которой выполняется пересчёт основного маршрута. Для её получения или задания следует использовать свойство IKrScript.ProcessOwner или IKrScript.WorkflowProcess.ProcessOwner.

Владелец текущего процесса – это персональная роль, от имени которой выполняется пересчёт текущего маршрута. Для основного процесса совпадает с владельцем процесса. Для её получения или задания следует использовать свойство IKrScript.WorkflowProcess.ProcessOwnerCurrentProcess.

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

Пересчёт части маршрута этапом “Пересчёт маршрута” выполняется следующим образом:

  • Система полностью пересчитывает текущую группу, так же, как и при входе в группу.
  • Если в пересчитанной группе этапа “Пересчёт маршрута” нет – выдается ошибка.
  • Если в пересчитанной группе ранее этапа “Пересчёт маршрута” есть новые этапы – выдается ошибка.
  • Если всё в порядке, управление передается на следующий этап в группе.

Правила выполнения маршрута:

  • Система выполняет маршрут в глобальном порядке групп, входящих в него.
  • При “входе” в группу, т.е. перед выполнением первого этапа, входящего в эту группу, система выполняет и проверяет рантайм-условие (выполнение маршрута). Если условие ложно, система переходит к следующей группе в маршруте.
  • Если рантайм-условие истинно, то выполняется сценарий рантайм-инициализации (выполнение маршрута) группы.
  • Далее система по очереди выполняет этапы, входящие в группу, при этом для каждого этапа по очереди:

    • вычисляется условие;
    • если условие истинно, то выполняется сценарий инициализации и выполняется собственно этап;
    • при завершении этапа выполняется сценарий постобработки.
  • После завершения последнего этапа, входящего в группу, выполняется сценарий рантайм-постобработки группы (выполнение маршрута).

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

    • Формирует список групп, подходящих по типу документа и роли сотрудника, которые по порядку (поле Порядок) должны выполняться между текущей завершенной группой и следующей.
    • Если такие группы есть, для них выполняется полный пересчёт маршрута по общим правилам.

Особенности работы маршрутов при удалении или изменении групп или шаблонов этапов

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

  • при запуске процесса;
  • при входе в группу;
  • при достижении этапа “Пересчёт маршрута”;
  • при нажатии кнопки “Пересчитать” на вкладке Маршрут;

При исключении группы или шаблона этапов из маршрута удаляются также и подпадающие под пересчёт все связанные этапы. В том числе и изменённые пользователем.

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

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

Если в шаблоне есть этап с вычисляемыми исполнителями, то при удалении такого шаблона/этапа карточки, где должен выполниться этот этап, сломаются. Система будет пытаться вычислить SQL исполнителей, но не сможет, т.к. такой шаблон/этап уже не существует. Чтобы избежать таких проблем рекомендуется не удалять такие шаблоны/этапы, а сделать шаблон недоступным для новых карточек (например, прописав в условии старта шаблона, скрипт false) и желательно переименовать/добавить описание, чтобы в будущем не забыть, что это шаблон для поддержания старых карточек. А новые карточки пойдут уже по новому маршруту.

Примеры маршрутов

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

Note

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

Каждый пример разбирается в несколько шагов:

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

Примеры, которые рассматриваются:

Инициация нового договора (пример)

Ниже представлена общая схема процесса.

После инициации договор будет отправлен на согласование, если он дороже 100 000.

После успешного согласования он будет переведен в состояние “На подписании руководителем” и отправлен на подписание руководителю.

Затем договор будет переведен в состояние “На подписании контрагентом” и отправлен инициатору на организацию подписания контрагентом.

И в самом конце договор получит состояние “Подписано сторонами”.

Интересным аспектом этого процесса является собственный этап доработки, который включен в подписание. Если кто-либо (руководитель или контрагент) не подписали документ, то после доработки документ вновь уйдет на подписание, а не на полный цикл согласования с прохождением всех согласующих.

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

Для создания новой карточки договора настроен тайл Инициировать договор в меню системы, необходимо его нажать.

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

Для запуска маршрута необходимо в меню системы нажать на кнопку Запустить процесс. Т.к. сумма договора меньше 100 000, то договор должен сразу попасть на подписание.

Note

Кнопка Запустить процесс по схеме согласования служит для запуска маршрута с предварительным согласованием документа по настроенной пользователем схеме - это типовая возможность платформы, описанная в Руководстве пользователя, но в данном примере не рассматривается.

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

На вкладке Маршрут можно увидеть автоматически сформированный маршрут:

Видно, что состояние карточки изменилось на “На подписании руководителем”. Состояние карточки можно посмотреть и на основной вкладке карточки, и на вкладке Маршрут.

Возьмем задание на подписание в работу соответствующей кнопкой в самом задании (работа с заданиями в системе описана в Руководстве пользователя).

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

Note

В настройках маршрута для этапа подписания есть возможность разрешить из задания подписания отправлять дочерние задания согласования (см. этап “Подписание”).

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

Далее сразу же приходит следующее задание. Это задание инициатору на организацию подписания договора контрагентом.

Состояние карточки изменилось и теперь оно “На подписании контрагентом”.

Теперь откажем в подписании, введя комментарий (при отказе в подписании он обязательный).

И сразу же приходит задание доработки. Состояние карточки изменилось на “Отказ”.

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

Статус прохождения маршрута можно посмотреть в листе согласования. Лист согласования - это специальный виртуальный файл, который для удобства система формирует у каждой карточки, участвующей в согласовании. В нем в удобном для просмотра, печати или, например, отправки почтой, в табличном виде представлен маршрут согласования и подписания документа. Файл “Лист согласования” всегда актуальный, так как формируется системой автоматически в момент запроса содержимого и физически в карточке не хранится.

Также посмотреть текущее состояние всех документов, отправленных текущим пользователем на согласование, можно в представлении Мои документы в рабочем месте Пользователь.

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

Снова придет задание на подписание руководителем. Система начала новый цикл подписания.

Чтобы полностью завершить процесс, необходимо текущее задание подписания и следующее задание на подписание с контрагентом завершить вариантом Подписать.

Процесс завершится и состояние карточки изменится на “Подписано сторонами”.

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

Теперь инициируем договор с большей суммой. Еще раз нажимаем в меню системы кнопку Инициировать договор и в созданной карточке указываем сумму 200 000, после чего кнопкой запустить процесс, расположенной в меню системы запускаем выполнение маршрута.

И сразу же приходит задание на согласование договора, которого не было в прошлом кейсе.

Перейдя на вкладку Маршрут можно увидеть новый этап “Согласование внутри компании”. Он состоит из последовательного согласования ролями “Руководитель инициатора” и подразделением “Финансовый департамент”.

Если завершить задание согласования положительным вариантом (кнопка Согласовать после взятия задания в работу), а затем успешно согласовать и следующее задание, то маршрут перейдет на этапы подписания как в предыдущем кейсе - сначала внутри компании руководителем, а затем и контрагентом. Можно поэкспериментировать с данными заданиями, выбирая разные варианты прохождения маршрута.

Note

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

Особенности настройки данного маршрута:

  • Тайл создания нового договора по шаблону реализован с помощью вторичного процесса (Администратор -> Маршруты -> Вторичные процессы) с названием “tile: Инициировать договор”. Для данного вторичного процесса не настроены этапы маршрута, т.к. он выполняет связанную с процессом группу этапов “sg: Инициировать договор”, группа же в свою очередь выполняет шаблон этапов “st: Договор инициация (тайл)”, в котором есть этап создания карточки по шаблону.
  • Условие подстановки этапа согласования в зависимости от суммы договора прописано одной строчкой скрипта в условиях выполнения шаблона этапов “st: Договор согласование”.
  • Группа “sg: Договор согласование” не отображается в маршруте карточки документа, но инициализируется и служит для двух целей (выполняет скрипты):
    • при инициализации маршрута выполняется проверка, что в карточке договора указана сумма (совместно с валютой);
    • выставляется флаг для пропуска этапа доработки, который есть в маршруте перед этапом подписания (этап должен запускаться только при неподписании, но не при первом прохождении маршрута).
  • Подписание документа выполняется в рамках группы маршрута “sg: Договор подписание”, группа выполняет шаблон этапов “st: Договор подписание”.
  • В шаблоне этапов подписания для этапа доработки указано условие запуска (пропуск при первом выполнении маршрута). В случае неподписания документа маршрут возвращается в начало текущей группы - как раз на этап доработки. Смена состояний договора реализована с помощью этапов соответствующего типа.

Подготовка, согласование и исполнение служебной записки/заявки (пример)

Следующий пример существенно сложнее. Это процесс служебной записки разных типов.

Схема процесса:

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

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

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

Если заявка является финансовой:

  • После отправки на согласование будет предложено предоставить финансовое обоснование или ввести комментарий.

  • Когда заявка инициирована и приложено обоснование, она отправляется на согласование. В нем участвуют роли: “Руководитель инициатора”, “Финансовый департамент” и “Главный бухгалтер”. Интересно, что времени на согласование система будет давать всё меньше с каждым новым циклом согласования.

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

Если инициатор не подтверждает выполнение заявки, то система вновь отправляет задание исполнителю заявки с комментарием недовольного инициатора.

Итак, создадим новую служебную записку помощью тайла Обычная СЗ в группе тайлов СЗ в меню системы.

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

Далее кнопкой на тулбаре диалогового окна служебной записки можно ее отправить на согласование.

Система сформирует маршрут и запустит процесс, отправив задание на исполнение заявки на роль “ДИТ”. При этом карточка автоматически откроется уже во вкладке.

На вкладке Маршрут можно посмотреть автоматически сформированный маршрут. В настоящий момент активен этап “Исполнение обычной СЗ”.

В задании уже написано, что нужно сделать, возьмем задание в работу.

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

Завершим задание кнопкой Завершить, чтобы сообщить системе что заполнение заявки завершено и можно продолжить маршрут.

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

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

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

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

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

Состояние карточки изменилось на “На исполнении”. Часто со сменой состояния также настраивают изменения прав доступа на карточку, например, чтобы инициатор имел права на изменение данных и файлов карточки, только пока она в состоянии “Проект”.

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

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

Возьмем задание в работу. Данное задание другого типа - в нем доступны только два варианта завершения Выполнено и Не принято. Эти варианты специально настроены под данный шаг маршрута с помощью типа этапа Настраиваемое задание.

Не примем выполнение, нажав на кнопку Не принято и указав комментарий.

Маршрут снова переходит на этап исполнения заявки, отправив заданию исполнителю с комментарием инициатора. Завершим данное задание.

Система вновь присылает задание на подтверждение, которое завершим уже вариантом Выполнено.

Исполнение заявки принято, процесс завершен, карточка перешла в состояние “Исполнен”.

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

Теперь инициируем финансовую заявку, чтобы посмотреть на работу согласования. В меню системы нажмем на кнопку СЗ -> Финансовая СЗ.

Вновь система создала карточку заявки и открыла её в диалоговом окне, как и с обычной СЗ - процесс запускается по кнопке Отправить на согласование, расположенной на тулбаре диалогового окна карточки. На Инициатора сформируется первое задание по маршруту:

Задание уже взято в работу. Нажав на кнопку Приложить обоснование откроется диалоговое окно, где можно добавить файл или указать комментарий. А для завершения данного задания, необходимо в диалоговом окне нажать на кнопку тулбара Отправить.

Документ отправится дальше по маршруту.

Для примера система настроена таким образом, что приложенные в диалоге Предоставление обоснования файлы переносятся в карточку документа, а введённый комментарий к финансовому обоснованию записывается в поле Комментарий к обоснованию карточки служебной записки.

Согласно схеме процесса, роли “Руководитель инициатора”, приходит задание на согласование заявки. Срок задания составляет 5 рабочих дней.

Возьмем задание в работу и завершим его вариантом Не согласовать.

Note

Данное задание отправляется типом этапа “Согласование”. Работа с заданием согласования подробно описана в Руководстве пользователя.

Система сразу сформирует следующее задание по маршруту - инициатору на доработку для корректировки заявки.

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

Система снова отправляет задание на предоставление обоснования, где Инициатор в диалоговом окне может приложить файл или указать комментарий.

После завершения задания на предоставление обоснования, система вновь отправляет задание первому из согласующих - роли “Руководитель инициатора”. Обратите внимание, что срок задания уменьшился и составляет уже 4 дня! Все работает так, как и было задумано и описано в начале раздела с данными примером. Если дальше не согласовывать документ, то с каждым новым циклом срок будет уменьшаться, пока не составит 1 день.

Теперь согласуем документ, завершив задание согласования вариантом Согласовать. Система сразу же отправляет следующее задание согласования на роль “Финансовый департамент”.

Если завершить и это задание, согласовав документ, мы попадем на этап согласования финансового обоснования главным бухгалтером - тоже реализованное в виде диалога:

Завершим данное задание, пополнив поле Результат проверки и нажав на кнопку тулбара диалога Согласовано.

Мы попадаем на уже знакомый нам этап исполнения заявки, только исполнителем будет другая роль, потому что категория заявки “Финансовая СЗ”.

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

Особенности настройки данного маршрута:

  • Тайлы создания служебной записки реализованы с помощью вторичных процессов (Администратор -> Маршруты -> Вторичные процессы) “tile: СЗ обычная” и “tile: СЗ финансовая”, причем этап создания карточки указан сразу тут, во вторичном процессе, на вкладке Маршрут, в отличии от тайла инициации договора, где этап создания карточки настроен через группу этапов и шаблон этапов.
  • Маршрут обработки СЗ настроен с помощью двух групп этапов: “sg: СЗ согласование” и “sg: СЗ исполнение”, причем в группе согласования СЗ написан скрипт - условие выполнения группы (только для финансовых СЗ).
  • Для выполнения маршрута настроены 5 шаблонов этапов (Администратор -> Маршруты -> Шаблоны этапов), названия которых начинаются с “st: СЗ …”. В данных шаблонах можно найти скрипты как для самих шаблонов, так и для этапов данных шаблонов - данные скрипты обеспечивают выполнение всей специфичной логики, описанной в данном примере.

Последовательное согласование договора купли-продажи по списку участников, заданных непосредственно в карточке (пример)

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

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

Создадим карточку договора купли-продажи из меню системы: Создать карточку -> Документы - > Договорной документ -> Договор купли-продажи.

Откроется новая карточка договора купли-продажи. Необходимо ее заполнить, указав нескольких сотрудников в поле Исполнители.

Note

Если в справочнике нет достаточного количества сотрудников, их можно создать.

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

После запуска карточка выглядит вот так:

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

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

  • войти в систему под сотрудником, на кого назначено задание;
  • назначить себя заместителем сотрудника;
  • или же добавить себя в список функциональных ролей задания - отобразив скрытое задание, кликнув на автора или исполнителя задания и в открывшемся диалоговом окне добавив запись с типом Исполнитель (подробней в разделе Редактирование списка ФРЗ).

Возьмем задание в работу и завершим положительным решением, т.к. вариантом Согласовать (подробнее о задании согласования в Руководстве пользователя). Система сразу же отправляет задание следующему согласующему, выбрав его по алфавиту из списка в поле Исполнители.

При этом в маршруте отображается всего один этап согласования (хотя при этом есть и другие, скрытые этапы):

Особенности настройки данного маршрута:

  • Все настройки маршрута можно увидеть в шаблоне этапов (Администратор -> Маршруты -> Шаблоны этапов) “st: Договор купли-продажи согласование в цикле”.
  • В инициализации данного шаблона система проверяет, что указан хоть один согласующий в поле Исполнители.
  • В инициализации этапа “Согласования” высчитывается согласующий.
  • При завершении задания согласования, маршрут переходит на этап “Управление процессом”, который обеспечивает возврат на шаг назад, снова на этап “Согласования” для отправки очередного задания согласования.

Создание уже зарегистрированного документа (пример)

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

В данном случае система по нажатию глобального тайла:

  • Создаст карточку входящего по шаблону.
  • Выполнит для нее регистрацию.
  • Откроет карточку в рабочем месте пользователя.

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

В подсистеме маршрутов есть этап “Регистрация”, который выполняет те же действия в автоматическом режиме или отправляет задание исполнителю.

Для тестирования данного процесса необходимо в меню системы нажать на тайл Зарегистрировать входящий.

Откроется и сразу сохранится карточка входящего, а на вкладке История заданий будет видно, что регистрация уже выполнена.

Особенности настройки данного маршрута:

  • Тайл реализован с помощью вторичного процесса с названием “tile: Зарегистрировать входящий”, этот процесс выполняет группу “sg: Зарегистрировать входящий (тайл)”, которая в свою очередь выполняет шаблон этапов “st: Зарегистрировать входящий (тайл)”.
  • В шаблоне этапов два этапа: создания карточки и регистрации документа.

Передача данных между процессами

Пример передачи данных будет рассмотрен на примере указания значения в задании, отправляемого этапом “Типизированное задание”.

В процессе-“отправителе” выполняется создание задания и сохранение передаваемого значения в состоянии выполняющегося процесса.

В процессе-“получателе” выполняется получение значения, сохранённого в хранилище состояния процесса “отправителя”.

Warning

Для работы примеров необходимо в карточке Настроек типового решения указать тип задания RsTestTask (RsTestTask) в таблице Расширенные настройки типов заданий, используемых в подсистеме маршрутов.

Note

Примеры выполняются на карточке типа “Дополнительное соглашение”.

Передача данных из основного процесса во вторичный процесс

  1. Сохранение значения в хранилище пользовательской информации основного процесса.

    Данный пример рассмотрен в шаблоне этапов с названием “st: Пример передачи значения. Из основного процесса”:

    Шаблон этапов содержит один этап “Типизированное задание”, настроенный следующим образом:

    • Тип задания: RsTestTask
    • Сценарий инициализации:

      this.ProcessInfoStorage["Comment"] = Guid.NewGuid().ToString();

  2. Получение значения из хранилища с дополнительной информацией основного процесса во вторичном процессе.

    Данный пример рассмотрен во вторичном процессе с названием “Пример передачи значения. Из основного процесса. Модификация задания”:

    Маршрут содержит этап “Сценарий” в котором задан скрипт инициализации:

    // Получение значения из хранилища с дополнительной информацией основного процесса. var processInfo = await this.GetPrimaryProcessInfoAsync(); var comment = processInfo.Get<object>("Comment");

    // Получение модифицируемого задания. var task = ((CardStoreTaskExtensionContext) this.CardContext).Task;

    // Установка значения в карточке задания. task.Card.Sections[KrConstants.KrTask.Name].Fields[KrConstants.KrTask.Comment] = comment;

Передача данных между вторичными процессами

  1. Сохранение значения в хранилище пользовательской информации первого вторичного процесса.

    Данный пример рассмотрен во вторичном процессе с названием “Пример передачи значения. Из вторичного процесса. Создание задания”:

    Маршрут вторичного процесса содержит один этап “Типизированное задание” настроенный следующим образом:

    • Тип задания: RsTestTask
    • Сценарий инициализации:

      this.ProcessInfoStorage["Comment"] = Guid.NewGuid().ToString();

  2. Получение значения из хранилища с дополнительной информацией основного процесса в вторичном процессе.

    Данный пример рассмотрен во вторичном процессе с названием @:

    Маршрут вторичного процесса содержит этап “Сценарий” в котором задан скрипт инициализации:

    // Получение модифицируемого задания. var task = ((CardStoreTaskExtensionContext) this.CardContext).Task;

    // Получение идентификатора вторичного процесса по идентификатору задания. var secondaryProcessID = await this.Db .SetCommand( this.DbScope.BuilderFactory .Select() .C("wt", "ProcessRowID") .From("WorkflowTasks", "wt").NoLock() .Where() .C("wt", "RowID").Equals().P("TaskRowID") .Build(), this.Db.Parameter("TaskRowID", task.RowID)) .LogCommand() .ExecuteAsync<Guid>(this.CancellationToken);

    if(secondaryProcessID == Guid.Empty) { this.AddError($"Не найден вторичный процесс для задания с ИД = {task.RowID:B}."); return; }

    // Получение значения из хранилища с дополнительной информацией по найденному вторичному процессу. var processInfo = await this.GetSecondaryProcessInfoAsync(secondaryProcessID); var comment = processInfo.Get<object>("Comment");

    // Установка значения в карточке задания. task.Card.Sections[KrConstants.KrTask.Name].Fields[KrConstants.KrTask.Comment] = comment;

Изменение заданий, отправляемых этапами

В примерах рассматривается случай изменения задания, отправленного заданным этапом.

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

  1. Как найти отправленное заданным этапом задание?

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

  2. Изменить найденное задание.

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

Изменение заданий, отправляемых самим этапом

В примере рассматривается изменение задания, отправляемого самим этапом. В типовом решении к таким этапам относятся все этапы, кроме этапа “Типовая задача”.

Для упрощения работы с примером, задание будет отправляться и изменяться во вторичных процессах. Изменять задание можно и в расширении на сохранение карточки или задания.

Warning

Для работы примера необходимо в карточке настроек типового решения на вкладке Дополнительно в таблице Расширенные настройки типов заданий, используемых в подсистеме маршрутов указать тип задания TestTask1.

  1. Пример вторичного процесса “Пример изменения заданий, отправляемых самим этапом. Создание задания”.

    1. Режим: Кнопка.
    2. Асинхронный: Да.
    3. Добавить этап “Типизированное задание”.

      1. Задать тип задания: TestTask1.

      2. Задать сценарий инициализации:

        var card = await this.GetCardObjectAsync();

        if (card is null) { return; }

        card.Info["StageFlag"] = BooleanBoxes.True;

  2. Пример вторичного процесса “Пример изменения заданий, отправляемых самим этапом. Модификация задания”.

    1. Асинхронный: Нет.
    2. Режим: Действие.
    3. Тип события: Перед созданием задания.
    4. Добавить этап “Сценарий”.

      1. Задать сценарий инициализации:

        var context = ((ICardStoreTaskExtensionContext) this.CardContext); var task = context.Task;

        if (task.TypeID != DefaultTaskTypes.TestTask1TypeID || task.State != CardRowState.Inserted) { return; }

        var stageFlag = context .Request .TryGetCard() ?.TryGetInfo() ?.TryGet<bool>("StageFlag") ?? false;

        if (stageFlag) { // Изменение созданного задания.

        (task.Settings ??= new())["TestData"] = BooleanBoxes.True; }

Изменение заданий, отправляемых этапом “Типовая задача”

В примере рассматривается изменение задания, отправляемого этапом “Типовая задача”. Обработчик этапа “Типовая задача” не отправляет задания. Он запускает процесс WfResolution и контролирует его выполнение. Это не позволяет, например, передать данные через Card.Info в расширение на сохранение созданного задания. Т.о. следующий сценарий инициализации работать не будет:

(await GetCardObjectAsync()).Info["StageFlag"] = true;

Рассмотрим способ передачи информации об этапе через IKrScope.

  1. Пример вторичного процесса “Пример изменения заданий, отправляемых этапом “Типовая задача”. Создание задания”.

    1. Режим: Кнопка.
    2. Асинхронный: Да.
    3. Добавить этап “Типовая задача”.

      1. Задать сценарий инициализации:

        this.KrScope.Info["ResolutionStageFlag"] = BooleanBoxes.True;

  2. Пример вторичного процесса “Пример изменения заданий, отправляемых этапом “Типовая задача”. Модификация задания”.

    1. Асинхронный: Нет.
    2. Режим: Действие.
    3. Тип события: Перед созданием задания.
    4. Добавить этап “Сценарий”.

      1. Задать сценарий инициализации:

        #using Tessa.Extensions.Default.Shared.Workflow.Wf

        var context = ((ICardStoreTaskExtensionContext) this.CardContext); var task = context.Task;

        if (task.ProcessKind != WfHelper.ResolutionProcessName || task.State != CardRowState.Inserted || task.TypeID != DefaultTaskTypes.WfResolutionTypeID && task.TypeID != DefaultTaskTypes.WfResolutionChildTypeID) { return; }

        var customData = this.KrScope.Info.TryGet<bool>("ResolutionStageFlag");

        if (customData) { // Изменение созданного задания.

        (task.Settings ??= new())["TestData"] = BooleanBoxes.True; }

Прочие примеры

Также в примерах доступны следующие, которые можно рассмотреть самостоятельно:

  • Вторичный процесс “Диалоги. Пример использования настройки ‘Сохранять файлы после завершения диалога’“.
  • Маршрут по карточке “Мероприятие”.

Установка примеров

Warning

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

Загрузите библиотеку примеров по ссылке RoutingSamples.zip.

Для ее установки нужно:

  • Установить библиотеки схемы ExamplesBase и RoutingSamples из папки Scheme.
  • Импортировать типы карточек из папки Types, представления из папки Views и рабочие места из папки Workplaces.
  • Установить библиотеку карточек RoutingSamples.jcardlib из папки Cards. Она включает в себя все необходимые маршруты, кнопки, шаблоны и подразделения.

Также, для корректной работы примеров после их импорта необходимо проверить некоторые условия и выполнить дополнительные настройки:

  • Убедиться, что сотрудник, от которого выполняются примеры - входит в какое-нибудь подразделение, и у этого подразделения задан руководитель. В сценариях прохождения примеров предполагается, что все роли выполняет один и тот же человек (для удобства и простоты), но, разумеется, можно включить любых пользователей в процесс.
  • Убедиться, что в справочнике сотрудников есть сотрудник Admin (с идентификатором 3db19fa0-228a-497f-873a-0250bf0a4ccb), который автоматически создается при установке системы на новую БД. При импорте некоторых объектов, таких как шаблоны карточек - он указан как владелец шаблона.
  • Проверить, что для типа карточки “Протокол” в настройках типового решения (Меню системы → Настройки → Типовое решение) и для типа документа “Служебная записка” (рабочее место Администратор → Документы и задания → Типы документов → Служебная записка) установлен флаг Использовать маршруты.
  • При импорте библиотеки карточек для примеров, создадутся несколько подразделений, которые используются в настройках маршрутов. Их можно не использовать, но тогда необходимо:

    • В карточке шаблона этапов “st: СЗ согласование” в этапе “Согласование с руководителем и фин. департаментом” вместо подразделения “Финансовый департамент” указать любое подразделение или роль, существующие в системе.
    • В карточке шаблона этапов “st: СЗ исполнение” в этапах “Исполнение финансовой СЗ” и “Исполнение обычной СЗ” указать любых исполнителей вместо указанных в них ролей “Департамент обеспечения” и “ДИТ”.
  • Добавить в карточку Настроек типового решения тип карточки “Мероприятие”, выставив настройки, как на рисунке ниже:

Настройка маршрутов пользователем

Пользователь может менять сформированный маршрут документа в пределах, разрешенных настройками маршрутов. Ему может быть доступно:

  • Добавление новых этапов в маршрут.
  • Изменение существующих этапов.
  • Изменение порядка этапов.
  • Пропуск этапов.

Изменение маршрута выполняется на вкладке Маршрут карточки документа. Чтобы определить, какие возможности есть у пользователя, система проверяет следующие правила:

  • Наличие права Редактирование маршрута согласно правилам доступа - для текущего типа и состояния карточки. Обратите внимание, что для объектов в состоянии отличном от “Проект”, необходимо сначала нажать тайл Редактировать. Если права Редактирование маршрута у пользователя нет - никакие возможности изменения маршрута не будут доступны. Если есть, то появляются описанные далее возможности.
  • В настройках группы этапов может быть указано, что группа нередактируемая. Тогда пользователь не сможет добавлять новые этапы в эту группу и не сможет поменять настройки или порядок существующих этапов.
  • Если в настройках группы этапов указано, что группа редактируемая, то пользователь может добавить в эту группу новые этапы, согласно настройкам в справочнике настроек типового решения (см. далее).
  • Если в настройках группы указано, что группа редактируемая, то возможность редактирования или изменения порядка этапов, заданных в шаблонах этапов, будет зависеть от настроек, заданных в шаблоне этапов.
  • В рамках шаблона этапов Администратор системы может выдать права на редактирование этапов данного шаблона, а также права на перемещение этапов.
  • Для этапа в шаблоне этапов можно выставить флаг Разрешен пропуск, в комбинации с флагом Пропуск этапов в правилах доступа, данные настройки позволяют пользователю пропускать (а для пользователя визуально - удалять) этапы в автоматически сформированном маршруте.

Справочник настроек этапов маршрута

Этот справочник позволяет настроить - каким пользователям в какие группы этапов и что (какие этапы) можно добавлять. Например, логично разрешить в группу этапов “Согласование” добавлять только этапы согласования. Редактировать справочник может только администратор.

Справочник расположен в карточке настроек типового решения (Меню системы → Настройки → Типовое решение), вкладка Дополнительно, таблица Ограничения при добавлении.

Каждая строка в справочнике задает одно правило. В правиле можно указать:

  • Типы документов - для каких типов документов работает правило.
  • Группы этапов - в какие группы этапов будет разрешено добавлять этапы. Пользователь увидит эти группы этапов в диалоге добавления этапа.
  • Типы этапов - какие типы этапов разрешено добавлять в указанные выше группы. Пользователь увидит список этих типов этапов в диалоге добавления этапа.
  • Роли - любые роли в системе, кроме контекстных. Это поле определяет, кому именно разрешено добавлять указанные выше типы этапов. Если пользователь входит хотя бы в одну из перечисленных тут ролей, данное правило будет для него работать.

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

Tip

Диалог добавления этапов использует два представления KrFilteredStageGroups, KrFilteredStageTypes для получения списка доступных пользователю групп и типов этапов. Их можно поменять для получения какой-то своей собственной логики выбора.

Настройка маршрутов администратором

Различные объекты подсистемы маршрутов доступны администратору системы в рабочем месте Администратор в папке Маршруты.

Карточка “Группа этапов”

Группа этапов объединяет несколько связанных по смыслу шаблонов этапов в группу маршрута. Обычно группы представляет крупные части маршрута, например “Подготовка”, “Согласование” или “Исполнение”.

Создать карточку группы этапов можно через меню системы Создать карточку → Маршруты → Группа этапов или нажав на кнопку + Создать в верхней правой части представления с шаблонами этапов.

Поля карточки группы этапов делятся на следующие блоки:

Основная информация:

  • Название - название карточки для отображения в списках.
  • Описание - подробный комментарий к группе.
  • Порядок - целое число, которое определяет положение данной группы в общем маршруте. Должно быть уникальным. Система при построении маршрута упорядочивает группы именно по этому числу.
  • Все этапы нередактируемые - если флаг установлен, то пользователь при работе с маршрутом на вкладке Маршрут карточки документа не сможет менять этапы в этой группе.
  • Игнорировать при пересчёте - если флаг установлен, данная группа этапов будет игнорироваться при пересчёте (т.е. отключена).
  • Вторичный процесс - ссылка на тайл процесса, с которым связана группа. Если ссылка установлена, то группа не попадает в основной маршрут карточки. Она будет подставлена в маршрут, выполняемый по нажатию соответствующего тайла. С одним тайлом может быть связано сколько угодно групп.

Ограничения при пересчёте:

  • Типы - перечисление типов документов или карточек, в маршрут которых может быть подставлена данная группа. Если не указаны, то для всех типов. Если группа связана с глобальным тайлом, то значение этого поля игнорируется. Наравне с одиночными значениями для выбора доступны группы ссылок с типом “Тип документа”.
  • Роли - группа будет подставлена в маршрут, если текущий пользователь (который нажимает тайл или запускает процесс) входит в любую из указанных ролей. Если роли не указаны, они не проверяются.

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

Построение маршрута - в данной группе находятся условия и сценарии, выполняемые в момент построения маршрута.

  • На вкладке Условие можно задать условие, которое определяет включение этой группы в маршрут.
  • SQL условие - позволяет задать условие подстановки группы в маршрут при помощи sql-скрипта. Вычисляется при построении маршрута.

    Запрос должен возвращать ноль или одну строку и строго одну колонку. Истинным значением считается запрос, возвращающий 1. Ложным значением считается запрос, вернувший 0 строк или строку со значением 0 или NULL. Запрос, возвращающий более одной строки и более одного столбца, является некорректным.

    В запросе доступны следующие плейсхолдеры:

    • #user_id - идентификатор текущего пользователя.
    • #user_name - имя текущего пользователя.
    • #card_id - идентификатор карточки, для которой производится расчет.
    • #card_type_id - идентификатор типа карточки, для которой производится расчет.
    • #doc_type_id - идентификатор типа документа текущей карточки или значение null, он не задан для карточки.
    • #type_id - идентификатор типа документа текущей карточки, если он не известен, то идентификатор типа карточки.
    • #doc_state - целое число, идентификатор состояния текущей карточки.
    • #stage_group_id - идентификатор текущей группы.
  • Условное выражение - позволят задать условие подстановки группы в маршрут по правилам написания логических выражений языка C#. Доступные в контексте поля и объекты описаны в разделе Особенности работы сценариев и рекомендации по их использованию. Чаще всего используется объект Tessa.Cards.Card, возвращаемый методом IKrScript.GetCardObjectAsync(), через который можно проверить (а в обычных сценариях и поменять) данные текущей карточки.

  • Инициализация - это сценарий, выполняемый перед построением маршрута.
  • Постобработка - это сценарий, выполняемый после того, как маршрут построен.

Выполнение маршрута - в этой группе можно задать условия и сценарии, которые выполняются при выполнении маршрута.

  • На вкладке Условие можно задать условие, которое определяет, выполнится ли эта группа, когда маршрут до нее дойдет.
  • SQL условие - условие можно задать в форме запроса SQL.
  • Условное выражение - в этом поле можно задать условие в синтаксисе C#.
  • Инициализация - это сценарий, выполняемый перед выполнением этапов группы.
  • Постобработка - это сценарий, выполняемый после того, как этапы группы выполнены.

Порядок построения маршрута и выполнения сценариев и проверки условий описан в данном разделе. Подробно про написание условий и сценариев для объектов маршрута рассказано в данном разделе.

Карточка “Шаблон этапов”

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

Список всех шаблонов этапов можно найти в представлении Администратор -> Маршруты -> Шаблоны этапов. Новая карточка шаблона этапов создается из меню системы Создать карточку → Маршруты → Шаблон этапов, или же кнопкой + Создать в верхней правой части представления.

В карточке шаблона этапов следующие вкладки с настройками:

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

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

    • В начале группы - этапы этого шаблона в маршруте документа будут всегда в начале своей группы. Добавленные пользователем вручную этапы будут всегда идти после них.
    • В конце группы - этапы из этого шаблона в карточке документа фиксируются в конце своей группы и, даже если пользователь после пересчёта вручную будет добавлять новые этапы, они добавятся не в конец списка (как это привычно), а будут расположены в списке перед этапами из шаблона.
  • Порядок - номер порядка для данного шаблона. Актуально, если есть несколько шаблонов с одинаковыми настройками, тогда этапы из этих шаблонов будут добавляться в указанном порядке, т.е.: сначала этапы из шаблона с порядком 0, потом из шаблона с порядком 1 и т.д.

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

    • Шаблон 1: положение - в конце группы, порядок = 0, можно перемещать = нет;
    • Шаблон 2: положение - в конце группы, порядок = 1, можно перемещать = нет.

    Пересчитываем маршрут в карточке договора и в результирующем маршруте порядок этапов такой:

    • Этап, добавленный вручную.
    • Шаблон 1.
    • Шаблон 2.

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

    Однако, если в Шаблоне 2 выставить флаг Можно перемещать и пересчитать маршрут в карточке договора, можно увидеть, что результирующий маршрут изменился:

    • Этап, добавленный вручную.
    • Шаблон 2.
    • Шаблон 1.

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

    1. В начале группы и нельзя менять порядок
    2. В начале группы и можно менять порядок
    3. Этапы, добавленные пользователем вручную
    4. В конце группы и можно менять порядок
    5. В конце группы нельзя менять порядок

    В пределах каждой подгруппы этапы сортируются по значению поля Порядок.

  • Этапы нередактируемые - при выставленном флаге сотрудник не сможет редактировать параметры этапов, которые были добавлены в карточку документа автоматически на основании данного шаблона (даже если у сотрудника, в соответствии с настроенными правилами доступа, есть разрешение на редактирование маршрута). Администратору также будет недоступно редактирование таких этапов в карточке документа.

  • Можно перемещать - при выставлении флага сотрудник сможет перемещать этапы, которые были добавлены в карточку документа автоматически из данного шаблона (при наличии прав доступа на редактирование маршрута).

    Warning

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

  • Группа - группа, в которую входит этап. Каждый этап должен входить в группу.

  • Типы - список типов карточек, для которых данный шаблон этапов включается в маршрут. Если поле не заполнено, то данный шаблон будет действовать для всех типов документов. Наравне с одиночными значениями для выбора доступны группы ссылок с типом “Тип документа”.
  • Список ролей - список ролей, которым будет доступен данный шаблон этапов. Т.е. только для указанных сотрудников при расчете маршрута или его части будут подставляться этапы из данного шаблона (при выполнении всех других условий шаблона). Если поле не заполнено, то данный шаблон будет действовать для всех пользователей.

    В поле можно указать как конкретных сотрудников, так и роли или подразделения.

SQL-условие - условие, задаваемое через SQL-запрос. Вычисляется при построении маршрута.

Запрос должен возвращать ноль или одну строку и строго одну колонку. Истинным значением считается запрос, возвращающий 1. Ложным значением считается запрос, вернувший 0 строк или строку со значением 0 или NULL. Запрос, возвращающий более одной строки и более одного столбца, является некорректным.

В запросе доступны следующие плейсхолдеры:

  • #user_id - идентификатор текущего пользователя.
  • #user_name - имя текущего пользователя.
  • #card_id - идентификатор карточки, для которой производится расчет.
  • #card_type_id - идентификатор типа карточки, для которой производится расчет.
  • #doc_type_id - идентификатор типа документа текущей карточки или значение null, он не задан для карточки.
  • #type_id - идентификатор типа документа текущей карточки, если он не известен, то идентификатор типа карточки.
  • #doc_state - целое число, идентификатор состояния текущей карточки.
  • #stage_template_id - идентификатор текущего шаблона этапов.
  • #stage_group_id - идентификатор текущей группы.
  • #stage_type_id - идентификатор типа этапа.

Условное выражение. Пишется по правилам написания логических выражений языка C#. Доступные в контексте поля и объекты описаны в разделе Особенности работы сценариев и рекомендации по их использованию. Чаще всего используется объект Tessa.Cards.Card, возвращаемый методом IKrScript.GetCardObjectAsync(), через который можно проверить (а в обычных сценариях и поменять) данные текущей карточки.

Инициализация - при построении маршрута система сначала выполняет эти сценарии для всех подходящих по типу документа и роли шаблонов, а уже затем начинает вычислять условия для включения этапов в маршрут. На данном этапе можно выполнять сложные проверки и, при необходимости, отменить пересчёт и выдать сообщение об ошибке.

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

Порядок построения маршрута и выполнения сценариев и проверки условий описан в данном разделе. Подробно про написание условий и сценариев для объектов маршрута рассказано в данном разделе.

Вкладка Маршрут:

На вкладке настраиваются этапы, которые будут подставлены в маршрут документа при выполнении всех условий данного шаблона.

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

Доступные типы этапов описаны в разделе Типы этапов.

Вкладка Результат компиляции.

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

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

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

    Note

    При компиляции не выполняется проверка SQL запросов.

Карточка “Вторичный процесс”

При помощи карточки “Вторичный процесс” можно описать новый процесс, который можно запускать в карточке независимо от основного, отображенного на вкладке Маршрут, или глобально, т.е. вне контекста карточки. Такой маршрут может выполнять любые действия - управлять основным процессом (отозвать, выполнить переход и т.п.), манипулировать данными текущей карточки, запускать новые процессы, отправлять задания и так далее.

Вторичный процесс поддерживает несколько режимов:

  • Простой процесс - процесс, который можно запускать в расширениях или скриптах.
  • Кнопка - процесс, запускаемый по кнопке в меню системы.
  • Действие - процесс, запускаемый по какому-либо событию.

Основные настройки и выбор режима:

  • Название - название карточки, которое будет отображаться в представлении и ссылках на вторичный процесс.
  • Описание - подробное описание нюансов этого вторичного процесса. Полезно для комментирования.
  • Режим - выбор режима вторичного процесса. В зависимости от режима отображаются специфичные настройки, описанные ниже.
  • Глобальный - флаг, определяющий, выполняется ли данный процесс в контексте карточки. Если процесс глобальный, то в контексте отсутствует карточка. Глобальные процессы могут быть только синхронными.
  • Асинхронный - если маршрут, связанный с вторичным процессом, асинхронный, т.е. отправляет задания или выполняет какие-то другие асинхронные этапы, то необходимо ставить этот флаг. Синхронные процессы строятся и выполняются целиком в памяти, это быстрее и эффективнее, но не позволяет отправлять задания в рамках процесса.
  • Не отображать сообщение при отсутствии доступных для выполнения этапов - флаг, определяющий, отображение сообщения вида “В маршруте отсутствуют этапы, выполняемые при запуске процесса” при отсутствии этапов доступных для выполнения.

Сообщение при недоступности для выполнения - сообщение, которое выводится пользователю, если проверка при запуске процесса выполнилась неуспешно. При запуске процесса проверяется тип карточки (поле Типы), состояние карточки (поле Состояния карточек), различные роли (поля Роли, Контекстные роли) и сценарии из группы Дополнительные настройки выполнения (SQL условие и условное выражение C#).

Сообщение может содержать плейсхолдеры `{0}` и `{1}`, которые будут заменены на название и идентификатор вторичного процесса. Например, _Выполнить действие "{0}" может только инициатор процесса. Обратитесь к Васильеву В.В._.

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

  • Типы - для каких типов карточки или документа данный процесс можно запускать. Применимо только к контекстным вторичным процессам и игнорируется для глобальных. Наравне с одиночными значениями для выбора доступны группы ссылок с типом “Тип документа”.
  • Роли - текущий пользователь должен входить в одну из этих ролей, чтобы запустить процесс. Доступны только роли, имеющие постоянный состав: сотрудник, подразделение, статическая, динамическая и умная роль. Позволяет ограничить видимость тайла. Проверки контекстных ролей, например “Инициатор”, выполняются при запуске процесса (см. поле Доступно ролям). Это сделано для того, чтобы гарантировать быстрое открытие карточки или клиента. Вычисление контекстных ролей может занимать какое-то время и замедлять открытие карточки. Выполнять их каждый раз при открытии неэффективно. Если поле не заполнено, то данный шаблон будет действовать для всех пользователей.
  • Состояния карточек - в каких состояниях карточек процесс доступен для запуска (видима кнопка). Применимо только к контекстным процессам и игнорируется для глобальных. Наравне с одиночными значениями для выбора доступны группы ссылок с типом “Состояние документа”.
  • Доступно ролям - список ролей, которые будут вычислены на сервере при нажатии тайла и система проверит, что пользователь входит хотя бы в одну из них.

Группы этапов вторичного процесса - список, показывающий все группы, относящиеся к данному вторичному процессу. Список является неизменяемым, вторичный процесс для группы устанавливается в настройках карточки группы.

Режим Простой процесс

  • Разрешить запуск в клиентском приложении - простой процесс может быть запущен в клиентском коде. Проверка ограничений будет выполнена.
  • Проверять ограничения при пересчёте - необходимо ли проверять ограничения, указанные в блоке Ограничения при пересчёте. Настройка актуальна, только если запуск с клиента запрещен.

Режим Кнопка

  • Текст плитки - текст на тайле, который увидит пользователь. Допускается использовать строки локализации и их комбинации.
  • Включить в группу - название группы, в которую будет помещен этот тайл. Можно указать одинаковое название группы в нескольких тайлах и все они будут в одной группе. Поддерживается только один уровень вложенности. Можно использовать локализацию.
  • Значок - алиас иконки для этого тайла. Доступные иконки можно найти в файлах png в архиве с релизом платформы, в папке Misc\Icons.
  • Сочетание клавиш - горячие клавиши, при нажатии на которые происходит выполнение действия тайла.
  • Порядок - определяет порядок сортировки тайлов. Тайлы сортируются в порядке возрастания номера.
  • Текст подтверждения - вопрос, который нужно задать пользователю. Подтверждение будет показано, только если установлен флаг Спрашивать подтверждение.
  • Всплывающая подсказка - подсказка, которую увидит пользователь, если задержит мышь на тайле на полсекунды.
  • Группировать в “Действия” - тайл (вместе с группой, если она задана), будет отображаться в группе Действия меню системы. Применимо только для контекстных тайлов.

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

  • Дополнительные настройки видимости - SQL условие и условное выражение C# определяющие видимость тайла вторичного процесса.

Режим Действие

  • Тип события - событие, по которому будет запущен маршрут. Доступны следующие события:

    • Создание карточки - запуск маршрута при создании карточки.

      Аналогично методу расширения CardNewExtension.AfterRequest.

      Тип значения свойства IKrScript.CardContext: ICardNewExtensionContext.

      Созданную карточку можно получить следующим образом: IKrScript.GetCardObjectAsync().

    • Перед сохранением карточки - запуск маршрута перед сохранением карточки.

      Аналогично методу расширения CardStoreExtension.BeforeRequest.

      Тип значения свойства IKrScript.CardContext: ICardStoreExtensionContext.

      Карточку можно получить следующим образом: IKrScript.GetCardObjectAsync(). В пакете карточки присутствуют только изменения.

      Данный тип события может быть полезен для проверок и дополнительной валидации данных.

    • Сохранение карточки - запуск маршрута при сохранении карточки.

      Аналогично методу расширения CardStoreExtension.BeforeCommitTransaction.

      Тип значения свойства IKrScript.CardContext: ICardStoreExtensionContext.

      Карточку можно получить следующим образом: IKrScript.GetCardObjectAsync(). Выполнение указанного метода приведёт к загрузке карточки, если она до этого не выполнялась.

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

    • Перед завершением задания - запуск маршрута при завершении задания (выборе одного из варианта завершения, в т.ч. с выставленным флагом Не удалять задание).

      Аналогично методу расширения CardStoreTaskExtension.StoreTaskBeforeRequest.

      Тип значения свойства IKrScript.CardContext: ICardStoreTaskExtensionContext.

      Получить задание можно следующим образом:

      var task = ((ICardStoreTaskExtensionContext) this.CardContext).Task;

      Карточку можно получить следующим образом: IKrScript.GetCardObjectAsync(). В пакете карточки присутствуют только изменения.

    • Завершение задания - запуск маршрута при завершении задания (выборе одного из вариантов завершения, в т.ч. с выставленным флагом Не удалять задание).

      Аналогично методу расширения CardStoreTaskExtension.StoreTaskBeforeCommitTransaction.

      Тип значения свойства IKrScript.CardContext: ICardStoreTaskExtensionContext.

      Получить задание можно следующим образом:

      var task = ((ICardStoreTaskExtensionContext) this.CardContext).Task;

      Карточку можно получить следующим образом: IKrScript.GetCardObjectAsync(). Выполнение указанного метода приведёт к загрузке карточки, если она до этого не выполнялась.

    • Перед созданием задания - запуск маршрута при создании задания.

      Аналогично методу расширения CardStoreTaskExtension.StoreTaskBeforeRequest.

      Получить задание можно следующим образом:

      var task = ((ICardStoreTaskExtensionContext) this.CardContext).Task;

      Карточку можно получить следующим образом: IKrScript.GetCardObjectAsync(). В пакете карточки присутствуют только изменения.

      В данном событии можно, например, изменять создаваемое задание.

    • Создание задания - запуск маршрута при создании задания.

      Аналогично методу расширения CardStoreTaskExtension.StoreTaskBeforeCommitTransaction.

      Получить задание можно следующим образом:

      var task = ((ICardStoreTaskExtensionContext) this.CardContext).Task;

      Карточку можно получить следующим образом: IKrScript.GetCardObjectAsync(). Выполнение указанного метода приведёт к загрузке карточки, если она до этого не выполнялась.

  • Запускать один раз за запрос — флаг, определяющий, должен ли процесс быть выполнен только один раз при обработке события заданного типа.

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

Далее следуют скрипты, определяющие возможность выполнения процесса, а также видимости кнопки (если для вторичного процесса указан режим Кнопка).

  • SQL условие - запрос, выполняемый при расчете видимости тайла или выполнения вторичного процесса. Запрос должен возвращать ноль или одну строку и строго один столбец. Истинным значением считается запрос, возвращающий 1. Ложным значением считается запрос, вернувший 0 строк или строку со значением 0 или NULL. Запрос, возвращающий более одной строки и более одного столбца, является некорректным.

    Список доступных для всех видов процессов плейсхолдеров:

    • #user_id - идентификатор текущего пользователя.
    • #user_name - имя текущего пользователя.
    • #button_id - идентификатор карточки, текущего вторичного процесса.

    Следующие плейсхолдеры доступны только в контекстных процессах:

    • #card_id - идентификатор карточки, для которой производится расчет.
    • #card_type_id - идентификатор типа карточки, для которой производится расчет.
    • #doc_type_id - идентификатор типа документа текущей карточки или значение null, он не задан для карточки.
    • #type_id - идентификатор типа документа текущей карточки, если он не известен, то идентификатор типа карточки.
    • #doc_state - целое число, идентификатор состояния текущей карточки.
  • Условное выражение - условное выражение в синтаксисе C#. Если истинно, то тайл будет виден или процесс запущен. Например, тайл, который виден, если сумма договор больше 100000.

    (await GetCardAsync()).DocumentCommonInfo.Amount > 100000

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

Стоит обратить внимание, что сценарии предназначены именно для проверки видимости или возможности выполнения процесса. Если требуется по нажатию на тайл выполнить какой-то сценарий, правильнее сделать маршрут из одного этапа “Сценарий” и выполнять его по нажатию тайла.

Карточка “Метод расширения”

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

Новая карточка метода расширения создается из меню системы Создать карточку → Маршруты → Метод расширения или кнопкой + Создать из представления Администратор → Маршруты → Методы расширений.

Описание полей основной вкладки карточки:

  • Название - уникальное название карточки метода расширения.
  • Описание - описание карточки, указывается при необходимости.
  • Тело метода - поле для написания кода данного метода.

Система объединяет все карточки методов расширений в один класс, методы и свойства которых затем доступны из любых сценариев подсистемы маршрутов.

Ниже пример метода расширения, который определяет константу с телом письма и вспомогательный метод отправки уведомления указанного формата.

#using System.Threading; #using Tessa.Notices;

public const string MessageFormat = @" <html> <body> Это письмо предназначено для {0}. </body> </html> ";

public async Task SendNotificationExampleAsync(CancellationToken cancellationToken = default) { IMailService service = this.Resolve<IMailService>(MailServiceNames.WithoutTransaction);

var query = this.DbScope .BuilderFactory .SelectDistinct() .C("pr", "Email") .From("PersonalRoles", "pr").NoLock() .InnerJoin("RoleUsers", "ru").NoLock() .On().C("ru", "ID").Equals().C("pr", "ID") .InnerJoin("DocumentCommonInfo", "dci").NoLock() .On().C("dci", "AuthorID").Equals().C("ru", "ID") .Where() .C("dci", "ID").Equals().P("cardID") .And() .C("pr", "Email").IsNotNull() .Build();

this.Db.SetCommand(query, Db.Parameter("cardID", CardID)); var emails = await this.Db.ExecuteListAsync<string>(cancellationToken); Show(emails.Count.ToString()); foreach (var email in emails) { await service.PostMessageAsync(email, "Важное письмо", string.Format(MessageFormat, email), this.ValidationResult, cancellationToken: cancellationToken); } }

Вызвать такой метод из любого сценария можно так.

... await this.SendNotificationExampleAsync(this.CancellationToken); ...

Note

Отправлять уведомления лучше с использованием стандартного этапа “Отправка уведомления” и карточки “Уведомление” (см соответствующий раздел документации).

На вкладке Результат компиляции отображается информация (т.е. лог) по выполнению компиляции текущего метода и всех шаблонов и методов. Компиляцию можно выполнить, нажав на нужной вкладке кнопку Выполнить компиляцию или на кнопку Проверить скрипты, расположенную в меню системы (по данной кнопке выполняется компиляция всех шаблонов и методов).

После компиляции система выводит информационное сообщение аналогично, как при компиляции из карточки шаблона этапов.

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

Карточки маршрутов, входящие в типовую конфигурацию

В типовую конфигурацию TESSA входят карточки маршрутов, описанные в данном разделе.

Вторичные процессы:

  • Вернуть документ на доработку - кнопка для прерывания основного процесса и возврата в начало группы (в типовой конфигурации это формирование нового цикла согласования и отправка задания на доработку).
  • Ветка протокола - вторичный процесс, вызываемый из вторичного процесса “Разослать задачи по решениям”. Отправляет задачи по таблице Решения карточки протокола.
  • Запустить процесс - кнопка запуска основного процесса.
  • Запустить процесс по схеме согласования - кнопка запуска основного процесса с использованием схемы согласования.
  • Зарегистрировать документ - регистрирует документ, отзывает активные задания, выполняет переход на следующую группу - всё это выполняется в основном процессе.
  • Отменить процесс - кнопка для прерывания основного процесса и перехода в состояние “Отмена”.
  • Отменить регистрацию - кнопка отмены регистрации.
  • Отозвать процесс - кнопка для прерывания основного процесса и перехода в состояние “Проект”.
  • Разослать задачи по решениям - кнопка для запуска вторичного процесса рассылки задач по Протоколу.

Группы этапов:

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

Шаблоны этапов:

  • Возврат на доработку - шаблон этапов, обычно расположен в конце группы. Выполняет проверку, были ли отрицательные визы на каком-либо этапе Согласования или Подписания (или же в Схеме согласования) в текущей группе и если были, выполняет возврат в начало текущей группы.
  • Доработка - шаблон этапов, обычно расположен в начале группы (но после шаблона “Новая итерация согласования”), содержащий этап Доработки и после него этап очистки результатов предыдущего цикла на Схеме согласования (выполнится только в случае, если используется Схема согласования). Необходим для отправки задания доработки по документу в случае несогласования или неподписания документа.
  • Новая итерация согласования - шаблон этапов, обычно расположен в начале группы (перед шаблоном “Доработка”), необходим для корректной группировки записей в истории заданий по циклам, а именно для формирования нового цикла процесса в случае возврата на доработку.

Состояние процесса

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

Хранится состояние процесса в сериализованном в json виде в поле ApprovalCommonInfo.Info.

Например:

{ "Cycle::int":3, "CurrentPerformer::int":1, "TotalPerformers::int":1 }

Любой сценарий может обращаться к состоянию процесса, читать и писать туда значения в чрезвычайно простом синтаксисе.

{ // Добавим параметр "HasFinancialGroud" и установим ему значение ProcessInfo.HasFinancialGround = false

// Проверка значения if (ProcessInfo.HasFinancialGround == false) { ... } }

Состояние этапа и настройки этапа

Состояние этапа - это набор параметров, предназначенных для использования в качестве универсального хранилища любых данных, нужных при работе этапу процесса. Создается он в момент добавления этапа в маршрут и далее никогда не очищается. При этом, разумеется, если этап в какой-то момент был удален из маршрута, а потом добавлен заново - у него будет новое состояние. Как и состояние процесса, состояние этапа доступно из сценариев данного этапа (а при необходимости и из любых других сценариев маршрута) и предназначено для хранения информации, специфичной для конкретного этапа и его сценариев. Также, через состояние этапа он может обмениваться полезной информацией со сценариями в этом этапе. Состояние этапа хранится в сериализованном виде в json формате в поле KrStages.Info.

Например, этап создания карточки записывает идентификатор только что созданной карточки в состояние этапа в поле с именем cardID и сценарий постобработки может обратиться к этой информации:

// Выведем идентификатор созданной карточки в отладочное сообщение. Show((Guid)StageInfo.cardID);

Настройки этапа - это набор параметров этапа, которые доступны в пользовательском интерфейсе. Абсолютно все поля и параметры, которые там можно задать - хранятся в настройках этапа. Как и состояние, настройки этапа доступны для чтения и изменения любым сценариям. Типичное их использование - это в сценарии инициализации динамически рассчитать и задать какие-то параметры этапа, которые было невозможно сразу задать в пользовательском интерфейсе. Изменять можно абсолютно все параметры, которые видны в пользовательском интерфейсе этапа.

Вот пример сценария, который меняет текст задания перед его отправкой в этапе “Задача”.

Stage.Settings.KrResolutionSettingsVirtual__Comment = "Не забудьте приложить файл.";

В базе данных настройки этапа тоже хранятся в сериализованном в json виде в поле KrStages.Settings.

Note

Чтобы узнать, как называется тот или иной параметр, необходимо поменять его в интерфейсе этапа, закрыть форму этапа и нажать Ctrl+G для просмотра структуры изменённой карточки. На изображении ниже приведен пример того, что можно увидеть, если изменить состояние флага Отдельная задача каждому исполнителю в этапе Задача. В настройках этот флаг доступен по имени KrResolutionSettingsVirtual__MassCreation.

Important

Некоторые из настроек доступны не в объекте Stage.Settings, а напрямую в текущем контексте. Например, чтобы изменить срок задания, можно написать просто TimeLimit = 3;. Подробности описаны в следующем разделе.

Особенности работы сценариев и рекомендации по их использованию

Сценарии в системе маршрутов могут быть следующие:

  • В тайле можно задать сценарий (условие) видимости и сценарий, который выполняется при нажатии на тайл.

Сценарии, выполняемые при построении маршрута:

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

Сценарии, выполняемые при прохождении маршрута:

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

Все сценарии выполняются на серверной стороне.

Порядок построения маршрута, выполнения сценариев и проверки условий описан в разделе Виды процессов маршрутов, расчет маршрута и его выполнение.

Warning

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

Можно выделить следующие основные рекомендации и нюансы работы сценариев.

Сценарии, выполняемые при расчете маршрута:

  • Инициализация выполняется при построении маршрута для всех шаблонов перед проверками всех условий, Постобработка - после построения всего маршрута документа.

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

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

  • При расчете условий сначала выполняется Условное выражение, если оно успешно (или не задано), то после выполняется SQL-условие, и в случае, если и оно успешно (или не задано) - этапы из шаблона будут добавлены.

    Т.е. шаблон/группа “сработает” и добавит этапы в карточку документа только в случае успешного выполнения и C# условия, и SQL-условия или если данные поля (или поле) пустые.

  • Постобработка выполняется всегда, включая случаи, когда шаблон не подтвержден (т.е. если не выполнено C# или SQL условия). Это может использоваться для принятия каких-то решений в зависимости от подтверждения самого шаблона: если подтвержден - выполнить какое-то действие, если не подтвержден - другое.

Сценарии, выполняемые при проходе маршрута.

  • Сценарии Инициализации в этапах обычно используются для какой-то настройки параметров этапа. Например, программно вычислить срок задания.
  • Сценарии Постобработки в этапах удобно использовать для проверки результатов этапа. Некоторые этапы в состояние этапа записывают результаты своей работы, их можно как-то обработать. Можно проверить, что пользователь при завершении задания задал все нужные параметры в задании или карточке и выдать ошибку.
  • Сценарии Постобработки в этапах удобно использовать для проверки результатов этапа. Некоторые этапы в состояние этапа записывают результаты своей работы, их можно как-то обработать. Можно проверить, что пользователь при завершении задания задал все нужные параметры в задании или карточке и выдать ошибку.
  • Порядок расчета условий тот же, что и в дизайн-тайм условиях.

Сценарии в тайлах:

  • Сценарий видимости должен работать как можно быстрее. В нем запрещено выполнять какие-либо сложные или длительные действия, т.к. это влияет на скорость и даже возможность открытия карточки.
  • Сценарии проверки при нажатии предназначен для более сложных проверок, которые неоптимально делать при загрузке карточки. Но тем не менее, не стоит перегружать его функциональностью. Если нужно выполнить что-то сложное при нажатии на тайл - необходимо связать с тайлом маршрут и выполнить нужные вам действия в этапе “Сценарий” в этом маршруте.

В любой ситуации, если необходимо отменить текущую операцию (построение маршрута, запуск процесса, завершение этапа), следует выполнить сценарий примерно такого вида:

AddError("Пожалуйста, заполните категорию!");

Также все приведённые ниже свойства и методы описаны в интерфейсе IKrScript в расширениях типового решения в файле Source/Extensions/Tessa.Extensions.Default.Server/Workflow/KrCompilers/UserAPI/IKrScript.cs и в документации по API: IKrScript. Постобработка выполнения этапа выполняется как при нормальном завершении, так и при прерывании этапа. Чтобы отличать различные причины завершения этапа, можно использовать следующий код:

if (Stage.State == KrStageState.Inactive) { Show("Отозвано"); } else if (Stage.State == KrStageState.Skipped) { Show("Пропущено"); } else if (Stage.State == KrStageState.Completed) { Show("Завершено"); }

  • Отозвано может быть при отзыве/отмене.
  • Пропущено при регистрации с активным этапом.
  • Завершено при согласовании/несогласовании.

Написание сценариев для объектов маршрута

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

В скриптах, в зависимости от назначения скрипта, содержится информация о контексте его выполнения.

Для проверки скриптов на ошибки, необходимо нажать тайл Проверить скрипты в меню системы, сочетание клавиш Ctrl+Alt+B или нажать кнопку Выполнить компиляцию на вкладке Результат компиляции.

  • В случае успешной компиляции:

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

Warning

Если при попытке открыть любую карточку или запустить процесс появляется сообщение об ошибке “Сборка не найдена. Проверьте вывод компилятора на наличие ошибок компиляции.”, то для поиска точного местоположения ошибки необходимо перейти на вкладку Результат компиляции любой карточки подсистемы маршрутов, содержащей данную вкладку, а затем выбрать вложенную вкладку Все сценарии и нажать кнопку Выполнить компиляцию. Будет произведена компиляция всех скриптов в системе и выведены ошибки.

Ниже информация о свойствах контекста, которые доступны во всех скриптах:

Информация о выполняемом этапе

  • Stage (тип значения Stage) - объектная модель текущего выполняемого этапа. В ней содержится полная информация о текущем выполняемом этапе, включая его настройки. Более подробная информация об объекте этапа.
  • StageInfo (тип значения dynamic) - алиас для Stage.Info.

Информация о процессе

  • ProcessID (тип значения Guid) - идентификатор процесса. Используется только для асинхронных процессов.
  • ProcessTypeName (тип значения string) - тип процесса. Может принимать значения KrProcess и KrSecondaryProcess.
  • WorkflowProcess (тип значения WorkflowProcess) - объектная модель процесса. Более подробная информация об объекте процесса.
  • Stages (тип значения SealableObjectList<Stage>) - список этапов в процессе. Алиас для WorkflowProcess.Stages.
  • CurrentStages (тип значения Stage) - подмножество этапов в маршруте. В зависимости от контекста выполнения содержит разные выборки. Данный массив является неизменяемым, однако его элементы могут быть отредактированы.

    • Скрипт этапа - массив из одного элемента (текущий этап).
    • Скрипт шаблона этапов - массив из этапов текущего шаблона.
    • Скрипт группы этапов - массив из этапов текущей группы.
  • ProcessInfo (тип значения dynamic) - состояние процесса. Алиас для WorkflowProcess.Info.

  • GetCycleAsync() (тип возвращаемого значения int) и SetCycleAsync(int newValue) - методы, позволяющие получить или задать номер текущего цикла. Представляют собой типизированный интерфейс для получения/записи значения в ProcessInfo для основного процесса или для доступа к контекстуальному сателлиту, в котором хранится значение для остальных типов процессов. Важно отметить, что номер цикла хранится в состоянии основного процесса, однако доступ к номеру цикла может быть осуществлён и во вторичных процессах, что приводит к десериализации и сериализации состояния основного процесса. Поэтому обращение к номеру цикла вне основного процесса является дорогостоящей операцией и должно быть максимально сокращено.
  • Initiator (тип значения Author) - сотрудник, инициатор (автор) процесса.
  • InitiatorComment (тип значения string) - комментарий к циклу согласования, указанный в карточке.

Информация о выполняемом шаблоне

  • TemplateID (тип значения Guid) - идентификатор карточки шаблона этапа.
  • TemplateName (тип значения string) - название карточки шаблона этапа.
  • Order (тип значения int) - позиция карточки шаблона этапа.
  • Position (тип значения GroupPosition) - положение относительно этапов, добавленных вручную. Может принимать значения:

    • GroupPosition.AtFirst - для шаблонов в начале маршрута,
    • GroupPosition.AtLast - для шаблонов в конце маршрута.
  • CanChangeOrder (тип значения bool) - флаг Можно перемещать.

  • IsStagesReadonly (тип значения bool) - флаг Этапы нередактируемые.

Информация о карточке

Карточка:

  • GetCardObjectAsync() (тип значения Tessa.Cards.Card) - асинхронно возвращает объект карточки, содержащий идентификатор, секции и другую информацию. Для получения полей строковых секций удобно использовать метод GetCardAsync() (см. ниже).
  • CardID (тип значения Guid) - идентификатор карточки.
  • CardTypeID (тип значения Guid) - идентификатор типа карточки.
  • CardTypeName (тип значения string) - название типа карточки.
  • CardTypeCaption (тип значения string) - название типа карточки (отображаемое).
  • GetVersionAsync() (тип значения int) - асинхронно возвращает версию карточки.

Поля в карточке, файлы:

  • GetCardAsync() (тип значения dynamic) - представление строковых секций карточки посредством dynamic-полей (Tessa.Cards.CardTask.Card.DynamicEntries).

    Через данный метод удобно получать значения конкретных полей в строковых секциях карточки, например: (await GetCardAsync()).DocumentCommonInfo.Amount.

  • GetCardTablesAsync() (тип значения dynamic) - представление табличных секций карточки посредством dynamic-полей (Tessa.Cards.CardTask.Card.DynamicTables).

    Данный метод позволяет удобно получать строки из коллекционных секций, а также значения полей в строках, например: (await GetCardTablesAsync()).Recipients[0].UserID.

  • GetFilesAsync() (тип значения ListStorage<CardFile>) - асинхронно возвращает список файлов в карточке.

Задание:

  • CardTask - текущее завершаемое задание. Доступно, только если продвижение маршрута связано с завершением задания.

Сохранение, загрузка, валидация:

  • CardContext (тип значения: производные от ICardExtensionContext) - контекст сохранения или загрузки карточки, в зависимости от причины, инициировавшей выполнение скриптов.
  • ValidationResult (тип значения IValidationResultBuilder) - результат валидации.

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

  • Info (тип значения Dictionary<string, object>) - дополнительная структура данных, которую можно использовать для хранения полезной информации.

Зависимости

  • Session (тип значения ISession) - сессия текущего пользователя. Необходимо использовать Session.User.ID, чтобы получить идентификатор текущего пользователя.
  • Db (тип значения DbManager) - объект, используемый для выполнения SQL-запросов к текущей БД.

    • По умолчанию уже открыто соединение к основной БД системы, но посредством вызова using (DbScope.CreateNew("connectionAlias")) { ... } можно изменить базу данных, доступную по свойству Db.
    • Пример выполнения запроса: int result = await Db.SetCommand("select @Result", Db.Parameter("Result", 42)).LogCommand().ExecuteAsync&lt;int&gt;(CancellationToken);.
    • Следует учесть, что Db.Parameter("Result", 0) ведет себя нелогично и определит параметр типа nvarchar со значением DbNull, т.к. будет использована некорректная перегрузка метода Db.Parameter(). В связи с этим следует добавлять преобразование типа значения к object: Db.Parameter("Result", (object)0).
  • DbScope (тип значения IDbScope) - объект, обеспечивающий доступ к базам данных.

    • Позволяет открывать соединение к другим БД: await using (DbScope.CreateNew("connectionAlias")) { ... }.
    • Также определяет тип СУБД, которая используется системой: DbScope.Dbms.
    • Вместо вызова DbScope.Db для простоты рекомендуется использовать свойство Db, описанное выше.
  • UnityContainer (тип значения IUnityContainer) - IoC-контейнер для получения любых необходимых зависимостей в рамках системы. Для более удобного использования есть метод Resolve<T>(), о котором написано ниже.

  • CardMetadata (тип значения ICardMetadata) - содержит метаинформацию, необходимую для использования типов карточек совместно с пакетом карточек.
  • CardCache (тип значения ICardCache) - потокобезопасный кэш с карточками и дополнительными настройками.
  • KrTypesCache (тип значения IKrTypesCache) - кэш по типам карточек и документов, содержащих информацию по типовому решению.
  • KrScope (тип значения IKrScope) - объект, предоставляющий методы для работы с текущим контекстом подсистемы маршрутов, содержащим разделяемые карточки.

    • Exists (тип значения bool) - признак того, что в данный момент существует KrScope.
    • CurrentLevelID (тип значения Guid) - идентификатор текущего уровня вложенности.
    • GetMainCardAsync(Guid mainCardID, IValidationResultBuilder validationResult = default, bool withoutTransaction = default, CancellationToken cancellationToken = default) (тип значения Card) - асинхронно возвращает основную карточку из Scope. Разрешено использовать только в BeforeCommitTransaction или позже. При первом обращении карточка будет загружена полностью, далее ее объект будет кэширован и после завершения обработки автоматически сохранен.
    • GetKrSatelliteAsync(Guid mainCardID, IValidationResultBuilder validationResult = default, CancellationToken cancellationToken = default) (тип значения Card) - асинхронно возвращает основной сателлит Kr процесса. Рекомендуется использовать во всех расширениях на карточки, включенные в типовое решение, вместо явной загрузки через ICardRepository.
    • GetSecondaryKrSatelliteAsync(Guid processID, CancellationToken cancellationToken = default) (тип значения Card) - асинхронно возвращает сателлит вторичного процесса по идентификатору вторичного процесса.

Контроль выполнения шаблона

  • Confirmed (тип значения bool) - свойство, принимающее true, если этап был подтвержден (оба условия выполнились). Имеет смысл только в постобработке скриптов построения маршрута.
  • KrScriptType (тип значения KrScriptType) - свойство, описывающее текущее выполняемое действие. Может принимать следующие значения:

    • KrScriptType.Before
    • KrScriptType.Condition
    • KrScriptType.After
    • KrScriptType.ButtonVisibility
    • KrScriptType.ButtonExecution

Методы, доступные в контексте

  • CardRowsAsync(string sectionName) (тип значения ListStorage<CardRow>) - асинхронно возвращает строго типизированную коллекцию строк из секции основной карточки.

    Example

    foreach(var row in await CardRowsAsync("Recipients")) { ... }

  • IsMainProcess() (тип значения bool) - получить признак того, что текущий процесс является основным KrProcess.

    Example

    if (IsMainProcess()) { // Основной процесс. Маршрут отображается на вкладке "Маршрут", если она не скрыта. } else { // Вторичный процесс. }

  • IsMainProcessStartedAsync() (тип значения bool) - асинхронно возвращает признак, показывающий, что для текущей карточки запущен основной процесс (KrProcess).

  • RunNextStageInContextAsync(Guid cardID, bool wholeCurrentGroup = false, IDictionary<string, object> processInfo = null) - асинхронно выполнить следующий этап в контексте другой карточки. Данный метод имеет смысл только при выполнении маршрута. Если метод вызвать в скрипте инициализации, тогда текущий этап будет выполнен в другом контексте, иначе, если в постобработке, то следующий этап. Для карточки с идентификатором cardID будет запущен вторичный синхронный процесс, состоящий из текущего этапа или всех оставшихся этапов до конца текущей группы (wholeCurrentGroup == true). Для создаваемого синхронного процесса можно опционально передать ProcessInfo.
  • ContextChangePending() (тип значения bool) - возвращает признак того, что была запланирована смена контекста с помощью метода RunNextStageInContextAsync.
  • DoNotChangeContext() - отмена смены контекста.
  • Resolve<T>(string name = null) (тип значения T) - возвращает зависимость из IoC-контейнера с опциональным указанием имени (если зависимость является именованной, например, ICardRepository).

    Example

    var cardRepository = Resolve<ICardRepository>(CardRepositoryNames.Default);

  • AddStageAsync(string name, StageTypeDescriptor descriptor, int position) (тип значения Stage) - добавляет новый этап в маршрут с именем name и положением position. По умолчанию position - в конец.

    Особенности метода:

    • Если этап не был добавлен скриптом при предыдущих пересчётах, он будет создан с новым RowID.
    • Если этап был добавлен ранее, то RowID будет перенесен, но все значения изменены на стандартные.
    • Если этап был добавлен ранее и изменен пользователем, то возвращается null.
    • Можно использовать только в скрипте построения шаблона этапов.

      Example

      var stage = await AddStageAsync("ПримерЭтапа", StageTypeDescriptors.ApprovalDescriptor, 1);

      if(stage != null) { stage.Name = "Пример этапа"; } else { // При этом положение измененного пользователем этапа не специфицируется. // Для удержания этапа на том же месте необходимо использовать GetOrAddStageAsync. AddWarning("Этап изменен вручную"); }

  • GetOrAddStageAsync(string name, StageTypeDescriptor descriptor, int position) (тип значения Stage) - возвращает или добавляет этап к маршруту с указанным именем name, типом, описываемым через descriptor, и положением position. По умолчанию position - в конец.

    Особенности метода:

    • Если этап не был добавлен скриптом при предыдущих пересчётах, он будет создан с новым RowID.
    • Если этап был добавлен ранее, то RowID будет перенесен, но все значения изменены на стандартные.
    • Если этап был добавлен ранее и изменен пользователем, то возвращается этот этап.
    • Можно использовать только в скрипте построения шаблона этапов.

      Example

      var stage = await GetOrAddStageAsync("ПримерЭтапа", StageTypeDescriptors.ApprovalDescriptor, 1);

      // Даже если этап установлен пользователем, // его положение относительно других этапов из шаблона будет 1

      if(!stage.RowChanged) { stage.Name = "Пример этапа"; } else { AddWarning("Этап изменен вручную"); }

  • RemoveStage(string name) (тип значения bool) - удаляет этап из маршрута, добавленный через скрипт (доступен только в скрипте построения шаблона этапов).

  • SetSinglePerformer(Guid id, string name, Stage intoStage, bool ignoreManualChanges = false) - устанавливает исполнителя в этапе. Применимо только для типов этапов с одиночными исполнителями (доступно только в скрипте построения шаблона этапов).
  • SetSinglePerformer(string id, string name, Stage intoStage, bool ignoreManualChanges = false) - перегрузка для SetSinglePerformer(Guid, string, Stage, bool).
  • AddPerformer(Guid id, string name, Stage intoStage, int pos = int.MaxValue, bool ignoreManualChanges = false) (тип значения Performer) - добавляет исполнителя в этап intoStage на место position. По умолчанию в конец. Возвращает null, если этап изменен. Применимо только для типов этапов с множественными исполнителями (доступен в скрипте выполнения этапа и построения шаблона этапов).

    Example

    var stage = await AddStageAsync("ПримерЭтапа", StageTypeDescriptors.ApprovalDescriptor);

    if(stage != null) { var approver = AddPerformer(perfID, perfName, stage); }

  • AddPerformer(string id, string name, Stage intoStage, int pos = int.MaxValue, bool ignoreManualChanges = false) (тип значения Performer) - перегрузка для AddPerformer(Guid, string, Stage, int, bool).

  • RemovePerformer(Guid performerID, Stage stage, bool ignoreManualChanges = false) - удаляет исполнителя по идентификатору указанной роли для этапа с режимом множественных исполнителей.
  • RemovePerformer(string performerID, Stage stage, bool ignoreManualChanges = false) - перегрузка для AddPerformer(Guid, Stage, bool).
  • RemovePerformer(int index, Stage stage, bool ignoreManualChanges = false) - удаляет исполнителя, расположенного по указанному порядковому индексу для этапа с режимом множественных исполнителей.
  • ForEachStage(Action<CardRow> rowAction) - выполняет указанное действие над строкой (из коллекционной секции KrStages) этапа текущего процесса в обход объектной модели.

    Example

    ForEachStage(row => { ... });

  • ForEachStageInMainProcessAsync(Func<CardRow, Task> rowActionAsync, bool withNesteds = false) - асинхронно выполняет указанное действие над строкой (из коллекционной секции KrStages) этапа основного процесса карточки в обход объектной модели.

    Example

    await ForEachStageInMainProcessAsync(row => { ... });

  • SetStageStateAsync(CardRow stage, KrStageState stageStates) - асинхронно изменяет состояние этапа, заданного строкой секции карточки, а не объектной моделью. Полезно, когда нужно изменить состояние этапа из другого процесса.

    Example

    await ForEachStageInMainProcessAsync(row => SetStageStateAsync(row, KrStageState.Inactive));

  • AddTaskHistoryRecordAsync( Guid typeID, string typeName, string typeCaption, Guid optionID, string result = null, Guid? performerID = null, string performerName = null, int? cycle = null, Func<CardTaskHistoryItem, Task> modifyActionAsync = null) - асинхронно добавляет запись в текущую группу истории заданий.

  • AddTaskHistoryRecordAsync( Guid? taskHistoryGroup, Guid typeID, string typeName, string typeCaption, Guid optionID, string result = null, Guid? performerID = null, string performerName = null, int? cycle = null, int? timeZoneID = null, TimeSpan? timeZoneUTCOffset = null, Func<CardTaskHistoryItem, Task> modifyActionAsync = null) - асинхронно добавляет запись в указанную группу истории заданий.
  • Методы для вывода пользовательской информации в ValidationResult.

    • AddError(string text)
    • AddWarning(string text)
    • AddInfo(string text)
  • Методы для вывода отладочной информации в ValidationResult. При передаче одиночных объектов подробная информация выводится сразу, при передаче перечисления IEnumerable<T> подробная информация выводится в деталях ValidationResult.

    • Show(object obj)
    • Show(string message, string details)
    • Show(Stage stage)
    • Show(IEnumerable<Stage> stages)
    • Show(Performer approver)
    • Show(IEnumerable<Performer> approvers)

Подробнее об объектах для маршрута

Тип GroupPosition

Тип данных GroupPosition хранит информацию о значении поля Положение относительно этапов, добавленных вручную. В типе определено два свойства - ID и Name. Создавать новые объекты типа нельзя. Существует три предопределенных объекта:

Название
Идентификатор Имя
Unspecified null null
AtFirst 0 AtFirst
AtLast 1 AtLast

Тип WorkflowProcess

Класс содержит в себе полную информацию о текущем маршруте. Определение класса и полная информация о нем содержится в файле типового решения Source/Extensions/Tessa.Extensions.Default.Server/Workflow/KrObjectModel/WorkflowProcess.cs.

  • Author (тип значения Author) - автор (инициатор) основного процесса.

  • AuthorCurrentProcess (тип значения Author) - автор (инициатор) текущего процесса. При выполнении в основном процессе: возвращаемое значение соответствует значению, возвращаемому свойством Author; изменение свойства приводит к синхронному изменению свойства Author и наоборот.

  • ProcessOwner (тип значения Author) - владелец основного процесса.
  • ProcessOwnerCurrentProcess (тип значения Author) - владелец текущего процесса. При выполнении в основном процессе: возвращаемое значение соответствует значению, возвращаемому свойством ProcessOwner; изменение свойства приводит к синхронному изменению свойства ProcessOwner и наоборот.
  • AuthorComment (тип значения string) - комментарий к циклу согласования.
  • State (тип значения Tessa.Extensions.Default.Shared.Workflow.KrProcess.KrState) - состояние документа. Все стандартные состояния указаны в KrState статическими полями. При добавлении новых состояний в перечисление KrDocState с помощью редактора схемы для удобной работы в исходном коде с состоянием рекомендуется вынести новые состояния в отдельный статический класс в Shared-расширениях.

    Example

    public static class CustomDocStates { // Строка со значением ID = 1000 Name = "CustomState" добавлена в перечисление KrDocState // Использовать идентификаторы ниже 1000 крайне не рекомендуется во избежание конфликта с состояниями типового решения public static readonly KrState CustomState = new KrState(1000); }

    Теперь для изменения состояния карточки в скрипте достаточно:

    #using Tessa.Extensions.Shared.CustomHelpers WorkflowProcess.State = CustomDocStates.CustomState;

  • Stages (тип значения SealableObjectList<Stage>) - список этапов в маршруте. Более подробная информация об объекте этапа.

  • Info (тип значения dynamic) - состояние процесса. Персистентное хранилище ключ-значение, позволяющее хранить произвольные данные, полезные при выполнении процесса и любых скриптов в рамках процесса. Алиасом поля в объекте этапа является свойство ProcessInfo в контексте скрипта.

    Часто состояние процесса удобно использовать как общий буфер между этапами или даже группами. В Info можно записывать результат завершения какого-либо этапа, чтобы потом использовать этот результат в условии следующей группы.

    Example

    // Сценарий постобработки этапа ProcessInfo.StageResult = "Успешно";

    // ... // Условие группы ProcessInfo.StageResult == "Успешно" && ...

Тип Stage

Здесь перечислены основные свойства модели этапа. Определение класса и полная информация о нем содержится в файле типового решения Source/Extensions/Tessa.Extensions.Default.Server/Workflow/KrObjectModel/Stage.cs.

  • ID (тип значения Guid) - идентификатор этапа. Для шаблонных этапов это RowID этапа в шаблоне, а для этапов, добавленных вручную в карточке документа, это RowID строки в документе. Таким образом, при пересчётах и подстановках идентификатор строки будет сохраняться, что позволит использовать один и тот же идентификатор в скриптах.
  • StageTypeID (тип значения Guid) - идентификатор типа этапа. Каждый тип этапа описывается дескриптором, все дескрипторы стандартных типов этапов располагаются в Tessa.Extensions.Default.Shared.Workflow.KrProcess.StageTypeDescriptors.

    Example

    Stage.StageTypeID == StageTypeDescriptors.ApprovalDescriptor.ID

  • TemplateID (тип значения Guid) - идентификатор карточки шаблона этапа KrStageTemplate.

  • StageGroupID (тип значения Guid) - идентификатор карточки группы этапов KrStageGroup, к которой принадлежит текущий этап.
  • Name (тип значения string) - название этапа.
  • TimeLimit (тип значения double?) - срок выполнения этапа, указываемый в UI. Настройка доступна только для тех типов этапов, в дескрипторе которых UseTimeLimit выставлено в true.
  • Performer (тип значения Performer) - одиночный исполнитель этапа. Используется для тех типов этапов, в дескрипторе которых PerformerUsageMode выставлен в PerformerUsageMode.Single. Более подробная информация об объекте исполнителя.
  • Performers (тип значения ListStorage<Performer>) - список исполнителей этапа. Используется для тех типов этапов, в дескрипторе которых PerformerUsageMode выставлен в PerformerUsageMode.Multiple. Более подробная информация об объекте исполнителя.
  • Settings (тип значения dynamic) - настройки этапа, задаваемые через UI настройки. Набор настроек определяется структурой секций карточки настроек, связанной с типом этапа.

    Example

    Пример работы с настройками в Settings:

    // Название строковых полей формируется по шаблону "ИмяСекции__ИмяПоля" var comment = Stage.KrApprovalSettingsVirtual__Comment; comment = comment.Replace("пожалуйста", "немедленно"); Stage.KrApprovalSettingsVirtual__Comment = comment;

    // Название строковых секций образуется с использованием суффикса __Synthetic var firstRow = Stage.KrUniversalTaskOptionsSettingsVirtual__Synthetic[0];

  • Info (тип значения dynamic) - состояние этапа. Персистентное хранилище ключ-значение, позволяющее хранить произвольные данные, полезные при выполнении этапа и его скриптов. Алиасом поля в объекте этапа является свойство StageInfo в контексте скрипта.

    Example

    Для примера, будем хранить в Info количество выполнений этапа. В скрипте инициализации запишем:

    if (StageInfo.ExecutionCount == null) { StageInfo.ExecutionCount = 0; }

    StageInfo.ExecutionCount = StageInfo.ExecutionCount + 1;

    Затем, в сценарии постобработки этапа выведем это количество:

    if (StageInfo.ExecutionCount != null) { Show(StageInfo.ExecutionCount.ToString()); }

  • OrderChanged - признак того, что порядок менялся пользователем. Не зависит от изменения порядка в коде.

  • RowChanged - признак того, что этап менялся пользователем. Не зависит от изменений в коде.

Тип Performer

  • RowID (тип значения Guid) - RowID согласующего в таблице согласующих KrApprovers. Если согласующий попал в маршрут из шаблона, то RowID это ID для шаблонного согласующего. Если согласующий создан вручную, то RowID - это RowID для маршрута карточки.
  • ID (тип значения Guid) - идентификатор роли согласующего.
  • Name (тип значения string) - имя роли согласующего.
  • IsSql (тип значения bool) - признак того, что исполнитель подставлен через SQL запрос. Актуально только для множественных исполнителей.

Типы этапов

В этом разделе описаны все доступные “из коробки” типы этапов маршрута. Так как подсистема маршрутов расширяемая, то в проектной конфигурации могут быть добавлены новые типы этапов.

Общие настройки этапов

У всех этапов, независимо от типа, есть некоторые общие настройки (помимо названия). Все они описаны ниже.

  • Не показывать в маршруте - признак того, что в маршруте документа этап по умолчанию для пользователя не будет отображаться, даже если попадает в маршрут. Посмотреть скрытые этапы можно с помощью меню системы Другие → Показать скрытые этапы или с помощью сочетания клавиш Ctrl+Alt+H. Скрытые этапы будут выделены серым цветом в таблице сформированного маршрута.

  • Разрешён пропуск - признак того, что пользователь может пропускать данный этап в маршруте документа. Это делается путём нажатия кнопки Удалить, расположенной под таблицей этапов маршрута. При этом этап становится скрытым. Пропускать можно только неактивные этапы и если это разрешено правилами доступа (разрешение Пропуск этапов).

    Для активации пропущенного этапа необходимо в режиме отображения скрытых этапов выбрать нужный этап и нажать кнопку Активировать. Активировать этап можно только, если это разрешено правилами доступа (Разрешение Редактирование маршрута).

В блоке Дополнительно (в нижней части диалогового окна свойств этапа, по умолчанию свернут) следующие общие настройки:

  • Условие - тут можно либо в виде SQL запроса, либо в виде C# выражения (как на примере ниже) задать условие выполнения данного этапа. Если это условие не выполняется в момент, когда до этапа доходит выполнение маршрута, то этап будет пропущен.

    • SQL условие. Истинным значением считается запрос, возвращающий 1. Ложным значением считается запрос, вернувший 0 строк или строку со значением 0 или NULL.

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

      В запросе доступны следующие плейсхолдеры:

      • #user_id - идентификатор текущего пользователя.
      • #user_name - имя текущего пользователя.
      • #card_id - идентификатор текущей карточки.
      • #card_type_id - идентификатор типа текущей карточки.
      • #doc_type_id - идентификатор типа документа текущей карточки или значение null, если он не задан для карточки.
      • #type_id - идентификатор типа документа текущей карточки, если он не известен, то идентификатор типа карточки.
      • #doc_state - целое число, идентификатор состояния текущей карточки.
      • #stage_template_id - идентификатор текущего шаблона этапов.
      • #stage_rowid - идентификатор строки этапа в маршруте.
      • #stage_group_id - идентификатор текущей группы этапов.
      • #stage_type_id - идентификатор типа этапа.
    • Условное выражение. Пишется по правилам написания логических выражений языка C#. Доступные в контексте поля и объекты описаны в следующем разделе. Чаще всего используется объект Card, через который можно проверить (а в обычных сценариях и поменять) данные текущей карточки.

      Example

      Пример условия, проверяющего сумму договора.

      (await GetCardAsync()).DocumentCommonInfo.Amount > 100000

  • Инициализация. На этой вкладке задается сценарий, выполняемый перед выполнением этапа.

  • Постобработка. На этой вкладке задается сценарий, выполняемый после выполнения этапа.

    В сценарии постобработки можно получить завершаемое задание, обрабатываемое текущим этапом, следующими способами:

    1. Из карточки документа:

      var tasks = ((ICardStoreExtensionContext) this.CardContext).Request.Card.Tasks;

    2. Из свойства:

      var task = this.WorkflowTaskInfo.Task;

    3. Из состояния этапа.

      При завершении задания этап сохраняет копию завершаемого задания в коллекцию, расположенную в Stage.InfoStorage по ключу KrConstants.Keys.Tasks. Элемент коллекции – это словарь типа Dictionary&lt;string, object&gt;, являющийся хранилищем объекта CardTask.

      Example

      Пример получения задания из StageInfo.Tasks

      // Обратиться к конкретному элементу коллекции можно по его индексу, например: StageInfo.Tasks[i]

      // Если задание одно, в коллекции будет всегда один элемент. StageInfo.Tasks[0]

      По умолчанию сохраняется только основная информация по заданию. Не сохраняется информация о: CardTask.SectionRows, CardTask.Card, CardTask.Info. Для сохранения всей информации в сценарии инициализации этапа необходимо указать:

      this.Stage.WriteTaskFullInformation = true;

      Пример сохраняемых данных

      При Stage.WriteTaskFullInformation = false:

      { ".flags": 44052, ".state": 0, ".storedState": 1, "Action": 3, "AuthorID": "3db19fa0-228a-497f-873a-0250bf0a4ccb", "AuthorName": "Admin", "AuthorPosition": null, "Digest": "{$KrMessages_Stage}: Согласование", "GroupRowID": null, "HistoryItemParentRowID": null, "InProgress": "2021-06-22T15:04:49.433Z", "OptionID": "8cf5cf41-8347-05b4-b3b2-519e8e621225", "ParentRowID": null, "Planned": "2021-06-24T06:00:00Z", "PlannedQuants": 33, "PlannedType": 0, "PostponeComment": null, "Postponed": null, "PostponedTo": null, "ProcessID": null, "ProcessKind": null, "ProcessName": null, "Result": null, "RoleID": "3db19fa0-228a-497f-873a-0250bf0a4ccb", "RoleName": "Admin", "RoleTypeID": "929ad23c-8a22-09aa-9000-398bf13979b2", "RowID": "2f0cd55f-2cf5-42c0-8d24-8a27d2dd1fa8", "Settings": {}, "TimeZoneID": 0, "TimeZoneUtcOffsetMinutes": 180, "TypeCaption": "$CardTypes_TypesNames_KrApprove", "TypeID": "e4d7f6bf-fea9-4a3b-8a5a-e1a0a40de74c", "TypeName": "KrApprove", "UserID": "3db19fa0-228a-497f-873a-0250bf0a4ccb", "UserName": "Admin" }

      При Stage.WriteTaskFullInformation = true:

      { ".flags": 44052, ".state": 0, ".storedState": 1, "Action": 3, "AuthorID": "3db19fa0-228a-497f-873a-0250bf0a4ccb", "AuthorName": "Admin", "AuthorPosition": null, "Card": { "Created": "2021-06-22T15:02:17.03Z", "CreatedByID": "3db19fa0-228a-497f-873a-0250bf0a4ccb", "CreatedByName": "Admin", "Files": null, "Flags": 0, "ID": "7b2fe4eb-7942-4bef-85ec-602d6bd6b54b", "Info": null, "Modified": "2021-06-22T15:02:18.49Z", "ModifiedByID": "3db19fa0-228a-497f-873a-0250bf0a4ccb", "ModifiedByName": "Admin", "Permissions": { "CardPermissions": 87381, "FilePermissions": null, "Sections": null }, "Sections": { "KrAdditionalApproval": { "Fields": { "Comment": null, "FirstIsResponsible": false, "TimeLimitation": 1.0 } }, "KrAdditionalApprovalInfo": { ".table": 1, "Rows": null }, "KrAdditionalApprovalInfoVirtual": { ".table": 1, "Rows": [] }, "KrAdditionalApprovalUsers": { ".table": 1, "Rows": null }, "KrCommentators": { ".table": 1, "Rows": null }, "KrCommentsInfo": { ".table": 1, "Rows": null }, "KrCommentsInfoVirtual": { ".table": 1, "Rows": [] }, "KrTask": { "Fields": { "Comment": "Комментарий", "DelegateID": null, "DelegateName": null } }, "TaskCommonInfo": { "Fields": { "KindCaption": null, "KindID": null } } }, "TypeCaption": "$CardTypes_TypesNames_KrApprove", "TypeID": "e4d7f6bf-fea9-4a3b-8a5a-e1a0a40de74c", "TypeName": "KrApprove", "Version": 0 }, "Digest": "{$KrMessages_Stage}: Согласование", "GroupRowID": null, "HistoryItemParentRowID": null, "Info": {}, "InProgress": "2021-06-22T15:02:18.49Z", "OptionID": "8cf5cf41-8347-05b4-b3b2-519e8e621225", "ParentRowID": null, "Planned": "2021-06-24T06:00:00Z", "PlannedQuants": 33, "PlannedType": 0, "PostponeComment": null, "Postponed": null, "PostponedTo": null, "ProcessID": null, "ProcessKind": null, "ProcessName": null, "Result": null, "RoleID": "3db19fa0-228a-497f-873a-0250bf0a4ccb", "RoleName": "Admin", "RoleTypeID": "929ad23c-8a22-09aa-9000-398bf13979b2", "RowID": "7b2fe4eb-7942-4bef-85ec-602d6bd6b54b", "SectionRows": null, "Settings": {}, "TimeZoneID": 0, "TimeZoneUtcOffsetMinutes": 180, "TypeCaption": "$CardTypes_TypesNames_KrApprove", "TypeID": "e4d7f6bf-fea9-4a3b-8a5a-e1a0a40de74c", "TypeName": "KrApprove", "UserID": "3db19fa0-228a-497f-873a-0250bf0a4ccb", "UserName": "Admin" }

  • SQL исполнители. Для этапов, в которых есть список исполнителей (например, этап “Задача”), в этом поле можно написать sql-запрос, который будет выполнен для формирования списка исполнителей. Запрос выполнится непосредственно перед выполнением этапа. Также есть возможность смешивать вручную заданных исполнителей, подставив в нужное место исполнителей, рассчитанных через запрос.

    Warning

    Для вычисления SQL исполнителей используется скрипт, указанный в шаблоне этапа на момент выполнения скрипта.

    Запрос должен возвращать выборку, состоящую из двух столбцов: идентификатор и имя роли. В запросе доступны следующие плейсхолдеры:

    • #card_id - идентификатор карточки, для которой производится расчет.
    • #card_type_id - идентификатор типа карточки, для которой производится расчет.
    • #user_id - идентификатор текущего пользователя.
    • #user_name - имя текущего пользователя.
    • #stage_template_id - идентификатор текущего шаблона этапов.
    • #stage_template_name - название текущего шаблона этапов.
    • #stage_rowid - идентификатор строки этапа в таблице шаблона этапов, для которого вычисляются роли.

    Например, добавим этап, в котором укажем одного исполнителя, а также SQL запрос для вычисления исполнителей - запрос, вычисляющий всех пользователей и активных заместителей в подразделении “Финансовый департамент”:

    Вот какой результат возвращает запрос.

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

    Однако, при необходимости, можно указать положение вычисляемых исполнителей в этапе. Для этого в список исполнителей необходимо добавить служебную роль “Вычисляемые согласующие” нажатием на ссылку Добавить роль “Вычисляемые исполнители” под списком исполнителей. В список исполнителей добавится роль “Вычисляемые исполнители”. Любых других исполнителей можно добавить до и/или после этой роли.

    На место роли “Вычисляемые исполнители” будут подставлены исполнители, вычисленные в результате выполнения SQL запроса. Исполнители подставляются в том же порядке, в котором они возвращаются запросом.

Согласование

Этап согласования предназначен для отправки одного или нескольких заданий согласования.

Все возможности задания согласования описаны в Руководстве пользователя.

Настройки этапа:

  • Название этапа – название текущего этапа согласования.
  • Срок (рабочие дни) - срок для заданий согласования в рабочих днях. Срок можно задать и дробный, например 0,5 - половина рабочего дня (4 часа).
  • Дата выполнения - астрономическая дата выполнения задания. Можно указать либо это поле, либо Срок (рабочие дни).
  • Согласующие – согласующие текущего этапа. Можно указать как конкретных сотрудников, так и роли.

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

    • Исполнители для выбранного согласующего - список сотрудников или ролей, кому будет отправлено задание дополнительного согласования. Данные задания отправляются одновременно с родительским заданием согласования. Решения дополнительных согласующих заносятся в историю заданий и лист согласования, однако не влияют на итоговый результат согласования.
    • Первый исполнитель - ответственный - в случае, если флаг выставлен, то первый из указанных в списке Исполнителей будет считаться ответственным.

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

    Note

    Согласующий, для которого указаны дополнительные согласующие, отмечается в списке специальными символами (+) перед названием роли.

  • От имени (сотрудник или контекстная роль) - позволяет отправить задание от имени любого сотрудника. В отличие от отправки задачи по тайлу Поставить задачу, здесь можно выбрать абсолютно любого сотрудника, т.к. маршруты настраиваются администратором.

  • Вид - вид задания (отображается в виде заголовка в форме задания, также по виду возможна фильтрация в представлении Мои задания).
  • Комментарий - комментарий к текущему этапу согласования, он будет отображаться в сформированном исполнителю задании в качестве текста задания.
  • Вкладка Основные настройки:

    • Параллельный этап – флаг выставляется в случае, если текущий этап согласования должен проходить параллельно (актуально, если в поле Согласующие указано более одного согласующего).
    • Не возвращать на доработку - данный флаг отключает возврат на начало текущей группы этапов, выполняемый этапом “Согласование”. Для того, чтобы был выполнен возврат на доработку, при наличии несогласованных заданий согласования, в стандартную группу этапов “Согласование” включен шаблон этапов “Возврат на доработку”. В конце данного раздела есть примеры маршрутов согласования с использованием этого флага, где объясняется, как и в каких случаях ведёт себя процесс.

      Данной настройкой также можно управлять на уровне маршрута, в процессе выполнения, используя значение типа Nullable<bool> доступное по ключу Tessa.Extensions.Default.Shared.Workflow.KrProcess.KrConstants.Keys.NotReturnEdit в ProcessInfo. При расчёте итогового значения, значение из ProcessInfo объединяется по “И” со значением, указанным в настройках этапа. Если значение в ProcessInfo отсутствует или имеет значение null, то оно не учитывается.

    • Вернуть при несогласовании – вернуть документ на доработку Инициатору при несогласовании хотя бы одним из согласующих. Флаг проверяет только результат текущего этапа.

    • Рекомендательное согласование - при наличии отрицательных решений на данном этапе, система не будет возвращать процесс на доработку, т.е. решение таких согласующих не влияет на итог согласования - при несогласовании документ все равно будет считаться согласованным. При установке флага проставляется специальный вид задания, однако можно указывать собственный.
  • Вкладка Дополнительно:

    • Вернуть после согласования – вернуть договор на доработку Инициатору при согласовании всеми текущими согласующими. Флаг проверяет только результат текущего этапа.
    • Отключить автоматическое согласование - отключить для данного этапа автоматическое завершение задания согласования (см. Автоматическое согласование).

    Следующие две настройки управляют логикой работы этапа в подсистеме маршрутов.

    • Изменять состояние при старте - если флаг установлен (по умолчанию), то при запуске этапа состояние карточки устанавливается в “На согласовании”. Флаг можно снять, если не нужно такое поведение.
    • Изменять состояние при завершении - если флаг установлен, то при успешном выходе из этапа (все согласующие согласовали) состояние карточки устанавливается в “Согласовано”. При несогласовании в последовательном режиме - этап устанавливает состояние карточки “Не согласовано” сразу же, а в параллельном режиме выполнения - когда все согласующие завершили свои задания.
    • Настройки прав доступа для согласующих этапа

      • Редактировать карточку – дать права доступа на редактирование карточки документа согласующим этапа на момент исполнения их заданий;
      • Редактировать любые файлы – дать права доступа на редактирование приложенных файлов для согласующих этапа на момент исполнения их заданий.
  • Группа настроек Переопределение группы истории заданий.

    Позволяют указать параметры, определяющие группу в истории заданий. Функциональность аналогична, как в этапе “Управление историей”, кроме того, что данные настройки не распространяются на другие этапы.

    • Группа истории заданий - группа истории заданий, которая будет родительской по отношению к элементу истории заданий, отправляемых данным этапом.
    • Родительская группа - группа истории заданий, являющейся родительской по отношению к группе, задаваемой в поле “Группа истории заданий”. Если указана, то будет выбрана родительская группа заданного типа с наибольшей итерацией.

      Note

      Как создать новую группу истории заданий описано в разделе Управление историей.

    • Новая итерация - если флаг установлен, то будет создана новая итерация для группы истории заданий, заданной в поле “Группа истории заданий”.

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

  1. Если это последнее задание этапа

    И (были не согласовавшие в текущем этапе ИЛИ результат задания = “Не согласовано”), то:

    1. Если флаг Вернуть при несогласовании не стоит

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

    2. Если флаг Не возвращать на доработку стоит, то завершаем этап и идем дальше по маршруту.

    3. Если вышеописанные условия не выполнились, то возвращаемся в начало текущей группы.
  2. Если это не последнее задание этапа

    И этап последовательный

    И результат задания = “Не согласовано”, то:

    1. Выполняются те же проверки что и в пунктах 1.a - 1.c.
  3. Если результат задания = “Согласовано”, то:

    1. Если флаг Не возвращать на доработку стоит, то завершаем этап и идем дальше по маршруту.
    2. Если флаг Не возвращать на доработку не стоит

      И были не согласовавшие на этом же этапе или ранее в пределах группы

      И нет следующих этапов согласования в пределах группы, то возвращаемся в начало текущей группы.

    3. Если это последнее задание этапа И флаг Возвращать при согласовании стоит, то ищем первый этап доработки в текущей группе:

      1. Если нашли - переходим на него. После завершения задания доработки выполнение маршрута возобновляется с этапа, следующего за этапом, инициировавшим доработку. Номер цикла не изменяется.
      2. Если не нашли - завершаем этап и идем дальше по маршруту.

При обработке завершения задания, если результат = “Не согласовано” и этап не рекомендательный - в StageInfo пишется признак "Disapproved": true.

Проверка, были ли не согласовавшие в прошедших этапах, проверяет наличие флага "Disapproved": true в текущем и предыдущих этапах.

Имя флага Disapproved содержится в константе Tessa.Extensions.Default.Shared.Workflow.KrProcess.KrConstants.Keys.Disapproved.

Предполагается, что этап “Доработка” располагается в начале текущей группе этапов, который отправит задание инициатору на доработку документа.

Этап согласования завершается, когда завершится последнее задание этапа.

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

  • Примеры маршрутов в типовой группе Согласование с наличием всех типовых шаблонов этапов.

    Пример 1. Комбинация флагов Вернуть при несогласовании и Вернуть после согласования

    Example

    Шаблон этапов с маршрутом:

    Исполнители Параллельный Вернуть при несогласовании Не возвращать на доработку Рекомендательное согласование Вернуть после согласования
    1 Иванов, Петров Нет Да Нет Нет Да
    2 Волков Нет Да Нет Нет Нет

    Варианты прохождения маршрута:

    • Иванов - согласовал, Петров - согласовал, документ отправился на доработку, далее Волкову. Волков согласовал. Документ согласован.

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

    • Иванов - не согласовал, документ отправился на доработку с увеличением цикла.

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

    • Иванов - согласовал, Петров - согласовал, документ отправился на доработку, далее Волкову. Волков не согласовал, документ отправился на доработку с увеличением цикла.

      В данном случае был возврат в начало группы, т.к. документ не согласовали. Причем этот возврат не зависел от наличия флага Вернуть при несогласовании на втором этапе, т.к. внутри этапа согласования встроена проверка, срабатывающая на последнем этапе группы: если в маршруте на каком-либо этапе были отрицательные визы - вернуть маршрут в начало группы.

    Пример 2. Комбинация флагов Вернуть при несогласовании и Вернуть после согласования

    Example

    Шаблон этапов с маршрутом:

    Исполнители Параллельный Вернуть при несогласовании Не возвращать на доработку Рекомендательное согласование Вернуть после согласования
    1 Иванов, Петров Нет Нет Нет Нет Нет
    2 Волков Нет Нет Нет Нет Да

    Варианты прохождения маршрута:

    • Иванов - не согласовал, Петров - не согласовал, Волков - не согласовал, документ отправился на доработку с увеличением цикла.

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

    • Иванов - согласовал, Петров - согласовал, Волков - согласовал, документ отправился на доработку, далее переход в состояние “Согласован”.

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

    Пример 3. Флаг Не возвращать на доработку

    Example

    Шаблон этапов с маршрутом:

    Исполнители Параллельный Вернуть при несогласовании Не возвращать на доработку Рекомендательное согласование Вернуть после согласования
    1 Иванов, Петров Нет Нет Да Нет Нет
    2 Волков Нет Нет Да Нет Нет

    Варианты прохождения маршрута:

    • Иванов - не согласовал, Петров - согласовал, Волков - не согласовал, документ отправился на доработку с увеличением цикла.

      В данном случае флаг Не возвращать на доработку позволил после первого этапа перейти на второй, но не смотря на этот флаг во втором этапе, был выполнен переход в начало группы.

      В этом примере Флаг Не возвращать на доработку на первом этапе отключил встроенную в этап проверку, которая в случае несогласования возвращает маршрут в начало группы, а во втором этапе благодаря флагу не сработала проверка, которая в случае, если в группе ранее (на любых этапах) были отрицательные визы - вернуть маршрут в начало группы. Документ же вернулся на доработку в начало группы благодаря шаблону этапов “Возврат на доработку”, входящему в типовую поставку и находящемуся в конце группы “Согласование”.

    В предыдущих примерах маршрутов возврат в начало группы выполнялся как раз благодаря проверке, встроенной внутри этапа Согласования. Шаблон этапов “Возврат на доработку” даже не выполнялся, он выполнится только в случае выставления флага Не возвращать на доработку на последнем этапе группы.

    Другие варианты прохождения маршрута мы не рассматриваем, т.к. они аналогичны, т.е. не зависимо от решения на первом этапе, будет выполнен переход на второй, а при завершении второго этапа в зависимости от решения на обоих этапах документ или перейдет в состояние “Согласован”, или отправится на доработку.

    По сути, флаг Не возвращать на доработку отрабатывает так же, как снятый флаг Вернуть при несогласовании, небольшое отличие есть только на последнем этапе группы (при условии, что в группе есть типовой шаблон этапов “Возврат на доработку”). Возврат будет выполнен с помощью разных инструментов: с флагом Не возвращать на доработку - путём обозначенного шаблона этапов, без флага - путем встроенной проверки в этапе согласования. Инструменты разные, но итог один - возврат выполняется.

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

    Пример 4. Флаг Рекомендательное согласование

    Example

    Шаблон этапов с маршрутом:

    Исполнители Параллельный Вернуть при несогласовании Не возвращать на доработку Рекомендательное согласование Вернуть после согласования
    1 Иванов, Петров Нет Нет Нет Да Да
    2 Волков Нет Нет Нет Нет Нет

    Варианты прохождения маршрута:

    • Иванов - согласовал, Петров - согласовал, документ отправлен на доработку, далее Волкову. Волков - согласовал. Документ согласован.
    • Иванов - не согласовал, Петров - не согласовал, документ отправлен на доработку, далее Волкову. Волков - согласовал. Документ согласован.

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

    Во-вторых даже при наличии отрицательных виз не было возврата в начало группы (ни путём выполнения проверки, встроенной в этап согласование, ни путём выполнения шаблона этапов “Возврат на доработку”) по той же причине - при включенном флаге “Рекомендательное согласование любое решение для системы является положительным, не смотря на то, что в истории заданий и листе согласования фиксируется отрицательная виза.

  • Примеры маршрутов при отсутствии в группе типового шаблона этапов “Возврат на доработку”.

    Пример 5. Флаг Вернуть при несогласовании

    Example

    Шаблон этапов с маршрутом:

    Исполнители Параллельный Вернуть при несогласовании Не возвращать на доработку Рекомендательное согласование Вернуть после согласования
    1 Иванов, Петров Нет Да Нет Нет Нет
    2 Волков Нет Нет Нет Нет Нет

    Варианты прохождения маршрута:

    • Иванов - согласовал, Петров - не согласовал, документ отправлен на доработку с увеличением цикла.

    В этом примере вполне ожидаемое поведение маршрута с учетом приведенных выше примеров.

    • Иванов - согласовал, Петров - согласовал, Волков - не согласовал, документ отправлен на доработку с увеличением цикла.

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

    Пример 6. Флаг Не возвращать на доработку

    Example

    Шаблон этапов с маршрутом:

    Исполнители Параллельный Вернуть при несогласовании Не возвращать на доработку Рекомендательное согласование Вернуть после согласования
    1 Иванов, Петров Нет Нет Да Нет Нет
    2 Волков Нет Нет Да Нет Нет

    Варианты прохождения маршрута:

    • Иванов - не согласовал, Петров - согласовал, Волков - согласовал, документ переходит в состояние “Не согласован”.
    • Иванов - согласован, Петров - согласовал, Волков - не согласовал, документ переходит в состояние “Не согласован”.

    Это единственный пример, где в конце выполнения группы при наличии отрицательных виз не выполнен возврат на доработку, даже при отсутствии флага Рекомендательное согласование. Документ переходит в состояние “Не согласован” и маршрут согласования завершается. При этом наличие флага Не возвращать на доработку в первом этапе отрабатывает аналогично снятому флагу Вернуть при несогласовании, этот сценарий подробно описан в примере 3.

    Комбинация условий: наличие флага Не возвращать на доработку на последнем этапе группы и отсутствие в группе шаблона этапов “Возврат на доработку” может быть полезна, например, при настройке сложного маршрута согласования с использованием ветвления (чтобы в случае отрицательных виз ветка могла завершиться, без доработки внутри ветки) или при обработке отрицательных виз по своей логике, отличающейся от типовой.

Подписание

Этап подписания полностью аналогичен согласованию, за исключением:

  • в заданиях кнопки называются Подписать и Отказать вместо Согласовать и Не согласовать;
  • состояние карточки при входе в этап устанавливается “На подписании”;
  • для включения возможности выполнения запроса дополнительного согласования из задания “Подписания” в параметрах этапа необходимо установить флаг Разрешить дополнительное согласование;
  • для подписантов отсутствует возможность задания дополнительных согласующих в параметрах этапа.

Доработка

Этап, обеспечивающий доработку документа после несогласования или при отказе в подписании. Отправляет задание на доработку указанному исполнителю. По завершению задания передает управление следующему этапу в маршруте.

Настройки этапа:

  • Срок (рабочие дни) - срок задания в рабочих днях, допускаются дробные значения.
  • Дата выполнения - астрономическая дата выполнения задания. Можно указать либо это поле, либо Срок (рабочие дни).
  • Исполнитель - исполнитель задания. Обычно это роль “Инициатор согласования”, но можно указывать любую роль в системе.
  • От имени (сотрудник или контекстная роль) - позволяет отправить задание от имени любого сотрудника.
  • Вид - вид задания (отображается в виде заголовка в форме задания, также по виду возможна фильтрация в представлении Мои задания).
  • Комментарий - комментарий к текущему заданию доработки, он будет отображаться в сформированном исполнителю задании в качестве текста задания.
  • Изменять состояние - если флаг установлен (по умолчанию), то при входе в этап состояние карточки меняется на “На доработке”.

    Important

    В случае, если вход в этап выполняется после этапа “Согласование” или “Подписание” (т.е. в случае отказа в согласовании или подписании документа), для которых был выставлен флаг Изменять состояние при завершении, то этап “Доработка” не выполнит смену состояния. За это отвечает флаг KrConstants.Keys.IgnoreChangeState, блокирующий смену состояния для этапа “Доработка”.

  • Увеличить цикл - если флаг установлен (по умолчанию), то при входе в этап текущий цикл согласования увеличится на 1. Текущий цикл доступен в контексте из любого сценария: Cycle.

  • Доступ на редактирование схемы согласования - если флаг установлен, то исполнитель на время исполнения задания на доработку, независимо от настроенных правил доступа, получит права на редактирование схемы согласования карточки документа.
  • Не пропускать этап - по умолчанию этап доработки пропускает себя (т.е. передает управление дальше, не выполняя никаких действий), если управление на него приходит не из текущей группы или карточки. Это нужно, чтобы пропустить этап при запуске процесса. При этом, предполагается, что возврат из текущей группы - это возврат при несогласовании, поэтому в этом случае этап выполняется и отправляет задание на доработку. Следует установить флаг, если требуется управлять пропуском этапа самостоятельно из сценариев.
  • Управлять видимостью этапа - если флаг установлен (по умолчанию), то этап становится видимым при выполнении, иначе остаётся скрытым.

Группа настроек Переопределение группы истории заданий описана в этапе “Согласование”.

Типовая задача

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

Подробно возможности задач подробно описаны в соответствующем разделе руководства пользователя.

Настройки этапа:

  • Исполнители - любые роли в системе, можно указывать несколько. Если не установлен флаг Отдельная задача каждому исполнителю, то система сама вычислит список ролей, на основе указанных, которым будет доступно отправляемое задание, и исполнять задачу будет тот, кто первый взял ее в работу.
  • От имени (сотрудник или контекстная роль) - позволяет отправить задание от имени любого сотрудника. В отличие от отправки задачи по тайлу Поставить задачу, здесь можно выбрать абсолютно любого сотрудника, т.к. маршруты настраиваются администратором. Позволяет указать, какой сотрудник будет записан в список связанных с заданием ролей с ФР “Автор”.
  • Отправитель (сотрудник или контекстная роль) - позволяет указать, какой сотрудник будет записан в список связанных с заданием ролей с ФР “Отправитель”. Эта запись призвана отображать фактического создателя задания.

    Note

    Если не указать значение в поле От имени, то информация для него будет скопирована из поля Отправитель.

  • Отдельная задача каждому исполнителю - если флаг установлен, то каждый исполнитель получает отдельную задачу.

  • Первый исполнитель - ответственный - если флаг установлен, то первый исполнитель получит обычную задачу, а остальные - дочерние задачи.
  • Длительность (рабочие дни) - срок задания в рабочих днях. Допускаются дробные значения.
  • Дата выполнения - астрономическая дата выполнения задания. Можно указать либо это поле, либо Длительность (рабочие дни).
  • Вернуть после завершения - если флаг установлен, то после завершения исполнителем задача будет отправлена автору. Он сможет проверить результаты выполнения и при необходимости вернуть ее исполнителю или отправить другому сотруднику или сотрудникам. Если флаг установлен, то станет доступно поле Вернуть на роль, позволяющее вернуть задачу не автору, а любой другой роли.
  • Комментарий - текст задания.
  • Вид - вид задания.

Группа настроек Переопределение группы истории заданий описана в этапе “Согласование”.

Настраиваемое задание

Этап “Настраиваемое задание” позволяет отправить одному или нескольким исполнителям задание с заданными в настройках этапа вариантами завершения и обработать результат. Этап асинхронный и для завершения ждет завершения всех заданий исполнителей. После завершения задания этап завершается и передает управление далее по маршруту.

Настройки этапа:

  • Срок (рабочие дни) - срок задания в рабочих днях. Допускаются дробные значения.
  • Дата выполнения - астрономическая дата выполнения задания. Можно указать либо это поле, либо “Срок (рабочие дни)”.
  • Исполнители - исполнители задания. Можно указывать любые роли.
  • От имени (сотрудник или контекстная роль) - сотрудник, который будет автором отправленных заданий. Можно указать конкретного сотрудника или контекстную роль. В случае с контекстной ролью система ее вычислит и автором будет первый сотрудник из входящих в контекстную роль.
  • Вид - вид задания.
  • Текст задания - текст задания.
  • Варианты завершения - в этой таблице можно создать варианты завершения, которые будут доступны пользователю как кнопки завершения задания.

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

    • Вариант завершения - название варианта завершения (кнопки в задании). Можно использовать локализацию.
    • Сообщение - сообщение, которое будет отображаться пользователю при нажатии на данный вариант завершения, при этом для завершения задания необходимо будет повторно нажать на кнопку. Слева внешний вид задания до нажатия кнопки Выполнено, справа - после ее нажатия:

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

      // если комментарий пустой, ругаемся if ( String.IsNullOrWhiteSpace ( (string)StageInfo.Tasks[0].Comment ) ) { AddError("Пожалуйста, укажите комментарий!"); }

  • Дополнительный вариант завершения - если флаг установлен, то вариант завершения в задании будет доступен в выпадающем списке “Еще”.

Группа настроек Переопределение группы истории заданий описана в этапе “Согласование”.

При завершении задания этап записывает в состояние этапа информацию о завершаемом задании. Помимо основной информации о задании записывается также дополнительная информация:

  1. Comment - комментарий при завершении;
  2. OptionID - идентификатор варианта завершения, выбранного пользователем;
  3. OptionName - название варианта завершения, выбранного пользователем;
  4. CompletedByID - идентификатор сотрудника, завершившего задание;
  5. CompletedByName - отображаемое имя сотрудника, завершившего задание;
  6. Completed - дата и время завершения задания.
Пример сохраняемых данных

При Stage.WriteTaskFullInformation = false:

{ ".flags": 44052, ".state": 0, ".storedState": 1, "Action": 3, "AuthorID": "3db19fa0-228a-497f-873a-0250bf0a4ccb", "AuthorName": "Admin", "AuthorPosition": null, "Comment": "Комментарий", "Completed": "2021-06-22T15:24:13.4663366Z", "CompletedByID": "3db19fa0-228a-497f-873a-0250bf0a4ccb", "CompletedByName": "Admin", "Digest": "", "GroupRowID": null, "HistoryItemParentRowID": null, "InProgress": "2021-06-22T15:23:43.677Z", "OptionID": "99398df4-c529-4401-93b8-e4ce14c66d27", "OptionName": "Вариант завершения", "ParentRowID": null, "Planned": "2021-06-24T06:00:00Z", "PlannedQuants": 33, "PlannedType": 0, "PostponeComment": null, "Postponed": null, "PostponedTo": null, "ProcessID": null, "ProcessKind": null, "ProcessName": null, "Result": "Комментарий", "RoleID": "3db19fa0-228a-497f-873a-0250bf0a4ccb", "RoleName": "Admin", "RoleTypeID": "929ad23c-8a22-09aa-9000-398bf13979b2", "RowID": "3f3631e0-037e-47be-ae9e-ad78075959e5", "Settings": {}, "TimeZoneID": 0, "TimeZoneUtcOffsetMinutes": 180, "TypeCaption": "$CardTypes_TypesNames_KrUniversalTask", "TypeID": "9c6d9824-41d7-41e6-99f1-e19ea9e576c5", "TypeName": "KrUniversalTask", "UserID": "3db19fa0-228a-497f-873a-0250bf0a4ccb", "UserName": "Admin" }

При Stage.WriteTaskFullInformation = true:

{ ".flags": 44052, ".state": 0, ".storedState": 1, "Action": 3, "AuthorID": "3db19fa0-228a-497f-873a-0250bf0a4ccb", "AuthorName": "Admin", "AuthorPosition": null, "Card": { "Created": "2021-06-22T15:25:28.103Z", "CreatedByID": "3db19fa0-228a-497f-873a-0250bf0a4ccb", "CreatedByName": "Admin", "Files": null, "Flags": 0, "ID": "27da5497-cd7d-4032-8f79-f6c90483b047", "Info": null, "Modified": "2021-06-22T15:25:29.12Z", "ModifiedByID": "3db19fa0-228a-497f-873a-0250bf0a4ccb", "ModifiedByName": "Admin", "Permissions": { "CardPermissions": 87381, "FilePermissions": null, "Sections": null }, "Sections": { "KrTask": { "Fields": { "Comment": "Комментарий" } }, "KrUniversalTaskOptions": { ".table": 1, "Rows": [ { "Additional": false, "Caption": "Вариант завершения", "Message": "Сообщение", "OptionID": "99398df4-c529-4401-93b8-e4ce14c66d27", "Order": 0, "RowID": "94901333-01b7-4e6a-92d1-06f233a4ddd7", "ShowComment": true } ] }, "TaskCommonInfo": { "Fields": { "KindCaption": null, "KindID": null } } }, "TypeCaption": "$CardTypes_TypesNames_KrUniversalTask", "TypeID": "9c6d9824-41d7-41e6-99f1-e19ea9e576c5", "TypeName": "KrUniversalTask", "Version": 0 }, "Comment": "Комментарий", "Completed": "2021-06-22T15:25:38.5757756Z", "CompletedByID": "3db19fa0-228a-497f-873a-0250bf0a4ccb", "CompletedByName": "Admin", "Digest": "", "GroupRowID": null, "HistoryItemParentRowID": null, "Info": { ".universalOptionID": "99398df4-c529-4401-93b8-e4ce14c66d27" }, "InProgress": "2021-06-22T15:25:29.12Z", "OptionID": "99398df4-c529-4401-93b8-e4ce14c66d27", "OptionName": "Вариант завершения", "ParentRowID": null, "Planned": "2021-06-24T06:00:00Z", "PlannedQuants": 33, "PlannedType": 0, "PostponeComment": null, "Postponed": null, "PostponedTo": null, "ProcessID": null, "ProcessKind": null, "ProcessName": null, "Result": "Комментарий", "RoleID": "3db19fa0-228a-497f-873a-0250bf0a4ccb", "RoleName": "Admin", "RoleTypeID": "929ad23c-8a22-09aa-9000-398bf13979b2", "RowID": "27da5497-cd7d-4032-8f79-f6c90483b047", "SectionRows": null, "Settings": {}, "TimeZoneID": 0, "TimeZoneUtcOffsetMinutes": 180, "TypeCaption": "$CardTypes_TypesNames_KrUniversalTask", "TypeID": "9c6d9824-41d7-41e6-99f1-e19ea9e576c5", "TypeName": "KrUniversalTask", "UserID": "3db19fa0-228a-497f-873a-0250bf0a4ccb", "UserName": "Admin" }

Регистрация

Этап “Регистрация” позволяет отправить задание на регистрацию карточки. При регистрации карточке выделяется постоянный номер и изменяется состояние на “Зарегистрирована”, согласно настройкам типового решения.

Регистрация выполняется после завершения задания.

Настройки этапа:

  • Срок (рабочие дни) - срок задания в рабочих днях. Можно использовать дробные значения.
  • Дата выполнения - астрономическая дата выполнения задания. Можно указать либо это поле, либо Срок (рабочие дни).
  • Регистратор - исполнитель задания. Любая роль в системе.
  • От имени (сотрудник или контекстная роль) - позволяет отправить задание от имени любого сотрудника.
  • Вид - вид задания.
  • Комментарий - комментарий к этапу.
  • Без отправки задания - если флаг установлен, то задание регистрации не отправляется. В данном режиме этап выполняется в синхронном режиме.
  • Редактировать карточку – дать права доступа на редактирование карточки регистраторам на период исполнения задания (пока задание активно).
  • Редактировать любые файлы – дать права доступа на редактирование приложенных файлов для регистраторов на период исполнения задания (пока задание активно).

Отмена регистрации

Этап “Отмена регистрации” выполняет отмену регистрации документа, т.е. возвращает проектный номер и состояние “Проект”. Кроме названия и сценариев, настроек не имеет.

Этап синхронный, при получении управления выполняет дерегистрацию и сразу передает управление дальше.

Ознакомление

Этап “Ознакомление” позволяет отправить карточку на ознакомление указанным сотрудникам. Они получат почтовое уведомление и доступ на чтение карточки. Также отправленные на ознакомление документы доступны пользователю в рабочем месте Пользователь в представлении Мне на ознакомление. При открытии ими карточки система зафиксирует факт ознакомления в журнале ознакомления. Функциональность ознакомления полностью аналогична ознакомлению типового решения.

  • Получатели - список ролей? на которые будет отправлено ознакомление. Система объединит состав ролей, сформировав общий список сотрудников и затем каждому из них отравит на ознакомление документ.
  • Отправитель (сотрудник или контекстная роль) - сотрудник, от имени которого будет отправлено ознакомление. Можно указать сотрудника или контекстную роль. Если указана контекстная роль, система ее вычислит и возьмет первого сотрудника, входящего в эту роль.
  • Комментарий - комментарий к ознакомлению, обычный текст. При его формировании можно использовать функциональность плейсхолдеров, по аналогии с формированием шаблонов файлов. Подробно о плейсхолдерах и шаблонах файлов можно прочитать в соответствующем разделе руководства администратора.
  • Алиасы плейсхолдеров - если в формировании текста комментария используются плейсхолдеры, здесь можно указать для них сокращенные алиасы и использовать их для формирования текста комментария, так же, как и в шаблонах файлов.
  • Уведомление - выбор карточки уведомления, которая будет использована для отправки письма с уведомлением пользователя. Система сформирует письмо согласно шаблону в карточке уведомления и разошлет пользователям.

    В тексте выбранной карточки уведомления можно использовать некоторые дополнительные псевдо-плейсхолдеры:

    • {{sender}} - заменяется на имя отправителя;
    • {{comment}} - заменяется на сформированный комментарий;
    • &lt;comment_block&gt;...&lt;/comment_block&gt; - блок с комментарием. Удаляется в случае, когда {{comment}} пустой. Например, можно написать как показано в примере, и в случае пустого комментария весь текст “Инициатор отправил…” будет удален из почтового уведомления.

      Пожалуйста, внимательно прочтите документ. <comment_block>Инициатор отправил следующий комментарий: {{comment}}</comment_block>

  • Не отправлять заместителям - если флаг установлен, то из состава ролей будут исключены сотрудники, входящие туда как заместители.

Note

Идентификатор карточки, по которой этап отправляет ознакомление, определяется следующим образом. Проверяется значение в IKrScript.Stage.InfoStorage по ключу MainCardID, если оно не задано или равно null, то проверяется значение свойства IKrScript.MainCardID. Если ни одно из значений не задано, то этап завершается без отправки ознакомления.

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

this.Stage.InfoStorage["MainCardID"] = new Guid("<ИД карточки>");

Уведомление

Этап “Уведомление” позволяет сформировать и отправить уведомление сотрудникам по электронной почте (email). При формировании уведомления используется карточка уведомления, на которую ссылается этап. Подробнее про уведомления в соответствующем разделе руководства администратора.

  • Получатели - список ролей, на которые будет отправлено уведомление. Система объединит состав ролей, сформировав общий список сотрудников, исключит тех, у кого не указана почта в справочнике и затем каждому из них отравит сформированное уведомление.
  • Опциональные получатели - список ролей, на которые будет отправлено уведомление, если в правилах уведомлений сотрудников указано, что они хотят получить данное уведомление. Система объединит состав ролей, сформировав общий список сотрудников, исключит тех, у кого не указана почта в справочнике и затем каждому из них отравит сформированное уведомление.
  • Уведомление - выбор карточки уведомления, которая будет использована для отправки письма с уведомлением пользователя. Система сформирует письмо согласно шаблону в карточке уведомления.
  • Не отправлять заместителям - если флаг установлен, то из списка получателей будут исключены сотрудники, входящие туда как заместители.
  • Не отправлять подписчикам - если флаг установлен, то из списка получателей будут исключены сотрудники, подписанные на получение данного типа уведомлений, если они не включены в список получателей или опциональных получателей.

Этап выполняется синхронно, после запуска сразу формирует исходящие письма и передает управление следующему этапу в маршруте.

Создание карточки

Этап “Создание карточки” позволяет создать новую карточку из маршрута. Создать можно либо по выбранному шаблону карточки, либо просто выбрав определенный тип карточки. По созданной карточке можно сразу же запустить маршрут и/или открыть ее в рабочем месте пользователя.

Настройки этапа:

  • Тип - ссылка на тип карточки или тип документа, который будет использоваться для создания новой карточки.
  • Шаблон - ссылка на шаблон, по которому будет создана карточка.

    Note

    Стоит учитывать, что в большинстве режимов создания (см. поле Режим) пользователю не требуются права на создание карточек.

  • Режим - режим создания карточки:

    • Открыть новую карточку - карточка будет создана и открыта (но не сохранена!) непосредственно в клиентском рабочем месте пользователя, как если бы он ее сам создал по шаблону (или просто создал, если это создание по типу карточки). В этом режиме пользователю требуется доступ к указанному шаблону/праву на создание карточки. Открытая карточка будет новой, не сохраненной - пользователю нужно будет самостоятельно сохранить карточку. До момента сохранения информации об этой карточке в базе данных нет.
    • Сохранить карточку - карточка будет создана и сохранена на сервере. Пользователю в этом режиме не нужны права на создание карточки, а также доступ к шаблону, по которому создается карточка.
    • Сохранить и открыть карточку - карточка будет создана и сохранена на сервере, а затем уже открыта в рабочем месте пользователя. Пользователю в этом режиме не нужны права на создание карточки, а также доступ к шаблону, по которому создается карточка. Но при этом ему нужен доступ на чтение созданной карточки. Если такого доступа нет, то карточка создастся, но не откроется у пользователя в клиентском приложении. При этом карточка останется существовать в системе.
    • Запустить процесс - карточка будет создана и сохранена на сервере, а потом по ней будет сформирован маршрут и запущен процесс по маршруту. Процесс при этом сразу же выполнится до первого асинхронного этапа, например, отправки задания. Пользователю в этом режиме не нужны права на создание карточки, а также доступ к шаблону, по которому создается карточка.
    • Запустить процесс и открыть карточку - аналогичен Запустить процесс, но карточка будет открыта в рабочем месте пользователя после запуска процесса. Пользователю в этом режиме не нужны права на создание карточки, а также доступ к шаблону, по которому создается карточка. Но при этом ему нужен доступ на чтение созданной карточки. Если такого доступа нет, то карточка создастся, но не откроется у пользователя в клиентском приложении. При этом карточка останется существовать в системе.

После создания и сохранения карточки этап записывает идентификатор созданной карточки по ключу cardID (константа Tessa.Extensions.Default.Shared.Workflow.KrProcess.KrConstants.Keys.NewCardID) в состояние этапа.

{ "cardID": "e4d4db89-4320-4fcb-aa1f-9d36e33ca614" }

Сценарий постобработки может получить этот идентификатор ((Guid)StageInfo.cardID) и что-нибудь сделать с этим знанием, например:

  • Изменить созданную карточку, выполнив запрос к БД. К моменту выполнения сценария данные карточки уже записаны в базу данных, но транзакция еще открыта.
  • Изменить созданную карточку, выполнив следующий этап маршрута в ее контексте. Для этого нужно добавить в маршрут сразу после этапа создания карточки этап сценария. Затем в сценарии постобработки этапа создания карточки выполнить RunNextStageInContextAsync( (Guid)StageInfo.cardID ); (см. пример с созданием уже зарегистрированной карточки). Следующие этапы маршрута выполнятся в контексте вновь созданной карточки и в тексте сценария можно будет просто написать, например, (await GetCardAsync()).DocumentCommonInfo.Amount = 10 для изменения суммы договора.

Создаваемую карточку можно модифицировать в сценарии постобработки этапа, перед выполнением действия с карточкой (открытием, сохранением, запуском процесса), следующим образом:

var card = await GetNewCardAsync(); card.Sections["DocumentCommonInfo"].Fields["Subject"] = "Новая тема документа"; // Или (await NewCardAsync()).DocumentCommonInfo.Subject = "Новая тема документа";

Note

Важные нюансы:

  • в режиме Открыть новую карточку - card содержит пустой пакет карточки, предназначенный только для записи новых значений;
  • в остальных режимах - card содержит полный пакет карточки.

Смена состояния

Этап “Смена состояния” позволяет изменить состояние текущей карточки. Этап синхронный и передает управление дальше сразу после изменения состояния.

Настройки этапа:

  • Состояние - выбор из справочника состояний. Добавлять новые состояния можно в таблицу KrDocState при помощи библиотек схемы (или на рабочем месте Администратор в представлении Документы и задания -> Состояния документа).

Пересчёт маршрута

Этап “Пересчёт маршрута” выполняет пересчёт состава текущей группы маршрута и обновляет ту его часть, которая будет выполняться после этапа “Пересчёт маршрута”. При этом, если были изменения состава этапов до того места, где находится этап “Пересчёт маршрута”, то система трактует это как ошибки и никаких изменений в итоговом маршруте карточки производиться не будет. Пересчёт группы выполняется по обычным правилам пересчёта маршрута с выполнением сценариев дизайн-тайма, за исключением того, что система пересчитывает только текущую группу.

Этап не имеет дополнительных настроек (помимо общих, описанных выше).

Сценарий

Этап “Сценарий” позволяет выполнить какие-то действия в сценариях инициализации или постобработки.

Этап не имеет дополнительных настроек (помимо общих, описанных выше).

Управление процессом

Этап “Управление процессом” позволяет управлять маршрутом, выполняя различные переходы, отзыв, запуск процесса и так далее.

В поле Режим можно задать различные режимы работы этапа. Если установлен флаг Выполнять в основном процессе, то этап будет управлять основным процессом карточки, а не текущим. Этот флаг позволяет, например, по нажатию тайла, выполнить отзыв основного процесса. Маршрут, связанный с тайлом, будет вторичным отдельным маршрутом. Если флаг Выполнять в основном процессе не установлен, то этап будет пытаться управлять текущим вторичным процессом.

Доступные режимы работы:

  • Отправить сигнал - это специальный режим, позволяющий отправить некоторые заранее заданные специальные команды процессу. Этот режим может использоваться только с установленным флагом Выполнять в основном процессе. Такими командами могут быть:

    • KrStartProcessSignal - формирует маршрут и запускает процесс по документу. Если процесс уже запущен, выдает ошибку.
    • KrStartProcessUnlessStartedGlobalSignal - формирует маршрут и запускает процесс по документу. Если процесс уже запущен, просто ничего не делает.
  • Отменить процесс - может выполняться в основном и вторичном процессе. Отзывает текущий активный этап маршрута в основном процессе. Все этапы маршрута, включая отозванный, переходят в состояние “Не запущен”. Процесс маршрута завершается и должен быть запущен заново.

    Если происходит управление основным процессом из вторичного (например, мы отзываем основной процесс по нажатию тайла), в основном процессе может быть текущий активный этап, который отправил задания пользователю. В этом случае система всегда отзывает этот этап, который в свою очередь - обычно отзывает отправленные пользователям задания. Отозваны могут быть любые этапы, входящие в поставку платформы. При этом отзыв заданий выполняет, собственно, сам этап, когда подсистема маршрутов запрашивает отзыв. Кастомные этапы подсистемы маршрутов могут вести себя по-другому - так, как написано в соответствующем этапе.

  • Пропустить процесс - может выполняться в основном и вторичном процессе. Отзывает текущий активный этап маршрута в основном процессе. Отозванный этап и все этапы после него переходят в состояние “Пропущен”. Процесс маршрута завершается и должен быть запущен заново.

  • Переход на этап - выполняет переход на конкретный этап маршрута.

    В поле Строка с этапом нужно выбрать конкретный этап. Этап должен присутствовать в рассчитанной части маршрута, переход может выполняться вперед или назад.

    Если переход выполняется вперед, то все пропущенные этапы переходят в состояние “Пропущен”. Если переход выполняется назад, то все пропущенные этапы переходят в состояние “Не запущен”. Если указанного этапа нет, то этап управления процессом не выполняет никаких действий.

    При переходе в другую группу маршрута - выполняется пересчёт этой группы по общим правилам с выполнением сценариев группы “При расчете маршрута”.

  • Переход на группу - выполняет переход на конкретную группу маршрута. Группа должна присутствовать в рассчитанном маршруте в момент перехода.

    В поле Группа этапов нужно выбрать группу, на которую выполняется переход.

    При переходе выполняется пересчёт этой группы по общим правилам с выполнением сценариев группы “При расчете маршрута”. Далее начинается выполнение этапов этой группы.

    Если переход выполняется вперед, то все пропущенные этапы переходят в состояние “Пропущен”. Если переход выполняется назад, то все пропущенные этапы переходят в состояние “Не запущен”. Если указанной группы нет, то этап управления процессом не выполняет никаких действий.

  • Переход на следующую группу - выполняет переход на следующую группу в маршруте.

    При переходе выполняется пересчёт этой группы по общим правилам с выполнением сценариев группы “При расчете маршрута”. Далее начинается выполнение этапов этой группы. Если группы нет (маршрут заканчивается), то завершается процесс маршрута.

    Все пропущенные этапы переходят в состояние “Пропущен”.

  • Переход на предыдущую группу - выполняет переход на предыдущую группу в маршруте.

    При переходе выполняется пересчёт этой группы по общим правилам с выполнением сценариев группы “При расчете маршрута”. Далее начинается выполнение этапов этой группы. Если предыдущей группы нет (текущая группа первая в маршруте), то этап не выполняет никаких действий.

    Все пропущенные этапы переходят в состояние “Не запущен”.

  • Переход в начало текущей группы - выполняет переход на начало текущей группы.

    При переходе выполняется пересчёт этой группы по общим правилам с выполнением сценариев группы “При расчете маршрута”. Далее начинается выполнение этапов этой группы.

Ветвление

Этап ветвления предназначен для параллельного запуска нескольких вторичных процессов. Запускаемые таким образом вторичные процессы называются вложенными (имя типа процесса содержится в константе KrConstants.KrNestedProcessName), имеют свой контекст и состояние (ProcessInfo). Тем не менее все вторичные процессы, запущенные через ветвление (далее вложенные), сохраняются в сателлите родительского процесса (далее основной, не путать с первичным процессом).

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

После старта этапа “Ветвление”, все указанные вторичные процессы будут рассчитаны и запущены.

Note

Внутри этапа “Ветвление” также может запускаться вложенное “Ветвление”.

В сценарии Инициализация этапа “Ветвление” можно модифицировать состояние каждого из запускаемых процессов. Это может быть полезно, например, для передачи параметров в запускаемый процесс.

Example

Пример получения параметров запускаемых вложенных процессов:

IDictionary<string, object> nestInfo = this.GetProcessInfoForBranch(<Идентификатор (RowID) строки в коллекции вторичных процессов>);

nestInfo["key"] = "value";

// Далее в скриптах запускаемого вложенного процесса в ProcessInfo.key будет располагаться значение "value".

Important

“<Идентификатор (RowID) строки в коллекции вторичных процессов>” - это идентификатор строки в секции KrForkSecondaryProcessesSettingsVirtual_Synthetic, а не идентификатор карточки вторичного процесса.

Example

Пример создания ветки процесса:

var branches = Stage.SettingsStorage.Get<IList>(KrConstants.KrForkSecondaryProcessesSettingsVirtual.Synthetic);

var branch = new Dictionary<string, object>(); branch[KrConstants.KrForkSecondaryProcessesSettingsVirtual.RowID] = Guid.NewGuid(); branch[KrConstants.KrForkSecondaryProcessesSettingsVirtual.ID] = this.CardID; branch[KrConstants.StageRowIDReferenceToOwner] = this.Stage.RowID; branch[KrConstants.KrForkSecondaryProcessesSettingsVirtual.SecondaryProcessID] = <Идентификатор вторичного процесса>; // Тип значения: Guid. branch[KrConstants.KrForkSecondaryProcessesSettingsVirtual.SecondaryProcessName] = <Имя вторичного процесса>; // Тип значения: string.

branches.Add(branch);

Tip

В типовом решении, этап “Ветвление”, с настройкой запускаемых вложенных процессов в сценарии инициализации, используется во вторичном процессе “Разослать задачи по решениям” (используемом в карточке типа Протокол).

После завершения каждой из веток вызывается сценарий После завершения ветки. В сценарии доступен параметр NestedProcessInfo метода контекста типа ForkStageTypeHandler.ScriptContext:

  • SkipForkAndContinueRoute (тип значения bool) - значение, показывающее, необходимо ли завершить выполнение ветвления и перейти к следующему этапу или нет.
  • KeepBranchesAlive (тип значения bool) - значение, показывающее, необходимо ли отозвать оставшиеся ветки (false) или оставить – true. Используется только с флагом SkipForkAndContinueRoute.
  • ProcessInfo (тип значения IDictionary<string, object>) - дополнительная информация завершённого вложенного процесса.
  • SecondaryProcess (тип значения IKrSecondaryProcess) - информация о вторичном процессе.
  • BranchInfos (тип значения ListStorage<BranchInfo>) - коллекция, содержащая информацию о ветках этапа.

Все вложенные процессы могут иметь доступ к родительскому состоянию процесса с помощью IKrScript.MainProcessInfo. Таким образом можно реализовать взаимодействие между вложенными процессами и этапами ветвления.

В постобработке этапа можно получить информацию обо всех ветках следующим образом:

// В nestInfo обновленные ProcessInfo после завершения процесса. // После выполнения постобработки коллекция будет очищена. IDictionary<string, object> nestInfos = Stage.InfoStorage .TryGet<Dictionary<string, object>>(KrConstants.Keys.ForkNestedProcessInfo) .TryGet<Dictionary<string, object>>(<Идентификатор (RowID) строки в коллекции вторичных процессов преобразованный к строковому формату ForkStageTypeHandlerBase.ForkSecondaryProcessesRowIDFormat>);

IDictionary<string, object> nestInfo = this.GetProcessInfoForBranch(<Идентификатор (RowID) строки в коллекции вторичных процессов>);

// ...

// Техническая информация об ветках доступна в ForkStageTypeHandler.BranchInfo. var branchInfos = new ListStorage<ForkStageTypeHandler.BranchInfo>( this.Stage.InfoStorage.Get<IList>(ForkStageTypeHandler.PendingProcesses), ForkStageTypeHandler.BranchInfoFactory);

Important

При прерывании ветки ее ProcessInfo не попадает в этап “Ветвление”.

Управление ветвлением

Этап управления ветвлением необходим для динамического воздействия на активный этап ветвления. Активный этап ветвления - этап с типом “Ветвление” и в состоянии “Активен”. С помощью управления ветвлением можно воздействовать только на “Ветвление”, которое запустило текущий процесс (в котором находится этап управления ветвлением) или на этап “Ветвление” в первичном процессе.

Этап поддерживает два режима:

  • Добавить ветку - добавить одну или несколько веток к уже активному этапу ветвления. При необходимости, можно указать ProcessInfo также, как и в этапе “Ветвление”.
  • Завершение ветки - завершить одну или несколько веток. Если в этапе ветвления есть несколько вложенных процессов по одному и тому же вторичному процессу, тогда будут пропущены все эти процессы.

Выполнять в основном процессе - флаг, который необходимо использовать в том случае, если целевой этап “Ветвление” находится в первичном процессе. Если флаг снят, этап влияет на родительское ветвление. Если флаг установлен, тогда этап управления процессом должен находится в вторичном процессе, который запускается вне первичного. Это может быть нажатие кнопки процесса, событие или запуск в коде расширений с помощью IKrProcessLauncher (кроме запуска из сценариев). Если же флаг не выставлен, тогда этап управления должен находится во вложенном процессе.

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

// Получение строк этапов для первичного процесса var rows = (await GetContextualSatelliteAsync()).Sections[KrConstants.KrStages.Name].Rows; // Нахождение строки этапа вложенного процесса var nestedProcessRow = rows.First( p => p["NestedProcessID"] != null && (Guid)p["StageTypeID"] == StageTypeDescriptors.ApprovalDescriptor.ID); // Идентификатор вложенного процесса var nestedProcessID = (Guid)nestedProcessRow["NestedProcessID"];

// Настройки текущего этапа управления процессом var section = Stage .SettingsStorage .TryGet<IList>(KrConstants.KrForkNestedProcessesSettingsVirtual.Synthetic);

// Дополняем настройки идентификатором вложенного процесса // Данные настройки являются скрытыми, из интерфейса недоступны var dict = new Dictionary<string, object>(); dict["RowID"] = Guid.NewGuid(); dict["ID"] = CardID; dict["Order"] = 0; dict["NestedProcessID"] = nestedProcessID; section.Add(dict);

При необходимости явно выставить “Не запущен” вместо “Пропущен” для отменяемой ветки, можно воспользоваться следующим сценарием в инициализации этапа:

Stage.Settings.KrForkManagementSettingsVirtual__DirectionAfterInterrupt = (int)DirectionAfterInterrupt.Backward;

Типизированное задание

Этап типизированного задания позволяет отправлять исполнителям задание указанного в настройках этапа типа. Принципиальное отличие этапа типизированного задания от этапа настраиваемого задания заключается в том, что для типизированного задания необходимо в Tessa Admin разработать тип карточки задания, который будет подключен к подсистеме маршрутов и будет использоваться в этапе типизированное задание. Данный тип этапа, как правило, используется, если по маршруту требуется отправлять задание с нестандартным видом, т.е. содержащее в себе какие-то поля для отображения/заполнения, в то время как в “Настраиваемом задании” настраиваются только варианты завершения задания.

Для того, чтобы разработанный в Tessa Admin тип задания был доступен в подсистеме маршрутов, его необходимо добавить в карточку настроек типового решения на вкладку Настройки этапов маршрутов.

Ниже описаны настройки этапа типизированного задания.

  • Исполнители - любые роли в системе, можно указывать несколько. Задания рассылаются параллельно всем исполнителям.
  • От имени (сотрудник или контекстная роль) - позволяет отправить задание от имени любого сотрудника. В отличие от отправки задачи по тайлу Поставить задачу, здесь можно выбрать абсолютно любого сотрудника, т.к. маршруты настраиваются администратором.
  • Вид - вид задания.

    Для обеспечения функционирования возможности указания вида задания необходимо, чтобы тип задания содержал комплексную колонку TaskCommonInfo.Kind.

  • Тип задания (обязательный) - определяет тип отправляемых заданий.

  • Дайджест - текст задания.

Группа настроек Переопределение группы истории заданий описана в этапе “Согласование”.

После завершения каждого задания в этапе вызывается сценарий После завершения задания. В нем доступен стандартный контекст сценария этапа, а также дополнительные свойства и методы:

  • TypedTaskContext.Task - пакет завершаемого задания. Вариант завершения находится в Task.OptionID.
  • TypedTaskContext.CompleteStage - флаг, используемый для указания обработчику этапа на необходимость завершения этапа. Если выставить в true, то этап будет завершен, активные задания отозваны и управление перейдет к следующему этапу.
  • TypedTaskContext.SendTaskAsync(Performer исполнитель, Guid? тип задания, DateTime? дата завершения, int? срок в рабочих днях, string дайджест задания, CancellationToken cancellationToken = default) - асинхронно отправляет задания в рамках этапа. Обязательным параметром является Исполнитель, остальные значения берутся из настроек этапа, если не указано иное.
  • TypedTaskContext.RevokeTaskAsync(Guid taskID или IEnumerable&lt;Guid&gt; taskIDs, CancellationToken cancellationToken = default) - асинхронного отзывает задание в текущем процессе по указанным идентификаторам.

Пример сценария для этапа, отправляющего несколько заданий согласования, по варианту завершения Запросить комментарий отправляется новое задание комментирования, при согласовании отзывается отправленное комментирование, а при несогласовании завершается весь этап.

Note

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

// Получаем завершаемое задание var task = TypedTaskContext.Task; var optionID = task.OptionID; // Если это запрос комментария if (optionID == DefaultCompletionOptions.RequestComments) { // Получаем из задания информацию для запроса комментария var commentator = task.Card.Sections["KrCommentators"].Rows[0]; var comment = task.Card.Sections["KrTask"].Fields["Comment"] as string; var performer = new Performer((Guid)commentator["CommentatorID"], (string)commentator["CommentatorName"]);

// Отправляем новое задание на комментирование var newTask = await TypedTaskContext.SendTaskAsync(performer, DefaultTaskTypes.KrRequestCommentTypeID); newTask.Card.Sections[KrConstants.KrRequestComment.Name].Fields[KrConstants.KrRequestComment.AuthorRoleID] = task.UserID; newTask.Card.Sections[KrConstants.KrRequestComment.Name].Fields[KrConstants.KrRequestComment.AuthorRoleName] = task.UserName; newTask.ParentRowID = task.RowID; // Запоминаем идентификатор этого задания Stage.Info.CommentID = newTask.RowID; } else if (optionID == DefaultCompletionOptions.Approve || optionID == DefaultCompletionOptions.Disapprove) { // При завершении согласования отзываем комментирование var commentID = (Guid)Stage.Info.CommentID; await TypedTaskContext.RevokeTaskAsync(commentID); } if (optionID == DefaultCompletionOptions.Disapprove) { // Завершаем весь этап TypedTaskContext.CompleteStage = true; }

Создать файл по шаблону

Этап предназначен для создания файла по шаблону.

Настройки этапа

  • Шаблон файла — ссылочное поле с автодополнением, значение из справочника Шаблоны файлов, обязательно для заполнения. Здесь указывается непосредственно шаблон файла, используемый для создания файла.
  • Имя файла — значение типа string, здесь можно переопределить имя файла (в т. ч. с использованием плейсхолдеров), если не задано, то будет использовано имя файла из шаблона.
  • Категория файла — ссылочное поле с автодополнением, значение из справочника Категории файлов, задаёт категорию файла, в которую будет добавлен файл в карточке документа.

Более подробная информация о шаблонах файлов находится в разделе Шаблоны файлов и плейсхолдеры. В документации для разработчика см. также примечание для обработчика этапа “Создать файл по шаблону”.

Диалог

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

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

Диалоги могут быть также использованы в глобальных вторичных процессах.

Настройки этапа:

  • Вид - вид задания (только для асинхронных).
  • Дайджест - дайджест (описание) задания (только для асинхронных).
  • Тип карточки - тип карточки диалога. Если тип карточки содержит секцию “Satellites” (константа Tessa.Cards.Extensions.Templates.CardSatelliteHelper.SatellitesSectionName), то карточка считается сателлитом.
  • Шаблон - шаблон, по которому будет создана карточка.
  • Текст кнопки в задании - название варианта завершения (только для асинхронных).
  • Имя диалога (для расширений) - имя диалога для UI расширений (ICardEditorModel.DialogName). Позволяет фильтровать расширения только для текущего диалога.
  • Алиас диалога (ключ уникальности) - ключ уникальности, позволяющий отображать один и тот же экземпляр карточки в нескольких этапах диалога (если ключ уникальный и карточка уже была создана, то открывается существующая, а не создается новая). Используется только для времени жизни Карточка.
  • Время жизни диалога - указание того, с каким объектом ассоциируется карточка диалога:

    • Запрос - карточка диалога передается в запросе и нигде не сохраняется. Получить ее можно только в текущем сохранении. Следует использовать тогда, когда промежуточные данные о заполнении хранить не нужно.
    • Задание - карточка сохраняется в поле Task.Settings задания в виде JSON объекта. Карточка существует, пока существует задание. Следует использовать, когда нужна возможность промежуточного сохранения результатов диалога.
    • Карточка - диалог сохраняется как полноценная карточка по таблицам секций. Карточка может быть независима от основной, либо быть сателлитом, т.е. содержать секцию Satellites (константа Tessa.Cards.Extensions.Templates.CardSatelliteHelper.SatellitesSectionName). Если карточка является сателлитом, то вместе с удалением/импортом/экспортом основной карточки будут производиться соответствующие операции карточки сателлита. Для независимой карточки этого не происходит. Пример карточки-сателлита в типовом решении - KrExampleDialogSatellite.
  • Режим открытия диалога - определяет поведение при открытии карточки диалога - отображать всегда при открытии основной карточки или по кнопке в задании.

  • Отображаемое имя диалога - значение используется для формирования текста заголовка окна диалога при отсутствии дайджеста карточки.
  • Сохранять файлы после завершения диалога - значение определяет, должны ли сохраняться файлы диалога после его завершения (удаления). Флаг влияет только на диалоги, для которых в параметре Время жизни диалога указано значение Задание.

    Note

    Пример использования доступен в примерах маршрутов во вторичном процессе “Диалоги. Пример использования настройки “Сохранять файлы после завершения диалога”.

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

  • Не выводить вкладки - скрывает заголовки всех вкладок карточки.
  • Настройки кнопок позволяют задать кнопки верхнего и нижнего тулбаров, а также кнопки диалогов.

    • Алиас кнопки - название кнопки, используемое в скриптах.
    • Текст - отображаемый текст кнопки.
    • Тип - тип кнопки: на тулбаре или диалоговая.
    • Иконка - алиас иконки для кнопок тулбара (Thin, Int из поставки платформы Misc\Icons).
    • Отмена - признак того, что окно диалога следует закрыть без отправки запроса.

На этапе есть два вида сценариев (скриптов).

Сценарий валидации

В контексте доступна полная карточка, включая содержимое файлов.

Контекст содержит:

  • Dialog.Cancel - значение true, если необходимо прервать обработку диалога, иначе - false. При прерывании обработки карточка диалога не сохраняется, диалоговое окно не закрывается.
  • Dialog.CompleteDialog - значение true, если этап диалога необходимо завершить, иначе - false. При отмене завершения диалога карточка диалога сохраняется, только для диалогов с временем жизни Задание или Карточка, и диалоговое окно закрывается.
  • Dialog.ButtonName - алиас нажатой кнопки.
  • Dialog.StoreMode - способ сохранения карточки диалога (время жизни диалога).
  • Dialog.GetDialogCardAsync(CancellationToken cancellationToken = default) - возвращает карточку диалога.
  • Dialog.GetFileContentAsync(CardFile file) - возвращает контент файла из карточки диалога с временем жизни Запрос или Задание. Параметр метода file должен быть получен из карточки диалога. Например: (await Dialog.GetDialogCardAsync(this.CancellationToken)).Files[0].
  • Dialog.SetFileContent(CardFile file, byte[] content) - сохраняет контент файла в карточку диалога с временем жизни Запрос.
  • Dialog.GetFileContainerAsync(IValidationResultBuilder validationResult = default, CancellationToken cancellationToken = default) - возвращает файловый контейнер карточки диалога с временем жизни Задание или Карточка. Добавление и изменение файлов не поддерживается для диалога с временем жизни Карточка.

Пример скрипта валидации:

if (Dialog.ButtonName == "aaa" ) { Dialog.Cancel = true; } else if (Dialog.ButtonName == "bbb") { Dialog.CompleteDialog = false; }

Сценарий сохранения

Сценарий, выполняемый при сохранении карточки диалога.

Контекст содержит:

  • Dialog.ButtonName - алиас нажатой кнопки.
  • Dialog.StoreMode - способ сохранения карточки диалога (время жизни диалога).
  • Dialog.GetDialogCardAsync(CancellationToken cancellationToken = default) - возвращает карточку диалога.
  • Dialog.GetFileContentAsync(CardFile file) - возвращает контент файла из карточки диалога с временем жизни Запрос или Задание. Параметр метода file должен быть получен из карточки диалога. Например: (await Dialog.GetDialogCardAsync(this.CancellationToken)).Files[0].
  • Dialog.SetFileContent(CardFile file, byte[] content) - сохраняет контент файла в карточку диалога с временем жизни Запрос.
  • Dialog.GetFileContainerAsync(IValidationResultBuilder validationResult = default, CancellationToken cancellationToken = default) - возвращает файловый контейнер карточки диалога с временем жизни Задание или Карточка.

Порядок выполнения сценариев:

Время жизни карточки диалога Действие Последовательность выполнения
Запрос Завершение диалога 1. Сценарий валидации диалога
Задание
Карточка
Завершение диалога
Закрытие диалога по кнопке закрытия окна с сохранением
1. Сценарий сохранения диалога
2. Сценарий валидации диалога

Tip

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

Вспомогательные методы для работы с карточкой диалога расположены в классе Tessa.Cards.CardTaskDialogHelper.

Дополнительно в скрипте инициализации можно выполнить предзаполнение карточки. Карточка доступа с помощью метода GetNewCardAsync. При открытии в диалоге существующей карточки, метод GetNewCardAsync вернёт открываемую карточку.

Управление историей

Этап управление историей предназначен для управления группами в истории заданий.

Группа, определяемая данным действием, становится текущей и используется впоследствии при определении группы истории заданий всеми этапами, если это не переопределено в группе настроек этапа Переопределение группы истории заданий.

Настройки этапа:

  • Группа истории заданий - группа истории заданий, которая будет родительской по отношению к элементам истории заданий, отправляемых этапами.
  • Родительская группа - группа истории заданий, являющейся родительской по отношению к группе, задаваемой в поле Группа истории заданий. Если указана, то будет выбрана родительская группа заданного типа с наибольшей итерацией.
  • Новая итерация - если флаг установлен, то будет создана новая итерация для группы истории заданий, заданной в поле Группа истории заданий.

Создать новую группу, которая будет использоваться для формирования истории заданий можно кнопкой + Создать из рабочего места Администратор в представлении Документы и задания -> Типы групп истории заданий.

Для новой группы указываются следующие данные:

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

Созданную группу можно указывать как в этапе “Управление историей”, так и в этапах с отправкой задания (“Согласование”, “Типовая задача” и т.д.).

Back to top