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

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

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

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