DirectumRX Development Studio. Расширение возможностей регламентов согласования

42 14

В новой версии в составе DirectumRX появилась среда разработки – Development Studio, которая позволяет развивать систему под потребности компании, если возможностей настройки недостаточно.

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

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

Роль согласования с несколькими участниками

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

Создадим роль согласования как описано в разделе справки Добавление роли согласования, на шаге по вычислению сотрудника вместо перекрытия GetRolePerformer() реализуем новый метод GetRolePerformers() в серверных функциях справочника, созданного для новой роли (PurchaseApprovalRole):

/// <summary>
/// Получить список исполнителей из роли.
/// </summary>
/// <param name="task">Задача.</param>
/// <returns>Список исполнителей.</returns>
[Remote(IsPure = true), Public]
public List<Sungero.CoreEntities.IRecipient> GetRolePerformers(Sungero.Docflow.IApprovalTask task)
{
  var result = new List<Sungero.CoreEntities.IRecipient>();
  var document = task.DocumentGroup.OfficialDocuments.FirstOrDefault();
  var contract = Trade.Contracts.As(document);
  if (contract != null && _obj.Type == Purchases.PurchaseApprovalRole.Type.Experts)
  {
    foreach (var item in contract.Experts.Where(x => x.Expert != null))
      result.Add(item.Expert);
  }
  return result;
}

Переопределим логику серверной функции GetStageRecipients() из модуля Sungero.Docflow базового решения DirectumRX, данная функция вызывается при вычислениях исполнителей в обработчиках событий блоков схемы задачи и построении предметного отображения на закладке «Задачи» карточки документа. В серверных функциях перекрытого справочника ApprovalStage вызовем метод GetRolePerformers(), написанный на прошлом шаге.

/// <summary>
/// Получить исполнителей этапа без раскрытия групп и ролей.
/// </summary>
/// <param name="task">Задача.</param>
/// <param name="additionalApprovers">Доп.согласующие.</param>
/// <returns>Исполнители.</returns>
[Remote(IsPure = true), Public]
public override List<IRecipient> GetStageRecipients(Sungero.Docflow.IApprovalTask task,
List<IRecipient> additionalApprovers)
{
  var recipients = base.GetStageRecipients(task, additionalApprovers);
      
  var role = _obj.ApprovalRoles
        .Where(x => x.ApprovalRole.Type == Purchases.PurchaseApprovalRole.Type.Experts)
        .Select(x => Purchases.PurchaseApprovalRole.As(x.ApprovalRole)).Where(x => x != null)
        .SingleOrDefault();
      
  if (role != null)
  {       
    recipients.AddRange(Trade.Purchases.PublicFunctions.PurchaseApprovalRole.Remote.
      GetRolePerformers(role, task));
  }      
  return recipients;
}

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

Предупреждение в задании на согласование

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

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

Чтобы на этапе согласования происходила данная проверка, в карточку этапа с типом «Согласование» добавим новое логическое свойство Проверка полномочий. Для этого необходимо перекрыть справочник Sungero.Docflow.ApprovalStage.

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

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

var stage = ApprovalStages.As(_obj.Stage);
if (stage != null && stage.IsCheckAuthority == true)
{
 // Проверить полномочия текущего сотрудника.       
  var str = Purchase.PublicFunctions.GetInfoAboutAuthority(Sungero.Company.Employees.Current, 
    _obj.DocumentGroup.OfficialDocuments.FirstOrDefault());
 // Вывести предупреждение.
  if (!string.IsNullOrEmpty(str))
    e.AddInformation(Purchase.Resources.CheckAuthorityFormat(str));
}

Так это будет выглядеть в задании сотруднику:

Если проверку необходимо реализовать на этапе согласования с руководителем, то необходимо перекрывать задание Sungero.Docflow.ApprovalManagerAssignment.

Фиксация информации о согласовании с превышением лимита в тексте задания

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

Для этого в перекрытии задания Sungero.Docflow.ApprovalAssignment в событии До выполнения в аргумент e.Result допишем эту информацию:

if (_obj.Result == Result.Approved)
{
  var stage = ApprovalStages.As(_obj.Stage);
  if (stage != null && stage.IsCheckAuthority == true)
  {
    var str = Purchase.PublicFunctions.GetInfoAboutAuthority(Sungero.Company.Employees.Current, 
      _obj.DocumentGroup.OfficialDocuments.FirstOrDefault());
    if (!string.IsNullOrEmpty(str))
      e.Result = Purchase.Resources.CheckAuthorityAssignmentFormat(e.Result, str);
  }
}

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

В тексте задания могут быть зафиксированы любые другие необходимые в дальнейшем данные.

Голосование в процессе согласования

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

Рассмотрим пример: на последнем этапе согласования документов по тендеру среди участников тендерного комитета проводится открытое голосование по предложенному поставщику.

Для реализации данного кейса добавим новое свойство Голосование в карточку этапа с типом «Задание».

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

Для этого перекроем задание Sungero.Docflow.ApprovalSimpleAssignment и добавим свойство Vote с типом перечисление.

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

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

В дальнейшем планируем писать еще статьи, посвященные темам «Как это сделать?». Поделитесь в комментариях, с какими еще ситуациями вы сталкивались или какие еще рекомендации вы бы хотели видеть на DIRECTUM Club. Пожелания к формату статей тоже прошу писать в комментариях.

42
Авторизуйтесь, чтобы оценить материал.
5
Александр Волошин

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

recipients.AddRange(Trade.Purchases.PublicFunctions.PurchaseApprovalRole.Remote.
      GetRolePerformers(role, task));

Функция GetRolePerformers ждет от нас 1 роль, а мы передаем набор ролей. Чтобы ошибка ушла, строчку 

.Select(x => Purchases.PurchaseApprovalRole.As(x.ApprovalRole)).Where(x => x != null);

привел к виду

.Select(x => Purchases.PurchaseApprovalRole.As(x.ApprovalRole)).Where(x => x != null).FirstOrDefault();

 

Елена Попова

Александр, благодарю. В статью действительно закралась опечатка, поправила. 

Алексей Кузнецов

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

Метод 

GetRolePerformers(Sungero.Docflow.IApprovalTask task)

с одним параметром, а при вызове передается 2 параметра:
 

recipients.AddRange(Trade.Purchases.PublicFunctions.PurchaseApprovalRole.Remote. GetRolePerformers(role, task)

или существует перегруженный GetRolePerformers() ?

Елена Попова

Алексей, функция GetRolePerformers является функцией типа сущности PurchaseApprovalRole, при ее вызове необходимо первым параметром передавать ссылку на экземпляр сущности, т.е. параметр role, дополнительно же объявлен параметр task. Поэтому при вызове передается 2 параметра. Более подробно про функции их параметры и атрибуты можно почитать в разделе справки Функции

 

Mikhail Popkov

Добрый день! присоединюсь к вопросу выше. Вы пишите Создадим роль согласования ....GetRolePerformers()  по сути public List<Sungero.CoreEntities.IRecipient> GetRolePerformers(Sungero.Docflow.IApprovalTask task) - это создание новой серверной функции с одним параметром? откуда тогда 2-а параметра при вызове? и как понять что  GetRolePerformerявляется функцией типа сущности PurchaseApprovalRole?

Елена Попова

Mikhail,  в тексте статьи указано "реализуем новый метод GetRolePerformers() в серверных функциях справочника, созданного для новой роли (PurchaseApprovalRole)". Метод создается в серверных функциях справочника, что и служит описанием что GetRolePerformerявляется функцией типа сущности PurchaseApprovalRole.

Mikhail Popkov

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

Елена Попова

Mikhail, в данной ситуации метод и функция одно и то же.

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

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

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

Рекомендую ознакомится с разделом справки https://club.directum.ru/webhelp/directumrx/sds/index.html?sds_funktcii.htm

Саят Казырханов

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

Алена Перейма

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

Саят Казырханов

Алена, я думал это происходит автоматически. Хорошо, спасибо, попробую.

Святослав Романов

Алена, подскажите, пожалуйста, а где это можно сделать?

Святослав Романов: обновлено 23.07.2021 в 12:16
Денис Зайцев

Если возвращать List<Sungero.CoreEntities.IRecipient>, то можно получить ошибку

Unable to cast object of type 'System.Collections.Generic.List`1[Sungero.CoreEntities.IRecipient]' to type 'System.Collections.Generic.List`1[Sungero.Company.IEmployee]

Возможно это актуально для более новых версий RX, чем для версии на момент написания статьи, но сейчас даже в справке 4.6 предлагается IRecipient, а нужно возвращать List<Sungero.Company.IEmployee>

Елена Попова

Денис, оформите пожалуйста замечание к справке по значку письма.

Авторизуйтесь, чтобы написать комментарий