Использование динамической зоны ответственности

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

Создадим справочник Наша организация со свойствами Наименование и Бухгалтер и процесс согласования договора с Динамической зоной ответственности согласующего.

Для того, чтобы определять Зону ответственности с помощью сценария, необходимо поменять Зону ответственности на Динамическую

При смене типа Дизайнер предложит создать переменную для хранения пользователя.

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

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

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

Сценарий, определяющий ответственного, позволяет:
  1. Выбрать согласующего бухгалтера вручную.
  2. Поставить задачу согласования бухгалтеру, ответственному за данное юридическое лицо.
  3. Поставить задачу согласования главному бухгалтеру, если сумма договора больше (в данном примере больше миллиона).
  4. Поставить задачу согласования главному бухгалтеру, если бухгалтер, отвечающий за выбранное юридическое лицо, не справляется с объемом (в данном примере более трех активных задач согласования).
При использовании сценариев для вычисления зоны ответственности, убедитесь, что этот сценарий всегда будет выполнятся корректно и вовремя. В противном случае, логика бизнес-процесса может быть нарушена, а его выполнение - приводить к ошибкам.

Пример сценария с использованием PublicAPI

Примечание
Актуальная документация по PublicAPI доступна по ссылке.
Внимание!
Сценарий, указанный ниже, актуален для версий системы ELMA до 3.12.1 включительно.

Текст сценария:

//если автор задачи не выбрал согласующего вручную, начинаем определять его сценарием
if (context.Soglasuschiy == null)
{
	var runningStatus = PublicAPI.Enums.Workflow.WorkflowInstanceStatus.Running;
	//создаем фильтр для нахождения активных экземпляров процесса
	var filter = PublicAPI.Processes.WorkflowInstance.Filter()
		.Statuses(runningStatus)
		.TaskName("Согласование договора").Filter;
	var count = PublicAPI.Processes.WorkflowInstance.Count(filter);
	//если запущенно более трех экземпляров, или сумма договора более миллиона, ставим задачу Главному бухгалтеру
	if (count > 3 || context.SummaDogovora >= 1000000)
	{
		//для этого определяем руководителя бухгалтера привязанного к выбранной организации
		var chiefs = context.Organizaciya.Buhgalter.OrganizationItems.ToArray()
		    .Union(context.Organizaciya.Buhgalter.OrganizationGroups)
		    .Select(organizationItem =>
		    {
		        var parentOrganizationItem = organizationItem.ParentItem;
		        while (parentOrganizationItem != null && parentOrganizationItem.User == null)
		            parentOrganizationItem = parentOrganizationItem.ParentItem;
		        return parentOrganizationItem != null ? parentOrganizationItem.User : null;
		    })
		    .Where(u => u != null);
		var chief = chiefs.First();
		//ставим руководителя в зону ответственности
		context.Soglasuschiy = chief;
	}
	//иначе ставим задачу обычному бухгалтеру привязанному к данной организации
	else
	{
		context.Soglasuschiy = context.Organizaciya.Buhgalter;
	}
}
Внимание!
Сценарий, указанный ниже, актуален для версий системы ELMA ниже 3.8.

Пространства имен:

using EleWise.ELMA.API;
using EleWise.ELMA.Workflow.Models;

Текст сценария:

//если автор задачи не выбрал согласующего вручную, начинаем определять его сценарием
if(context.Soglasuschiy == null)
{
//создаем фильтр для нахождения активных экземпляров процесса
var filter = InterfaceActivator.Create<WorkflowInstanceFilter>();
filter.Statuses = new List<WorkflowInstanceStatus>();
//только активные
filter.Statuses.Add(WorkflowInstanceStatus.Running);
//только задача согласующего
filter.TaskName = "Согласование договора";
//получаем количество активных экземпляров процесса по фильтру
var count = WorkflowInstanceManager.Instance.Count(filter);
//если запущенно более трех экземпляров, или сумма договора более миллиона, ставим задачу Главному бухгалтеру
if(count > 3 || context.SummaDogovora >= 1000000)
{
//для этого определяем руководителя бухгалтера привязанного к выбранной организации
var chiefs = context.Organizaciya.Buhgalter.OrganizationItems.ToArray()
.Union(context.Organizaciya.Buhgalter.OrganizationGroups)
.Select(organizationItem =>
  {
  var parentOrganizationItem = organizationItem.ParentItem;
  while (parentOrganizationItem != null && parentOrganizationItem.User == null)
  parentOrganizationItem = parentOrganizationItem.ParentItem;
  return parentOrganizationItem != null ? parentOrganizationItem.User : null;
  })
.Where(u => u != null);
var chief = chiefs.First();
//ставим руководителя в зону ответственности
context.Soglasuschiy = chief;
}
//иначе ставим задачу обычному бухгалтеру привязанному к данной организации
else
{
context.Soglasuschiy = context.Organizaciya.Buhgalter;
}

Пример сценария без использования PublicAPI

Пространства имен: 
using EleWise.ELMA.Model.Services;
using EleWise.ELMA.Workflow.Models;
using EleWise.ELMA.Workflow.Managers;

 Текст сценария:

//если автор задачи не выбрал согласующего вручную, начинаем определять его сценарием
if(context.Soglasuschiy == null)
{
//создаем фильтр для нахождения активных экземпляров процесса
var filter = InterfaceActivator.Create<WorkflowInstanceFilter>();
filter.Statuses = new List<WorkflowInstanceStatus>();
//только активные
filter.Statuses.Add(WorkflowInstanceStatus.Running);
//только задача согласующего
filter.TaskName = "Согласование договора";
//получаем количество активных экземпляров процесса по фильтру
var count = WorkflowInstanceManager.Instance.Count(filter);
//если запущенно более трех экземпляров, или сумма договора более миллиона, ставим задачу Главному бухгалтеру
if(count > 3 || context.SummaDogovora >= 1000000)
{
//для этого определяем руководителя бухгалтера привязанного к выбранной организации
var chiefs = context.Organizaciya.Buhgalter.OrganizationItems.ToArray()
.Union(context.Organizaciya.Buhgalter.OrganizationGroups)
.Select(organizationItem =>
  {
  var parentOrganizationItem = organizationItem.ParentItem;
  while (parentOrganizationItem != null && parentOrganizationItem.User == null)
  parentOrganizationItem = parentOrganizationItem.ParentItem;
  return parentOrganizationItem != null ? parentOrganizationItem.User : null;
  })
.Where(u => u != null);
var chief = chiefs.First();
//ставим руководителя в зону ответственности
context.Soglasuschiy = chief;
}
//иначе ставим задачу обычному бухгалтеру привязанному к данной организации
else
{
context.Soglasuschiy = context.Organizaciya.Buhgalter;
}