7.7.5. Маршруты согласования#
7.7.5.1. Описание раздела#
Скрипты для динамической настройки маршрутов согласования: назначение участников на этапы, передача параметров из отчётов, проверка условий для ветвления процесса и контроль доступности исполнителей.
7.7.5.2. Скрипты#
7.7.5.2.1. Назначение участников маршрута из атрибутов документа#
Используется чтобы назначить пользователей на этапы маршрута на основе значений, хранящихся в атрибутах документа. Поддерживает одновременное назначение нескольких ролей (например, исполнитель, подписывающий, согласовывающий). Для каждой роли выполняется проверка существования учётной записи; при необходимости допускаются исключения на основе параметров документа.
Место применения: Приложение "Управление бизнес-процессами" > Справочники > Схема бизнес-процесса > [Процесс] > Редактировать > Вкладка "Процедуры" > Поле процедуры выполнения.
Тип: JEXL-скрипт
// Получаем информацию о бизне-процессе и записываем переменную с ним и документом
var idProc = Bpm_PrStateApi.getProcessId(idpPrState); // Получаем id поцесса
var idvDoc = Bpm_PrDocApi.getProcDocByPrState(idpPrState); // Получаем id состояния процесса для которого выполняется процедура
var ropProc = Bpm_ProcessApi.load(idProc); // Записываем процесс в переменную как объект выполняемой процедуры
// Получаем параметры-коды объектных привилегий схемы бизнес-процесса и создаем субъектов бизнес-процесса как объекты выполняемой процедуры
var paramArr = param.split(";");
// Исполнитель
var svEmployee = paramArr[0];
var ropTargetOptEmployee = Bpm_PrSubjectApi.getByPSSubject(ropProc, svEmployee);
var ropTargetEmployee = ropTargetOptEmployee.get();
var semployee = `
select coalesce(pers.iduser, 0) as iduseremployee
from wf_doc doc
left join bs_employee e on cast(doc.jobjattrs_dz ->> 'idR1EmployeeSng' as int8) = e.id
left join bs_person pers on e.idperson = pers.id
where doc.gid = '${idvDoc}'
`;
// Подписывающий
var svEmployeeSign = paramArr[2];
var ropTargetOptEmployeeSign = Bpm_PrSubjectApi.getByPSSubject(ropProc, svEmployeeSign);
var ropTargetEmployeeSign = ropTargetOptEmployeeSign.get();
var semployeesign = `
select
coalesce(pers.iduser, 0) as iduseremployeesign
,bo.scode as bocode
from wf_doc doc
left join bs_employee e on cast(doc.jobjattrs_dz ->> 'idR1EmployeeSignSng' as int8) = e.id
left join bs_person pers on e.idperson = pers.id
left join bs_bisobj bo on doc.idbisobj = bo.id
where doc.gid = '${idvDoc}'
`;
// Согласовывающий
var svEmployeeMain = paramArr[1];
var ropTargetOptEmployeeMain = Bpm_PrSubjectApi.getByPSSubject(ropProc, svEmployeeMain);
var ropTargetEmployeeMain = ropTargetOptEmployeeMain.get();
var semployeemain = `
select coalesce(pers.iduser, 0) as iduseremployeemain
from wf_doc doc
left join bs_employee e on cast(doc.jobjattrs_dz ->> 'idR1EmployeeMainSng' as int8) = e.id
left join bs_person pers on e.idperson = pers.id
where doc.gid = '${idvDoc}'
`;
// Установка пользователей с селекционного экрана в качестве подписантов
// Исполнитель
var lemployee = sql(semployee).asList();
for (w:lemployee){
if(w.iduseremployee == 0) {raise('Внимание! Для справки не указан исполнитель.');}
Bpm_PrSubjUserApi.register(ropTargetEmployee , w.iduseremployee, 0B, 0B);
}
// Подписывающий
var lemployeesign = sql(semployeesign).asList();
for (w:lemployeesign){
if(w.iduseremployeesign == 0 and w.bocode != '0100') {raise('Внимание! Для справки не указан подписывающий.');}
Bpm_PrSubjUserApi.register(ropTargetEmployeeSign , w.iduseremployeesign, 0B, 0B);
}
// Согласовывающий
var lemployeemain = sql(semployeemain).asList();
for (w:lemployeemain){
if(w.iduseremployeemain == 0) {raise('Внимание! Для справки не указан согласовывающий.');}
Bpm_PrSubjUserApi.register(ropTargetEmployeeMain, w.iduseremployeemain, 0B, 0B);
}
7.7.5.2.2. Назначение участника маршрута из связанного документа#
Используется чтобы назначить на этап маршрута пользователя, указанного в связанном документе (например, куратор в договоре). Извлекает данные через связи между сущностями и регистрирует пользователя как исполнителя. При отсутствии данных вызывает ошибку.
Место применения: Управление бизнес-процессами > Справочники > Схема бизнес-процесса > [Процесс] > Редактировать > Вкладка "Процедуры" > Поле процедуры выполнения.
Тип: jexl
var idProc = Bpm_PrStateApi.getProcessId(idpPrState);
var svSubj = param;
var idvDoc = Bpm_PrDocApi.getProcDocByPrState(idpPrState);
var ropProc = Bpm_ProcessApi.load(idProc);
var ropTargetOpt = Bpm_PrSubjectApi.getByPSSubject(ropProc, svSubj);
var ropTarget = ropTargetOpt.get();
var s = `
select coalesce (u.iduser, 0) as iduser
from cnt_contract r
join bs_employee e on r.idcuratoremployee = e.id
join bs_person u on e.idperson = u.id
where r.gid = ${idvDoc}
`;
var l = sql(s).asList();
for (w:l){
if(w.iduser == 0) {raise('Внимание! Для договора не указан куратор.');}
Bpm_PrSubjUserApi.register(ropTarget, w.iduser, 0B, 0B);
}
7.7.5.2.3. Проверка доступности исполнителей на этапе маршрута#
Используется чтобы проверить, доступен ли хотя бы один исполнитель на этапе маршрута (наличие активного режима работы). Если все назначенные пользователи и профили недоступны, устанавливается флаг и отправляется системное уведомление, предотвращая зависание задачи.
Место применения: Управление бизнес-процессами > Справочники > Схема бизнес-процесса > [Процесс] > Редактировать > Вкладка "Процедуры" > Поле процедуры выполнения.
Тип: JEXL-скрипт
/*
spCheckAvailableExecutorByPsSubject
Проверка свободных исполнителей по субъекту процесса
*/
/*
Проверка свободных исполнителей по субъекту процесса для выполнения задачи
Параметры: {системное имя субъекта процесса};{параметр для записи числового значения}
*/
var NNumber = function (number) { new ("ru.bitec.app.gtk.lang.NNumber", number); }
// param - строка с произвольными параметрами jexl скрипта
var paramArr = param.split(";");
var svSignSubj = paramArr[0];
var svParamName = paramArr[1].toString();
// idpPrState- параметр jexl скрипта с id состояния
var ropProc = Bpm_PrStateApi.getProcess(idpPrState);
var ropSignOpt = Bpm_PrSubjectApi.getByPSSubject(ropProc, svSignSubj);
if (!empty(ropSignOpt)) {
var ropSign = ropSignOpt.get();
var aroSign = ropSign.copyAro();
var idPrSubject = aroSign.id;
var sqlUser = `select btkUser.gid from Btk_User btkUser
where btkUser.id in (select prsubjuser.idUser from Bpm_PrSubjUser prSubjUser
where prsubjuser.idPrSubject = `+idPrSubject+`)`;
var gidavUser = sql(sqlUser).asList();
var sqlAcProfile = `select acProfile.gid from Btk_AcProfile acProfile
where acProfile.id in (select prSubjAcProfile.idAcProfile from Bpm_PrSubjAcProfile prSubjAcProfile
where prSubjAcProfile.idPrSubject = `+idPrSubject+`)`;
var gidavAcProfile = sql(sqlAcProfile).asList();
gidavUser.addAll(gidavAcProfile);
if (!Bpm_ProcessApi.checkVarExists(ropProc, svParamName)) {
raise(`Переменной`+svParamName+` для данного процесса не существует!!`);
}
Bpm_ProcessApi.setProcessVar(ropProc, svParamName, 1);
for (gidvResource : gidavUser) {
var query = `select t.id
from Mpr_OperModeResource t
where t.gidResource = '`+gidvResource.gid+`'
and t.dbegin < now() and (t.dend is null or t.dend > now())`;
var lst = sql(query).asList();
if (lst.size() == 0) {
Bpm_ProcessApi.setProcessVar(ropProc, svParamName, 0);
}
}
if (Bpm_ProcessApi.getProcessVar(ropProc, svParamName).toLong() == 0.0) {
var idvState = Bpm_PrStateApi.load(idpPrState).copyAro().idState();
var svCaption = Btk_ClassStateApi.load(idvState).copyAro().sCaption();
selection.coreRep().application().notifications().notify("Задача, направленная по маршруту, не может быть выполнена, поскольку в данный момент отсутствуют доступные исполнители. Текущее состояние задачи: "+svCaption);
}
}
7.7.5.2.4. Инициализация документа параметрами селекционного экрана отчёта#
Используется чтобы передать значения фильтров селекционного экрана отчёта в атрибуты создаваемого документа (например, бизнес-объект, период). Обеспечивает корректную инициализацию документа при запуске маршрута согласования из отчётной формы.
Место применения: Настройки системы > Отчёты > Настройка отчётных форм > [Отчетная форма] > Редактировать > Тип документа создаваемого по отчёту > [Документ] > Поле "Процедура установки атрибутов документа".
Тип: JEXL-скрипт
var rop = Wf_DocApi.load(idDoc); // Загружаем объект WF_Doc как переменную
var ropRpt = Rpt_EntityExecApi.load(idEntityExec); // Создаем объект селекционного экрана в кэше
var jsonString = ropRpt.jParams.toString(); // Получаем набор параметров
var json = toJObject(jsonString); // Записываем полученные параметры в json
var jData = Wf_DocApi.getJData(rop); // Передаем json с параметрами в Wf_Doc
var idBisObj = json.getLong("flt_idbisobj"); // Из Json параметров получаем значение конкретного атрибута строкой
/*
// Возможность получения данных в т.ч. запросом
var idacceptmnemo = json.getString("flt_idaccept");
var sql_text = `select id from bs_employee be where smnemocode_dz = '` + idacceptmnemo + `' and be.sposition = '` + idacceptpos + `'`;
*/
// Установка значений
Wf_DocApi.setidBisObj(rop, idBisObj);
// Wf_DocApi.setidBisObj(rop, json.getLong("flt_idBisObj")); // Альтернативный вариант сеттера
// Wf_DocApi.setObjAttrValue(rop, 'nYear', json.getLong("flt_nyear")); Сеттер для Json атрибута
7.7.5.2.5. Установка флага маршрута по учётным данным документа#
Используется чтобы анализировать учётные данные документа (например, проводки) и устанавливать флаг в переменной процесса при выполнении заданного условия (например, использование счёта, содержащего «76»). Результат может использоваться для условного перехода в маршруте согласования.
Место применения: Управление бизнес-процессами > Справочники > Схема бизнес-процесса > [Процесс] > Редактировать > Вкладка "Процедуры" > Поле процедуры выполнения.
Тип: JEXL-скрипт
// Процедура проверки наличия счета "76" в контировке одной из позиций приходного акта
var svVar = param; // Переменная для параметра, в который будет записан результат процедуры
var ropProc = Bpm_PrStateApi.getProcess(idpPrState); // Переменная для хранения контекста выборки конкретного маршрута
var gidvDoc = Bpm_PrDocApi.getProcDocByPrState(idpPrState); // Переменная для хранения документа - объекта маршрута
// Переменная для хранения результата sql-запроса, через выполнение которого проверяется наличие в контировке позиции приходного акта счета "76"
var s =
`
select case when (acc.sCode like '%76%') then 1 else 0 end as isacc76
from bbb_objdistr bo
join bs_acc acc on bo.idaccacc = acc.id
join stm_actindet aid on bo.gidobj = aid.gid
join stm_actin ai on aid.idDoc = ai.id
where ai.gid = '`+ idvDoc + `'
`;
/*
Цикл, который будет выполнять sql запрос для каждой позиции контировки приходного акта и если найдет хотя бы одну,
у которой счет учета услуг содержит код "76" запишет значение переменной для проверки условия наличия счета "76" в маршруте true
*/
var l = sql(s).asList();
for(w:l){
if (l.isacc76 == 1)
Bpm_ProcessApi.setProcessVar(ropProc , "isacc76", true);
}