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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  • Основной процесс – это главный процесс маршрута по карточке. Его вы можете видеть на вкладке Маршрут.

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

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

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

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

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

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

  • “Вход” в группу. Когда при выполнении процесса маршрут дошел до какой-то группы, то перед началом выполнения система перестраивает группу.

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

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

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

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

  • Затем выполняются сценарии инициализации всех групп (построение маршрута)

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

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

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

    • выполняются сценарии инициализации этих шаблонов этапов

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

    • строится маршрут по этой группе по подтвержденным этапам

    • выполняются сценарии постобработки для всех шаблонов, в т.ч. неподтвержденных

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

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

Например

В маршруте участвуют три группы: Группа 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 для всех трех групп. На этом моменте доступен полный маршрут по всем группам

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

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

    • проверяется вхождение текущего сотрудника в роли, указанные в поле “Роли” группы

    • если тайл глобальный (правая панель), то поле “Тип документа” группы игнорируется

    • если тайл контекстный (левая панель), то в маршрут попадают только группы, у которых в поле “Тип документа” присутствует тип текущего документа.

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

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

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

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

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

    • выполняются сценарии инициализации этих шаблонов этапов

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

    • строится маршрут по этой группе по подтвержденным этапам

    • выполняются сценарии постобработки для всех шаблонов, в т.ч. неподтвержденных

  • Затем для группы выполняется сценарий постобработки (построение маршрута).

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

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

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

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

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

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

  • Если в пересчитанной группе этапа “Пересчет маршрута” нет – выдается ошибка.

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

  • Если всё в порядке, управление передается на следующий этап в группе.

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

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

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

  • Если рантайм-условие истинно, то выполняется сценарий рантайм-инициализации (выполнение маршрута) группы.

  • Далее система по очереди выполняет этапы, входящие в группу, при этом для каждого этапа по очереди:

    • вычисляется условие

    • если условие истинно, то выполняется сценарий инициализации и выполняется собственно этап

    • при завершении этапа выполняется сценарий постобработки

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

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

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

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

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

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

Note

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

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

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

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

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

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

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

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

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

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

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

В правой панели нажмите тайл “Инициировать договор”.

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

Давайте попробуем отправить договор на согласование не внося изменений в сумму. Она меньше 100 000 и это значит, что договор должен сразу попасть на подписание.

Нажмем в левой панели кнопку “Запустить процесс”. Мы запустили маршрут прохождения документа.

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

Обратите внимание на сформированный маршрут на вкладке “Маршрут”.

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

Вернемся к процессу. В задании на подписание нажмите кнопку “В работу”, чтобы взять задание в работу.

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

Нажмите кнопку “Подписать”, вы увидите поле для ввода комментария. Нажмите “Подписать” еще раз для подтверждения завершения задания.

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

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

Давайте откажем в подписании. Нажмите кнопку “В работу”. Затем нажмите кнопку “Отказать”, введите комментарий (при отказе в подписании он обязательный) и нажмите еще раз “Отказать”.

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

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

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

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

Давайте инициируем новый цикл согласования. Возьмите в работу задание редактирования и нажмите кнопку “Начать новый цикл”.

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

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

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

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

Теперь давайте инициируем договор с большей суммой. Еще раз нажмите в правой панели кнопку “Инициировать договор”.

В открывшейся карточке договора введите сумму 200 000.

И опять в левой панели нажмите тайл “Запустить процесс”.

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

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

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

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

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

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

Давайте посмотрим на схему процесса.

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

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

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

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

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

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

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

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

Давайте создадим новую служебную записку. Нажмите тайл “Обычная СЗ” в группе тайлов “СЗ” на правой панели.

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

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

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

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

Теперь нажмите кнопку “В работу” в задании.

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

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

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

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

Давайте вернемся в карточку и заполним поле “Категория документа”. Выберите “Прочие СЗ” из выпадающего списка и опять отправьте на согласование.

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

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

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

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

Например, так:

И назад при завершении оно придёт так:

Мы же просто завершим задачу - заявка исполнена. Нажмите кнопку “Завершить” в задании и подтвердите завершение.

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

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

Давайте не примем выполнение. Мы чем-то недовольны. Нажмите кнопку “Не принято”, заполните комментарий и еще раз нажмите “Не принято” для подтверждения завершения.

И мы опять переходим на этап выполнения заявки. Система вновь отправила задание исполнителю с комментарием инициатора.

Давайте опять возьмём задание в работу и затем завершим его. Нажмите “В работу”, затем нажмите “Завершить” и на форме завершения задания еще раз нажмите “Завершить”.

Система вновь присылает нам задание на подтверждение. Возьмите его в работу, и нажмите “Выполнено”.

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

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

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

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

Вновь система создала карточку заявки и открыла её в диалоговом окне. Система запустит процесс и отправит задание на роль “Инициатор”.

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

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

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

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

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

Давайте не согласуем заявку. Нажмите “В работу”, далее “Не согласовать”, введите комментарий и далее еще раз нажмите “Не согласовать” для подтверждения.

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

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

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

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

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

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

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

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

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

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

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

Давайте создадим карточку протокола. В правой панели нажмите тайл “Протокол” в группе “Создать”.

Откроется новая карточка протокола. Заполните ее, указав нескольких сотрудников в поле “Участники”. Создать нового сотрудника вы можете в правой панели в группе тайлов “Создать → Роли → Персональная роль (сотрудник)”, если у вас есть административные права.

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

В моем случае после запуска карточка выглядит вот так.

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

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

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

Далее сохраните карточку сотрудника нажатием тайла “Сохранить” в левой панели или сочетанием [ctrl+s]. Обратите внимание, что заместитель должен появиться в поле “Сотрудники” группы “Состав роли” карточки сотрудника. Это может произойти с небольшой задержкой, т.к. за пересчет замещений отвечает служба Chronos, входящая в состав платформы, которой может быть нужно небольшое время.

Теперь вернемся к карточке протокола и в левой панели нажмем тайл “Обновить” или просто [F5]. Теперь мы можем исполнить задание. В форме задания написано, что мы его видим как заместитель исполнителя (справа от фамилии исполнителя).

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

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

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

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

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

  • Создаст карточку входящего по шаблону.

  • Выполнит для нее регистрацию.

  • Откроет карточку в рабочем месте пользователя.

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

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

В правой панели нажмите тайл “Зарегистрировать входящий”.

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

Полностью посмотреть настройки этого маршрута вы можете в рабочем месте “Администратор” в папке “Маршруты”.

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

Warning

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

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

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

  • Установить библиотеку схемы “RoutingSamples” из папки “Scheme”. Она включает в себя несколько новых состояний карточек.

  • Импортировать типы карточек из папки “Types” и представления из папки “Views”.

  • Добавить в рабочее место “Пользователь” (или в любое другое) узел с представлением RsEvents.

  • Установить библиотеку карточек “RoutingSamples.cardlib” из папки “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 - идентификатор типа документа текущей карточки

  • #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. Оба они в конце маршрута относительно этапов, добавленных пользователем вручную.

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

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

  • Шаблон 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 - идентификатор типа документа текущей карточки

  • #type_id - айди типа документа текущей карточки, если он не пуст, в противном случае айди типа карточки.

  • #doc_state - целое число, идентификатор состояния текущей карточки

  • #stage_template_id - идентификатор текущего шаблона

  • #stage_group_id - идентификатор группы, в которую включен текущий этап

  • #stage_type_id - идентификатор типа этапа

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  • Кнопка - процесс, запускаемый по плитке в левой(локальный) или в правой(глобальный) панели.

  • Действие - процесс, запускаемый по какому-либо событию

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

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

Описание - подробное описание нюансов этого вторичного процесса. Полезно для комментирования.

Режим - выбор режима вторичного процесса. В зависимости от режима отображаются специфичные настройки.

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

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

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

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

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

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

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

Состояния карточек - в каких состояниях карточек процесс доступен для запуска (видима кнопка). Применимо только к контекстным процессам и игнорируется для глобальных.

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

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

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

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

Режим “Кнопка”

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

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

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

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

Значок - алиас иконки для этого тайла. Доступные иконки вы можете увидеть в файле Thin Icons.png в папке с документацией в архиве с релизом платформы.

Размер плитки - размер плитки.

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

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

Группировать в “Действия” - тайл (вместе с группой, если она задана), будет отображаться в группе “Действия” контекстной панели. Применимо только для контекстных тайлов.

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

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

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

    Аналогично методу расширения 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 - идентификатор типа документа текущей карточки

  • #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); ...

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

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

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

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

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

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

В типовую конфигурацию Tessa входят следующие карточки маршрутов:

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

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

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

    • Запустить процесс - кнопка запуска основного процесса.

    • Зарегистрировать документ - регистрирует документ, отзывает активные задания, выполняет переход на следующую группу - всё это выполняется в основном процессе.

    • Отменить процесс - кнопка для прерывания основного процесса и перехода в состояние “Отмена”.

    • Отменить регистрацию - кнопка отмены регистрации.

    • Отозвать процесс - кнопка для прерывания основного процесса и перехода в состояние “Проект”.

    • Разослать задачи по решениям - кнопка для запуска вторичного процесса рассылки задач по Протоколу.

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

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

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

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

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

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

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

Например:

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

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

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

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

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

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

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

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

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

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

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

Note

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

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

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

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

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

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

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

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

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

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

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

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

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

Warning

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

Если при выполнении не удаётся найти класс содержащий сценарий относящийся к запрашиваемому объекту, то, в этом случае, создаётся исключение с текстом ошибки:

Пример текста ошибки при отсутствии класса содержащего скрипт объекта

Класс KrRuntime_Stage_4fe70ef042a94f809d2a07be17a46512 не найден. Проверьте наличие указанного объекта в системе. Более подробно см. Руководство администратора -> Маршруты документов -> Особенности работы сценариев и рекомендации по их использованию. Проверьте вывод компилятора на наличие ошибок компиляции.

Имя класса имеет следующий формат: <Префикс объекта>_<Алиас объекта>_<Идентификатор объекта>.

Идентификаторы используемые при компиляции скриптов маршрутов содержатся в классе Tessa.Extensions.Default.Server.Workflow.KrCompilers.SourceBuilders.SourceIdentifiers.

Доступные префиксы объектов:

  • SourceIdentifiers.KrStageCommonClass – Имя базового класса для классов, содержащий методы расширения.

  • SourceIdentifiers.KrDesignTimeClass – Имя класса, содержащего сценарий построения маршрута.

  • SourceIdentifiers.KrRuntimeClass – Имя класса, содержащего сценарий выполнения маршрута.

  • SourceIdentifiers.KrVisibilityClass – Имя класса, содержащего сценарий условия видимости.

  • SourceIdentifiers.KrExecutionClass – Имя класса, содержащего сценарий условия выполнимости процесса.

Доступные алиасы объектов:

  • SourceIdentifiers.StageAlias – Алиас генерируемого класса, содержащего скрипты этапа.

  • SourceIdentifiers.TemplateAlias – Алиас генерируемого класса, содержащего скрипты шаблона этапов.

  • SourceIdentifiers.GroupAlias – Алиас генерируемого класса, содержащего скрипты группы этапов.

  • SourceIdentifiers.SecondaryProcessAlias – Алиас генерируемого класса, содержащего скрипты вторичного процесса.

Идентификатор объекта.

Уникальный идентификатор объекта: этапа в карточке шаблона этапов, шаблона этапов, группы этапов или вторичного процесса.

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

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

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

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

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

  • При расчете условий сначала выполняется “Условное выражение”, если оно успешно (или не задано), то после выполняется 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> или нажать кнопку “Выполнить компиляцию” на вкладке “Результат компиляции”.

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

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

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

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

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

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

  • 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>) - асинхронно возвращает строго типизированную коллекцию строк из секции основной карточки.

    Пример

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

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

    Пример

    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).

    Пример

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

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

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

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

    • Если этап был добавлен ранее, то RowID будет перенесен, но все значения изменены на стандартные.

    • Если этап был добавлен ранее и изменен пользователем, то возвращается null.

    • Можно использовать только в скрипте построения шаблона этапов.

      Пример

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

    • Если этап был добавлен ранее и изменен пользователем, то возвращается этот этап.

    • Можно использовать только в скрипте построения шаблона этапов.

      Пример

      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, если этап изменен. Применимо только для типов этапов с множественными исполнителями (доступен в скрипте выполнения этапа и построения шаблона этапов).

    Пример

    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) этапа текущего процесса в обход объектной модели.

    Пример

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

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

    Пример

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

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

    Пример

    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-расширениях.

    Пример:

    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 можно записывать результат завершения какого-либо этапа, чтобы потом использовать этот результат в условии следующей группы

    Например:

    // Постскрипт этапа 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.

    Пример

    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 настройки. Набор настроек определяется структурой секций карточки настроек, связанной с типом этапа.

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

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

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

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

    Для примера, будем хранить в 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]. Скрытые этапы будут выделены серым цветом.

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

Для активации пропущенного этапа необходимо в режиме отображения скрытых этапов, если пользователь является администратором или в режиме отображения пропущенных этапов (тайл Другие → Показать пропущенные этапы или с помощью сочетания клавиш [Ctrl+Alt+H]), если у пользователя обычный уровень доступа, нажать кнопку “Активировать” или выбрать одноимённый пункт контекстного меню. Активировать этап можно только, если это разрешено правилом доступа “Редактирование маршрута”.

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

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

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

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

  • #user_id - идентификатор текущего пользователя

  • #user_name - имя текущего пользователя

  • #card_id - идентификатор карточки, для которой производится расчет

  • #card_type_id - идентификатор типа карточки, для которой производится расчет

  • #doc_type_id - идентификатор типа документа текущей карточки

  • #type_id - айди типа документа текущей карточки, если он не пуст, в противном случае айди типа карточки.

  • #doc_state - целое число, идентификатор состояния текущей карточки

  • #stage_template_id - идентификатор текущего шаблона

  • #stage_rowid - идентификатор строки этапа в маршруте

  • #stage_group_id - идентификатор группы, в которую включен текущий этап

  • #stage_type_id - идентификатор типа этапа

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

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

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

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

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

Подробнее сценарии описаны в следующем разделе.

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

Warning

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

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

  • #card_id - идентификатор карточки, для которой производится расчет

  • #card_type_id - идентификатор типа карточки, для которой производится расчет

  • #user_id - идентификатор текущего пользователя

  • #user_name - имя текущего пользователя

  • #stage_template_id - идентификатор текущего шаблона

  • #stage_template_name - название текущего шаблона

  • #stage_rowid - 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.

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

Подписание

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

  • В заданиях кнопки называются “Подписать” и “Отказать” вместо “Согласовать” и “Не согласовать”;

  • Состояние карточки при входе в этап устанавливается “На подписании”.

Доработка

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

Срок (рабочие дни) - срок задания в рабочих днях, допускаются дробные значения.

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

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

От имени (сотрудник или контекстная роль) - позволяет отправить задание от имени любого сотрудника.

Вид - вид задания.

Комментарий - комментарий к этапу.

Изменять состояние - если флажок установлен (по умолчанию), то при входе в этап состояние карточки меняется на “На доработке”. Снимите флажок, если вам не нужно такое поведение.

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

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

Управлять видимостью этапа - если флажок установлен (по умолчанию), то этап становится видимым при выполнении, иначе остаётся скрытым.

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

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

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

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

Note

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

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

Задача

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

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

Исполнители - любые роли в системе, можно указывать несколько. Если не установлен флажок “Отдельная задача каждому исполнителю”, то система объединит всех исполнителей в одну роль, на которую отправит задание. Исполнять его будет тот, кто первым возьмет задание в работу.

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

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

Первый исполнитель - ответственный - если флажок установлен, то первый исполнитель получит обычную задачу, а остальные - дочерние задачи.

Длительность (рабочие дни) - срок задания в рабочих днях. Допускаются дробные значения.

Дата выполнения - астрономическая дата выполнения задания. Можно указать либо это поле, либо “Длительность (рабочие дни)”.

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

Комментарий - текст задания.

Вид - вид задания.

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

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

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

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

Note

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

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

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

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

Вот так выглядит взятое в работу настраиваемое задание.

Срок (рабочие дни) - срок задания в рабочих днях. Допускаются дробные значения.

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

Исполнители - исполнители задания. Можно указывать любые роли.

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

Вид - вид задания.

Текст задания - текст задания.

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

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

Вариант завершения - название варианта завершения (кнопки в задании). Можно использовать локализацию.

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

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

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

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

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

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

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

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

Note

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

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

При завершении задания этап записывает в состояние этапа в коллекцию Tasks набор значений, описывающих все нюансы завершения задания. Элемент коллекции - это сериализованное состояние задания хранящееся в виде словаря Dictionary<string, object>.

// Обратиться к конкретному элементу массива можно по его индексу, например StageInfo.Tasks[i].OptionName // Получить количество элементов можно при помощи StageInfo.Tasks.Count() // Если задание одно, в массиве будет всегда один элемент. К его данным можно обращаться следующим образом: StageInfo.Tasks[0]

Вот пример набора параметров, которые записывает система.

{ "Tasks": [ { "RowID": "976f5b71-4130-46fe-8826-90513014bb24", "RoleID": "2778f2a8-e77b-4c15-9f23-2c56d1946099", "RoleName": "Инициатор согласования", "RoleTypeID": "b672e00c-0241-0485-9b07-4764bc96c9d3", "AuthorID": "3db19fa0-228a-497f-873a-0250bf0a4ccb", "AuthorName": "Admin", "AuthorPosition": null, "Action": 3, "TypeID": "9c6d9824-41d7-41e6-99f1-e19ea9e576c5", "TypeName": "KrUniversalTask", "TypeCaption": "$CardTypes_TypesNames_KrUniversalTask", "UserID": "3db19fa0-228a-497f-873a-0250bf0a4ccb", "UserName": "Admin", "OptionID": "bc390ea9-530b-4467-b352-e6842db2e6c5", "OptionName": "Выполнено", "Result": null, "Planned": "2018-07-14T11:04:47", "PlannedQuants": 79, "InProgress": "2018-07-11T11:05:40", "Digest": "Пожалуйста, подтвердите, что ваша СЗ исполнена. В этом случае нажмите \"Выполнено\". Если необходимо еще что-то сделать, пожалуйста, нажмите \"Не принято\" и введите ваш комментарий.", "ParentRowID": null, "HistoryItemParentRowID": null, "ProcessID": null, "ProcessName": null, "ProcessKind": null, "Postponed": null, "PostponedTo": null, "PostponeComment": null, "Comment": null, "CompletedByID": "3db19fa0-228a-497f-873a-0250bf0a4ccb", "CompletedByName": "Admin", "Completed": "2018-07-14T11:04:47.393Z" }, { "RowID": "1737a91c-f53f-4630-b3d7-ca8c87c461d2", "RoleID": "fe037e05-2c9e-4a51-8b01-15e11f1ae86a", "RoleName": "Департамент обеспечения", "RoleTypeID": "abe57cb7-e1cb-06f6-b7ca-ad1668bebd72", "AuthorID": "3db19fa0-228a-497f-873a-0250bf0a4ccb", "AuthorName": "Admin", "AuthorPosition": null, "Action": 3, "TypeID": "9c6d9824-41d7-41e6-99f1-e19ea9e576c5", "TypeName": "KrUniversalTask", "TypeCaption": "$CardTypes_TypesNames_KrUniversalTask", "UserID": "3db19fa0-228a-497f-873a-0250bf0a4ccb", "UserName": "Admin", "OptionID": "e4d4db89-4320-4fcb-aa1f-9d36e33ca614", "OptionName": "Не принято", "Result": "Пожалуйста, проверьте еще раз.", "Planned": "2018-07-14T11:04:47.393Z", "PlannedQuants::int": 79, "InProgress::dtm": "2018-07-11T11:07:56.963Z", "Digest": "Пожалуйста, подтвердите, что ваша СЗ исполнена. В этом случае нажмите \"Выполнено\". Если необходимо еще что-то сделать, пожалуйста, нажмите \"Не принято\" и введите ваш комментарий.", "ParentRowID": null, "HistoryItemParentRowID": null, "ProcessID": null, "ProcessName": null, "ProcessKind": null, "Postponed": null, "PostponedTo": null, "PostponeComment": null, "Comment": "Пожалуйста, проверьте еще раз.", "CompletedByID": "3db19fa0-228a-497f-873a-0250bf0a4ccb", "CompletedByName": "Admin", "Completed": "2018-07-14T11:04:47.393Z" } ] }

Основные параметры:

  • Comment - комментарий при завершении;

  • OptionID - идентификатор варианта завершения, выбранного пользователем;

  • OptionName - название варианта завершения, выбранного пользователем;

  • CompletedByID - идентификатор сотрудника, завершившего задание;

  • CompletedByName - отображаемое имя сотрудника, завершившего задание;

  • RowID - идентификатор задания;

  • RoleID - идентификатор роли, на которую назначено задание;

  • RoleName - название роли, на которую назначено задание.

Как описано выше, обращаться к ним можно из сценария пост-обработки в синтаксисе StageInfo.Tasks[0].OptionName. Далее, в зависимости от выбранного пользователем варианта завершения можно записать какие-то параметры в ProcessInfo и в зависимости от них выстроить дальнейший маршрут, пропустить или повторить этапы.

Регистрация

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

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

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

Срок (рабочие дни) - срок задания в рабочих днях. Можно использовать дробные значения.

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

Регистратор - исполнитель задания. Любая роль в системе.

От имени (сотрудник или контекстная роль) - позволяет отправить задание от имени любого сотрудника.

Вид - вид задания.

Комментарий - комментарий к этапу.

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

  • Редактировать карточку – дать права доступа на редактирование карточки регистраторам;

  • Редактировать любые файлы – дать права доступа на редактирование приложенных файлов для регистраторов.

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

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

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

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

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

Получатели - список ролей на которые будет отправлено ознакомление. Система объединит состав ролей, сформировав общий список сотрудников и затем каждому из них отравит на ознакомление документ.

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

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

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

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

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

  • {{sender}} - заменяется на имя отправителя;

  • {{comment}} - заменяется на сформированный комментарий;

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

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

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

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

Уведомление

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

После создания и сохранения карточки этап записывает идентификатор созданной карточки по ключу 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). Тем не менее все вторичные процессы, запущенные через ветвление (далее вложенные), сохраняются в сателлите родительского процесса (далее основной, не путать с первичным процессом).

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

Обратите внимание, что внутри этапа “Ветвление” также может запускаться вложенное “Ветвление”.

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

Пример получения параметров запускаемых вложенных процессов.

IDictionary<string, object> nestInfo = this.GetProcessInfoForBranch(<Идентификатор (RowID) строки в коллекции вторичных процессов>);

nestInfo["key"] = "value";

// Далее в скриптах запускаемого вложенного процесса в ProcessInfo.key будет располагаться значение "value".

Будьте внимательны, “<Идентификатор (RowID) строки в коллекции вторичных процессов>” - это идентификатор строки в секции KrForkSecondaryProcessesSettingsVirtual_Synthetic, а не идентификатор карточки вторичного процесса.

Пример создания ветки процесса

var branches = (IList<object>) Stage.SettingsStorage[KrConstants.KrForkSecondaryProcessesSettingsVirtual.Synthetic];

var branche = new Dictionary<string, object>(); branche[KrConstants.RowID] = Guid.NewGuid(); branche[KrConstants.ID] = this.CardID; branche[KrConstants.StageRowID] = this.Stage.RowID; branche[KrConstants.KrForkSecondaryProcessesSettingsVirtual.SecondaryProcessID] = <Идентификатор вторичного процесса>; // Тип значения: Guid. branche[KrConstants.KrForkSecondaryProcessesSettingsVirtual.SecondaryProcessName] = <Имя вторичного процесса>; // Тип значения: string.

branches.Add(branche);

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>((List<object>) this.Stage.InfoStorage[ForkStageTypeHandler.PendingProcesses], ForkStageTypeHandler.BranchInfoFactory);

Обратите внимание, при прерывании ветки ее 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<List<object>>(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.

Тип задания (обязательный) - определяет тип отправляемых заданий.

Дайджест - текст задания.

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

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

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

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

Note

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

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

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

  • TypedTaskContext.Task - пакет завершаемого задания. Вариант завершения находится в Task.OptionID;

  • TypedTaskContext.CompleteStage - флаг, используемый для указания обработчику этапа на необходимость завершения этапа. Если выставить в true, то этап будет завершен, активные задания отозваны и управление перейдет к следующему этапу;

  • TypedTaskContext.SendTaskAsync(Performer исполнитель, Guid? тип задания, DateTime? дата завершения, int? срок в рабочих днях, string дайжест задания, CancellationToken cancellationToken = default) - асинхронно отправляет задания в рамках этапа. Обязательным параметром является - “исполнитель”, остальные значения берутся из настроек этапа, если не указано иное;

  • TypedTaskContext.RevokeTaskAsync(Guid taskID или IEnumerable<Guid> taskIDs, CancellationToken cancellationToken = default) - асинхронного отзывает задание в текущем процессе по указанным идентификаторам.

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

// Получаем завершаемое задание 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; }

Создать файл по шаблону

Этап предназначен для создания файла по шаблону.

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

Более подробная информация о шаблонах файлов находится в разделе Шаблоны файлов и плейсхолдеры

Диалог

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

  • Вид - вид задания (только для асинхронных)

  • Дайждест - дайджест (описание) задания (только для асинхронных)

  • Текст кнопки в задании - название варианта завершения (только для асинхронных)

  • Тип карточки - тип карточки диалога (Если тип карточки содержит секцию “Satellites” (константа Tessa.Cards.Extensions.Templates.CardSatelliteHelper.SatellitesSectionName), то карточка считается сателлитом)

  • Шаблон - шаблон, по которому будет создана карточка.

  • Имя диалога - имя диалога для UI расширений (ICardEditorModel.DialogName). Позволяет фильтровать расширения только для текущего диалога

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

  • Время жизни диалога - указание того, с каким объектом ассоциируется карточка диалога

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

  • Задание - карточка сохраняется в поле Task.Settings задания в виде JSON объекта. Карточка существует, пока существует задание. Следует использовать, когда нужна возможность промежуточного сохранения результатов диалога.

  • Карточка - диалог сохраняется как полноценная карточка по таблицам секций. Карточка может быть независима от основной, либо быть сателлитом (содержать секцию “Satellites” (константа Tessa.Cards.Extensions.Templates.CardSatelliteHelper.SatellitesSectionName)). Если карточка является сателлитом, то вместе с удалением/импортом/экспортом основной карточки будут производиться соответствующие операции карточки сателлита. Для независимой карточки этого не происходит. Пример карточки-сателлита в типовом решении - KrExampleDialogSatellite.

  • Режим открытия диалога - определяет поведение при открытии карточки диалога:

  • Всегда

  • Не отображать автоматически

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

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

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

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

  • Алиас кнопки - название кнопки, используемое в скриптах

  • Текст - отображаемый текст кнопки

  • Тип - тип кнопки (Тулбар, диалоговая)

  • Иконка - алиас иконки для кнопок тулбара (Thin, Int)

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

В этапе есть два вида скриптов:

Скрипт валидации

В контексте доступна полная карточка, включая содержимое файлов.

Контекст содержит:

  • Dialog.Cancel - признак того, что необходимо прервать обработку диалога без закрытия окна. По умолчанию false, может быть выставлено в true.

  • 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. Сценарий сохранения

    2. Сценарий валидации

Tip

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

Вспомогательные методы для работы с карточкой диалога расположены в классе Tessa.Cards.CardTaskDialogHelper.

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

Управление историей

Этап управление историей предназначен для управления группами в истории заданий.

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

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

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

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

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

Для новой группы указываются следующие данные:

  • Название - название группы, можно использовать строки локализации

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

  • Описание - понятное описание для группы, не обязательно для заполнения

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

Back to top