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);
}