Примеры сценариев маршрутизатора

Материал из Intermech Wiki
Перейти к навигации Перейти к поиску

Общие принципы

В пользовательских сценариях маршрутизатора доступны глобальные переменные, при помощи которых можно получать доступ к свойствам текущего действия, его вложениям, переменным и вызывать функции Search API. Список свойств и методов того или иного интерфейса можно посмотреть в библиотеке типов бизнес сервера, например, открыв sbserver.exe при помощи Delphi. Назначение основных свойства и методов должно быть понятно из их наименования, так, например, действие (ISActivity), обладает следующими свойствами: Name (название), Attachments (вложения), Variables (переменные), Status (статус действия), StartedTime (дата старта) и т.д.

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

  • Activity: ISActivity - текущее действие
MsgBox Activity.Name 

– покажет сообщение с названием текущего действия)

  • AppServer : ISearchRDM – объект бизнес-сервера текущего пользователя
MsgBox AppServer.GetUserName(-1)

покажет сообщение "Системный администратор")

*При работе через Search API в сторонней программе ссылку на бизнес сервер можно получить через ITS4App.GetSbServer()

  • S4App (COM объект Search, переменная появилась в Search 8, доступна только при выполнении сценария на клиенте)

Позволяет обращаться к Search API (например, вызвать функции OpenDocument, GetFieldValue) пример- регистрация документа c:\test.txt в архиве, в переменной маршрутизатора Arc должен быть номер архива, после регистрации к вложениям действия добавляется архивная копия этого документа:

DocID = S4App.LogFileInArchiveNumber("C:\tesl.txt",Arc.asString)
Activity.Attachments.AddLink(DocID) ‘прикрепим этот документ как вложение
  • Все системные переменные*
if (SYS_STRONGSIGN.asString = "1") Then
 MsgBox "Строгий контроль подписей включен"
Else
 MsgBox "Строгий контроль подписей выключен"
end if
  • Все пользовательские переменные*

сравнение значений переменных:

if (Usr1.asString = Usr2.asString) Then
 MsgBox “Исполнителем двух заданий не может быть один и тот же человек”;

присвоение значения переменной:

MyVar.asString = 1

* к переменным, имеющим в своем названии символы, отличные от латинских, цифр и знака подчеркивания, по имени обращаться нельзя. Для доступа к таким переменным можно использовать конструкцию set Var =Activity.Variables.GetVariableByName("имя") и дальше обращаться к Var (или именовать нужные переменные исключительно символами [a..Z,0..1,_])

Функции сценариев, взаимодействующие с пользователем (например, показ сообщения MsgBox) работают только в режиме выполнения сценария клиентом.

Для успешного написания сценариев маршрутизатора нужно иметь представление о принципах и стандартных функциях выбранного языка программирования, наличие тех или иных функций определяется реализацией конкретного языка в Windows. Ссылки на некоторую документацию по скриптовым языкам можно найти в разделе См. также. Также не следует забывать, что, в отличие от VBScript, JScript - язык, чувствительный к регистру названий переменных, функций и т.д.
Сценарии маршрутизатора выполняются, в соответствии с настройками в шаблоне процесса, либо у назначенного пользователя (по нажатию кнопки "Отправить дальше" в почте), либо бизнес-сервером (автоматически при выполнении действия "Сценарий"). В случае выполнения на сервере выполнение производится от имени предыдущего пользователя по ходу маршрута (т.е. выполняя предыдущую задачу, пользователь неявно выполняет и последующие сценарии).

Значения переменных

Переменные типа “Список пользователей” и “Список строк” хранятся в своем внутреннем формате (см. ниже). Значением переменной типа “Архив” является числовой идентификатор архива. Для остальных типов переменных Var.AsString соответствует их значению.

Формат переменных типа “Список пользователей”

В каждой строке хранится пара значений, разделенных символом '='. Если список содержит несколько значений, строки разделяются переводом каретки. Формат строки со значениями:

ID=Kind, где ID идентификатор пользователя или группы, Kind - 0, если это пользователь, 1 - если это группа, 2 - переменная. Т.е. -1=0 - это пользователь “Системный администратор”.

Для понимания данного формата можно задать нужный набор пользователей/групп в качестве значения переменной, а затем посмотреть, что там реально хранится при помощи

msgbox uservar.AsString

Значение с Kind=1 (группа) и ID < -100 означает, что это должность. Идентификатор виртульной группы должности формируется так: -100-RANK_ID, т.е. группа -128 соответствует должности с RANK_ID=28.

Формат переменных типа “Список строк”

Значение переменных этого типа содержит её выбранное значение (первой строкой) и все её возможные значения (в последующих строках).

Пример получения выбранного значения переменной типа “Список строк”:

vals = Split(List.asString,vbCrLf,-1,1)
msgbox vals(0)

Повторное использование пользовательских функций

В сценариях на VBScript можно использовать конструкцию include, которая может загружать код из файла (например, с сетевого пути). Т.е. можно вынести какие-то часто используемые функции в файл, а в коде сценария вписать:

include("\\server\im\scripts\wf_lib.vbs")

Данная конструция позволяет сократить объем БД и позволяяет оперативно изменять текст скриптов без редактирования существующих шаблонов и перезапуска существующих процессов. Однако, в случае размещения в сетевой папке администратор должен обеспечить бесперебойный доступ к этой папке (требуется убедиться в отсутствии ограничений на количество подключений к сетевым папкам для установленной версии Windows). Также, внесение ошибок в такие функции будет немедленно отражаться на всех запущенных процессах, которые их используют.

Примеры сценариев

1. Вывод сообщений с перечислением обозначений всех прикрепленных документов и их владельцев

For i = 0 to Activity.Attachments.count-1
 Set Att = Activity.Attachments.Items(i)
 if (Att.AType = 0) or (Att.AType = 1) then ’обрабатываем только  раб. копии (0) и ссылки на документы (1)
  Set Doc = AppServer.GetDocument (Att.DocID, Att.Version)
  Set Params = Doc.GetParamsList
  MsgBox "Обозначение: " + Params.GetParamByName("DESIGNATIO").Value + _
  " , владелец: " + AppServer.GetUserName(Params.GetParamByName("DESIGNERID").Value)
 end if
Next

2. Изменение названия процесса

Среди вложений ищется ИИ (по типу документа, для примера: тип документа извещения = 100000, спецификации = 1, ТП = 3; типы других документов можно посмотреть в таблице DOCTYPES), если таковое найдено, название процесса формируется в виде ‘Изв.’ + Обозначение документа. Сценарий работает только, если выполняется сервером (в случае выполнения из почты пользователя переменная Activity.Owner не определена).

For i = 0 to Activity.Attachments.count-1
 Set Att = Activity.Attachments.Items(i)
if (Att.AType = 0) or (Att.AType = 1) then ’обрабатываем только  раб. копии (0) и ссылки на документы (1)
 if Att.DocType = 100000 Then 'ищем ИИ
  Set Doc = AppServer.GetDocument (Att.DocID, Att.Version)
  Set Params = Doc.GetParamsList
  Set Proc = Activity.Owner
  Proc.Name = "Изв." & Params.GetParamByName("DESIGNATIO").Value
  Exit For
 end if
end if
Next

3. Разбор значения переменной типа “список пользователей”

Всем вложенным документам устанавливается владелец, записанный в SYS_STARTER:

Parts = Split(SYS_STARTER.asString,vbCrLf,-1,1)
 PartInfo = Split(Parts(0),"=",-1,1)
 if (PartInfo(1) = "0") Then
  For i = 0 to Activity.Attachments.count-1
   Set Att = Activity.Attachments.Items(i)
   if (Att.AType = 0) or (Att.AType = 1) then
    Set Doc = AppServer.GetDocument (Att.DocID, Att.Version)
    Set Params = Doc.GetParamsList
    Params.GetParamByName("DESIGNERID").Value = PartInfo(0)
   end if
  Next
 end if

4. Вывод наименования архива для каждого вложения

set archives = AppServer.GetArchivesList
For i = 0 to Activity.Attachments.count-1
 Set Att = Activity.Attachments.Items(i)
if (Att.AType = 0) or (Att.AType = 1) then
 Set Doc = AppServer.GetDocument (Att.DocID, Att.Version)
 Set Params = Doc.GetParamsList
 arch_id = Params.GetParamByName("ARCHIVE_ID").Value
 set arc = archives.GetArchiveByID(arch_id)
 msgbox arc.Caption
end if
Next

5. Включаем вложенные документы в ручную выборку

(нужно знать идентификатор выборки (из таблицы SMPLIST), в примере 133 заменить на свой):

Set smp = AppServer.GetSample(133)
For i = 0 to Activity.Attachments.count-1
 Set Att = Activity.Attachments.Items(i)
 if (Att.AType = 0) or (Att.AType = 1) then 'документ
  smp.AddDocument(Att.DocID)
 end if
Next


6. Имена всех пользователей из переменной users записываются в переменную user_str

user_str = ""
vals = Split(users.asString,vbCrLf,-1,1)
for i = 0 to UBound(vals)-1
 u = Split(vals(i),"=")
 if u(1) = 0 then 'пользователь
  if user_str <> "" then
   user_str = user_str + ", "
  end if
  user_str = user_str + AppServer.GetUserName(u(0))
 end if
next

7. Универсальная конструкция для вызова Search API

Для написания универсальных скриптов, которые могут выполняться как на клиенте, так и сервером, использующих вызовы функций Search API, можно воспользоваться следующей конструкцией в начале сценария (далее для вызовов Search API следует пользоваться переменной S4Ap):

if SYS_EXECSIDE.AsString="SERVER" Then
 Set s4Ap = CreateObject("S4.TS4App")
 s4Ap.Login
else
 s4Ap = S4App
end if
…
s4ap.OpenArticle(artid)
key = s4ap.GetFieldValue_Articles ("Imbase_key")
…

8. Вывод наименований всех взятых на изменение документов из числа вложений в сообщение сценария

if sys_execside.asstring="SERVER" Then
 Set s4Ap = CreateObject("S4.TS4App")
 s4Ap.Login
else
 s4Ap = S4App
end if
s = ""
for i = 0 to Activity.Attachments.Count-1
 Set Att = Activity.Attachments.Items(i)
 checkedOut = false
 if Att.Atype = 0 then 'прикреплена рабочая копия
  checkedOut = true
 elseif Att.Atype = 1 then 'архивная копия, нужно определять статус
  s4Ap.OpenDocument(Att.DocID)
  if s4Ap.GetDocStatus<> 0 Then
   checkedOut = true
  end if
  s4Ap.CloseDocument
 end if
 if checkedOut then
  s = s & vbCrLf & "Документ (DocID=" & Att.DocID & ") " & Att.Name & "взят на изменение"
 end if
next
if s <> "" then
 Activity.Message.Text = s
end if

9. Установка значения параметра документа и/или изделия в нужное значение

*При запросе несуществующего параметра будет сгенерировано исключение, поэтому такие ситуации нужно обрабатывать при помощи On Error ..


For i = 0 to Activity.Attachments.count-1
 Set Att = Activity.Attachments.Items(i)
 DocID = 0
 VerID = 0
 ObjID = 0
 if (Att.AType = 0) or (Att.AType = 1) then 'прикреплен документ
  DocID = Att.DocID
  VerID = Att.Version
  ObjID = Att.ObjID
 end if
 
if (Att.AType = 4) then 'прикреплено изделие ObjID = Att.ObjID end if
if DocID <> 0 then Set Doc = AppServer.GetDocument (DocID, VerID) Set Params = Doc.GetParamsList Params.GetParamByName("Проверил").Value = "User" end if
if ObjID <> 0 then Set Obj = AppServer.GetObject (ObjID) Set Params = Obj.GetParamsList Params.GetParamByName("Расцеховка").Value = "test" end if
Next

10. Отправка сообщения пользователю

set router = AppServer.GetRouter
'получатель,тема,текст, ProcessID, ActivityID (могут быть -1, если не требуется связь с процессом)
router.createmessage -1,"subject","text",Activity.OwnerID,Activity.ID

11. Проверка права доступа на добавление документов в архив от имени текущего пользователя

Используется архив Demo (ID = 1), вместо него нужно подставить нужный идентификатор архива.

on error resume next
arAddObject = 101
set Arc = AppServer.GetArchivesList.GetArchiveByID (1)
Arc.CheckRight(arAddObject)
if (Err.Number <> 0) Then
 msgbox "Нет прав на добавление"
else
 msgbox "Права есть"
end if

12. Проверка, являются ли вложенные документы бумажными

on error resume next 'не реагировать на ошибки
 
For i = 0 to Activity.Attachments.count-1 Set Att = Activity.Attachments.Items(i)
if (Att.AType = 0) or (Att.AType = 1) then 'проверяем только раб. копии (0) и ссылки на документы (1) set Doc = Appserver.GetDocument(Att.DocID,Att.Version) Set Params = Doc.GetParamsList if Params.GetParamByName("arc_dir_id").Value = 0 Then MsgBox Doc.ObjectName & " бумажный" else MsgBox Doc.ObjectName & " файловый" end if end if Next

13. Получение списка групп пользователя

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

function GetUserGroupsStr(UserID: Integer; Expanded: Integer; GetGroupNames: Integer): WideString; safecall;

Expanded определяет, нужно ли возвращать все дерево групп (группы, в которые явно входит + группы, в которые входят эти группы), GetGroupNames указывает, возвращать наименования групп (1), или их идентификаторы (0).

set grList = Activity.AppServer.GetGroupsList
msgbox grList.GetUserGroupsStr(-1,1,1) ‘покажет группы, в которые входит SYSDBA

14. Возврат назад со cценария

Если действие “Сценарий” производит некий контроль, то при выполнении на сервере есть возможность вернуть выполнение назад при помощи присваивания Activity.ExecResult = -1. Нижеследующий пример проверяет, что в списке вложений присутствует спецификация и сборочный чертеж, иначе выполнение со сценария возвращается назад с записью предупреждения в сообщение:

spFound = false
sbFound = false

For i = 0 to Activity.Attachments.count-1 Set Att = Activity.Attachments.Items(i)
if (Att.AType = 0) or (Att.AType = 1) then 'обрабатываем только раб. копии (0) и ссылки на документы (1) Select Case Att.TypeName Case "Спецификация" spFound = true Case "Сборочный чертеж" sbFound = true End Select end if
Next
if (not spFound or not sbFound) then Activity.Message.Text = "В списке вложений должны присутствовать: Спецификация, Сборочный чертеж" Activity.ExecResult = -1 end if

Возврат назад (в начало маршрута или по стрелке) настраивается в Свойствах сценария на Вкладке "Откат"

15. Пример сдачи рабочих копий документов в архив сценарием

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

if sys_execside.asstring="SERVER" Then
 Set s4Ap = CreateObject("S4.TS4App")
 s4Ap.Login
else
 s4Ap = S4App
end if
for i = Activity.Attachments.Count-1 to 0 step -1 Set Att = Activity.Attachments.Items(i) if Att.Atype = 0 then 'рабочая копия DocID = Att.DocID s4Ap.OpenDocument(DocID) s4Ap.CheckIn s4Ap.CloseDocument
Activity.Attachments.Delete(i) 'открепим рабочую Activity.Attachments.AddLink(DocID) 'прикрепим архивную end if next

16. Поиск вложений по суффиксу в обозначении документа

Среди списка вложений ищутся документы, обозначение которых заканчивается на СБ или ЭСБ. Если таковые найдены, значение переменной маршрутизатора HaveSB устанавливается в 1:

Function EndsText(subtext, s)
 et = Right(s, Len(subtext))
 EndsText = UCase(et) = UCase(subtext)
end Function
For i = 0 to Activity.Attachments.Count-1 Set Att = Activity.Attachments.Items(i) if (Att.AType = 0) or (Att.AType = 1) then 'обрабатываем только раб. копии (0) и ссылки на документы (1) if EndsText(" СБ",Att.Designation) or EndsText(" ЭСБ",Att.Designation) Then 'ищем суффиксы СБ или ЭСБ HaveSB.asString = 1 Exit For end if end if Next


17. Проверка, что все вложения взяты на изменение + автоматическое взятие на изменение архивных копий

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

errs = ""
if sys_execside.asstring="SERVER" Then Set s4Ap = CreateObject("S4.TS4App") s4Ap.Login else s4Ap = S4App end if
s4Ap.QuietMode = 1 '"тихий" режим
for i = Activity.Attachments.Count-1 to 0 step -1 Set Att = Activity.Attachments.Items(i) if Att.AType = 1 then 'прикреплена архивная копия (1)
s4Ap.OpenDocument(Att.DocID) ds = s4Ap.GetDocStatus if (ds <> 0) and (ds <> s4Ap.GetUserID) Then errs = errs & vbCrLf & "Документ """ & Att.Designation & """ взят на изменение пользователем " & S4Ap.GetUserFullName_ByUserID(ds) else s4Ap.CheckOut
if (s4Ap.ErrorCode <> 0) Then errs = errs & vbCrLf & s4Ap.ErrorMessage else Activity.Attachments.Delete(i) 'открепим архивную Activity.Attachments.AddDocumentVersion Att.DocID, S4Ap.GetDocVersionID 'прикрепим рабочую end if end if
s4Ap.CloseDocument end if Next
if errs <> "" then Activity.Message.Text = "Во время попытки взять архивные копии прикрепленных документов на изменение произошли следующие ошибки: " & errs Activity.ExecResult = -1 end if

18. Чтение сообщений предыдущих исполнителей

Читается список сообщений, написанных пользователями, которые участвовали в текущем процессе до текущего действия, и записывается в пользовательскую переменную Msg:

s = ""
Set Msgs = Activity.Message For i = 0 to Msgs.PrevMessagesCount-1 ActName = Msgs.PrevMsgActivityName(i) CreateTime = Msgs.PrevMsgCreationTime(i) CreatorName = AppServer.GetUserName(Msgs.PrevMsgCreator(i))
s = s & "Действие: " & ActName & vbCrLf s = s & "Дата: " & CreateTime & vbCrLf s = s & "Исполнитель: " & CreatorName & vbCrLf s = s & "Текст: " & Msgs.PrevMsgText(i) & vbCrLf & "---------" & vbCrLf Next
Msg.AsString = s

См. также