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

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

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

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

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

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

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

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

Сценарий, определяющий ответственного, позволяет:
  1. Выбрать согласующего бухгалтера вручную.
  2. Поставить задачу согласования бухгалтеру, ответственному за данное юридическое лицо.
  3. Поставить задачу согласования главному бухгалтеру, если сумма договора больше N (в данном примере больше миллиона).
  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;
}