В новой версии в составе 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. Пожелания к формату статей тоже прошу писать в комментариях.
Добрый день. Спасибо за полезную статью. Воспользовался разделом, где нужно создать роль для нескольких исполнителей. Но получил ошибку в строчке
Функция GetRolePerformers ждет от нас 1 роль, а мы передаем набор ролей. Чтобы ошибка ушла, строчку
привел к виду
Александр, благодарю. В статью действительно закралась опечатка, поправила.
Добрый день. Не имею возможности проверить, к сожалению, но вот что непонятно:
Метод
с одним параметром, а при вызове передается 2 параметра:
или существует перегруженный GetRolePerformers() ?
Алексей, функция GetRolePerformers является функцией типа сущности PurchaseApprovalRole, при ее вызове необходимо первым параметром передавать ссылку на экземпляр сущности, т.е. параметр role, дополнительно же объявлен параметр task. Поэтому при вызове передается 2 параметра. Более подробно про функции их параметры и атрибуты можно почитать в разделе справки Функции
Добрый день! присоединюсь к вопросу выше. Вы пишите Создадим роль согласования ....GetRolePerformers() по сути public List<Sungero.CoreEntities.IRecipient> GetRolePerformers(Sungero.Docflow.IApprovalTask task) - это создание новой серверной функции с одним параметром? откуда тогда 2-а параметра при вызове? и как понять что GetRolePerformers является функцией типа сущности PurchaseApprovalRole?
Mikhail, в тексте статьи указано "реализуем новый метод GetRolePerformers() в серверных функциях справочника, созданного для новой роли (PurchaseApprovalRole)". Метод создается в серверных функциях справочника, что и служит описанием что GetRolePerformers является функцией типа сущности PurchaseApprovalRole.
Ок где можно почитать о том, чем отличается создание новой функции от создания нового метода судя по коду принцип схож
Mikhail, в данной ситуации метод и функция одно и то же.
Если разбираться детально, то и функция и метод - это некоторый фрагмент кода, который можно вызвать по имени и, опционально, передать ему какие-либо параметры. С этой точки зрения различий никаких нет.
С другой стороны, функция обычно включает в себя все необходимое для своей работы, а взаимодействие с внешним миром осуществляет через входные и выходные параметры, а также возвращаемое значение
Метод же для своей работы может использовать поля объекта, в котором определен.
Рекомендую ознакомится с разделом справки https://club.directum.ru/webhelp/directumrx/sds/index.html?sds_funktcii.htm
Добрый день! Написал свою вычисляемую роль и заметил что пользователи, которые попадают в роль, не отображаются в поле "Обязательные" карточки новой задачи на согласование, но если перейти в задаче на вкладку "Регламент", то на схеме видны все исполнители. Нужно что-то дополнительно где-то прописывать?
Саят, да, когда роль возвращает несколько согласующих надо дописать добавление их в поле Обязательные согласующие.
Алена, я думал это происходит автоматически. Хорошо, спасибо, попробую.
Алена, подскажите, пожалуйста, а где это можно сделать?
Если возвращать 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>
Денис, оформите пожалуйста замечание к справке по значку письма.
Авторизуйтесь, чтобы написать комментарий