Скрипт действия по событию

Общее описание скрипта

Скрипт задает действие, которое автоматически будет выполняться при наступлении события.

Место настройки скрипта

Форма добавления действия по событию типа "Скрипт" и форма редактирования действия по событию типа "Скрипт", см. Скриптовое действие по событию.

Когда выполняется скрипт

Скрипт выполняется при наступлении инициирующего события и после проверки условий выполнения действия по событию.

Асинхронное действие по событию:

  • скрипт может выполняться с некоторой задержкой относительно инициировавшего его события;
  • скрипт не влияет на завершение выполнения события с объектом.

    Пример. Скрипт настроен для события изменение объекта. В системе выполнено изменение объекта. Не зависимо от этого выполняется скрипт действия по событию, инициированный изменением объекта. Скриптовое действие по событию может быть выполнено или не выполнено.

Синхронное действие по событию:

  • скрипт выполняется сразу после наступления инициирующего события и проверки условий (если они заданы), на время выполнения скрипта блокируется интерфейс системы;
  • скрипт влияет на завершение выполнения события с объектом, если выполнение скрипта действия по событию невозможно, инициирующее его событие и все совершенные в результате него действия отменяются.

    Пример. Скрипт настроен для события изменение объекта. В системе выполняется изменение объекта и скрипт действия по событию, инициированный изменением объекта. Если скриптовое действие по событию успешно выполнено, изменение объекта будет завершено. Если скриптовое действие по событию не выполнится, объект не будет изменен.

Взаимодействие с внешней системой: скрипт выполняется в очереди обработки внешних операций. Пример внешней операции (взаимодействие с внешней системой), запрос информации из внешних ресурсов (SOAP, REST).

Внутренняя операция: скрипт выполняется в очереди обработки внутренних операций.

Переменные и их значения

Глобальные переменные:

  • user — пользователь, инициализировавший событие. Является объектом класса "Сотрудник" (employee).

    Если событие инициализировал суперпользователь, то user=null.

    Если событие инициализировано скриптом (скриптовое действие по событию, скрипт на вход в статус), то переменная user берется из контекста инициировавшего его скрипта.

    Пример: пользователь выполнил изменение атрибута → произошло изменение статуса объекта (действие по событию) → произошло изменение ответственного (действие на вход в статус) → произошло оповещение (действие по событию) .Во всех скриптах этой цепочки переменная user должна содержать сотрудника, выполнившего первоначальное изменение атрибута.

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

    Пример цепочки: пользователь изменяет статус объекта → инициируется событие "Смена статуса" → выполняется редактирование объекта (скрипт действия при входе в статус редактирует переменную subject через utils.edit) → инициируется событие "Изменение объекта" → отправляется оповещение (скрипт действия по событию "Изменение объекта"). Если в данной цепочке в переменную utils.edit не передать значение user, то в скрипте действия по событию user=null.

    Пример: Передача значения переменной user в следующий скрипт цепочки действий редактировании объекта.

    def serviceCall = utils.get('serviceCall$3801');
    utils.edit(serviceCall, ['title' : 'qwerty', '@user' : user]);
  • ip — ip-адрес рабочего места пользователя user. Если действие выполняется автоматически системой (а не пользователем), то переменная не определяется.
  • appVersion — версия приложения.
  • api — используется для обращения к методам api, например api.utils, api.ldap, api.timing, см. Методы API;
  • modules — используется для обращения к скриптовому модулю и конкретному методу, определенному в нем, с помощью конструкции: modules.{код модуля}.{имя метода}({параметры метода}...), см. Скрипт текста модуля;
  • logger — используется для отладки скриптов и позволяет вывести в лог на указанный уровень переданную строку, см. Оформление и отладка скриптов.
  • utils — синоним api.utils.

Переменные контекста subject, oldSubject и currentSubject:

  • subject — текущий объект, над которым производится действие (значение переменной может быть null). В переменной subject хранятся значения атрибутов объекта на момент добавления действия по событию в очередь.

    Для событий "Добавление комментария" и "Редактирование комментария" в качестве subject передается объект, к которому добавлен комментарий.

  • oldSubject — объект до выполнения события, в случаях если происходило его изменение (редактирование атрибутов, смена статуса, изменение признака массовости для запроса, иначе значение переменной = null.

    Для события "Редактирование комментария" в качестве oldSubject передается объект источник комментария. Событие "Добавление комментария" не является изменением объекта, поэтому в значении переменной будет null.

    При использовании переменной значение атрибутов типа "Обратная ссылка" всегда будет равно null.

  • currentSubject — текущий объект, над которым производится действие. В переменной currentSubject хранятся значения атрибутов объекта на момент обработки действия по событию с учетом изменений, которые внесли уже отработавшие действия по событию. Переменная currentSubject недоступна для пользовательских действий по событию.

Особенности использования переменных subject, currentSubject и oldSubject в скрипте действия по событию:

  • В зависимости от типа обрабатываемого события, значение переменных может быть = null.

    В действии по событию "Добавление объекта" есть subject, а oldSubject = null, в действии по событию "Удаление объекта" subject = null, но есть oldSubject, т.к.при удалении объекта уже не существует текущего объекта.

  • При добавлении объектов subject существует (subject!= null), но многие его атрибуты еще не заполнены (subject['attr_code']== null).
  • Любое действие по событию, даже синхронное, при добавлении объекта срабатывает только после окончания создания объекта, поэтому сама переменная subject и все ее атрибуты будут существовать.

Переменные контекста:

  • changedAttributes — список кодов атрибутов, значения которых изменились при редактировании объекта.

    Вычислимые атрибуты не попадают в контекстную переменную changedAttributes, так как значения вычислимых атрибутов (в том числе атрибута типа "Атрибут связанного объекта") вычисляются при отображении, не хранятся в базе данных и не редактируются в интерфейсе оператора.

    При редактировании атрибута типа "Обратная ссылка" на форме редактирования объекта, атрибут попадает в список измененных атрибутов. При изменении атрибута типа "Обратная ссылка" также изменяется объект, на который ведет прямая ссылка.

  • notification — оповещение.
  • cardObject — объект, из карточки которого было инициировано действие. Если действие инициировано НЕ из карточки объекта, то cardObject = null.

    Например, при создании объекта с помощью полноэкранной формы добавления cardObject = null, а при создании объекта с помощью формы быстрого добавления, вызванной с карточки объекта, cardObject будет содержать этот объект.

    cardObject = null для событий "Добавление комментария" и "Добавление файла".

    Если действие по событию вызвано скриптом (не из консоли):

    • Для синхронного действия по событию cardObject = объекту, с карточки которого было вызвано первое действие, и которое в последствии вызывало текущее.
    • Для асинхронного действия по событию cardObject = null.
  • objectListContext — критерии выборки объектов, если действие было инициировано из списка. Используя данную переменную можно получить коллекцию объектов, отображаемых в списке

  • geo — информация о местоположении мобильного устройства, при инициации события из мобильного клиента.

    В переменной хранятся сведения о широте (latitude) и долготе (longitude) текущего местоположения мобильного устройства.

    Значение переменной может быть null, зависит от разрешения использования геолокации на мобильном устройстве и настройки элемента меню карточки объекта в мобильном приложении, вызывающего данное действие по событию (включен параметр "Передавать геопозицию устройства").

Особенности скрипта

Особенности использования параметра "Атрибуты, передаваемые в контекст":

  • Если параметр заполнен, то в очередь обработки действий по событиям передаются только атрибуты, указанные в данном параметре.

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

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

Особенности для системных событий и эскалации

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

Переменные контекста, доступные в скрипте действия по системным событиям и эскалации

Переменные контекста:

  • sourceObject — в действиях по событиям на добавление объекта в системе (объект / комментарий / файл) sourceObject это добавленный объект (объект / комментарий / файл)

    Для событий "Добавление комментария" и "Редактирование комментария" в качестве sourceObject передается объект источник комментария.

  • comment — текст комментария, заполненный при смене ответственного или при смене статуса.
  • isCommentPrivate — признак приватности комментария, заполненного на форме смены статуса или форме смены ответственного:

    • true — комментарий, заполненный при смене ответственного или при смене статуса, приватный;
    • false — комментарий не приватный.
  • escalationLevel (доступна для действий при эскалации) — уровень эскалации (целое число, начинается с 1). Уровень эскалации характеризует текущую стадию выполнения процедуры эскалации для данного объекта, см. Эскалация.
  • mention — параметры упоминания объекта (атрибута, в котором использовались упоминания). Переменная доступна для действия по событию "Упоминание в рамках выбранных объектов".
    • mention.changedAttribute — измененный атрибут типа "Текст в формате RTF". Если упоминание добавлено в рамках комментария, то содержит 'text';
    • mention.newMentions — список идентификаторов новых упоминаний;
    • mention.untouchedMentions — список идентификаторов неизмененных упоминаний;
    • mention.removedMentions — список идентификаторов удаленных упоминаний.
  • mentions — список атрибутов, в которых использовались упоминания, в формате:

    mentions == [код_атрибута_1: mention, код_атрибута_2:mention...]

    Переменная доступна для действий по событию "Добавление комментария", "Редактирование комментария", "Добавление объекта", "Редактирование объекта", "Смена статуса", "Смена ответственного".

Особенности скрипта

  • Особенности использования в скрипте методов utils.find, utils.count и т.д.: в зависимости от различных условий текущий объект, над которым выполняется действие по событию, может учитываться или не учитываться в результатах, возвращаемых методами utils.find, utils.count и т.д. Для получения ожидаемого результата рекомендуется ситуацию с текущим объектом в скрипте обрабатывать отдельно. Для получения всех сотрудников с определенными свойствами, кроме текущего сотрудника, можно использовать конструкцию вида:

    utils.find('employee', [UUID: op.not(subject.UUID)])

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

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

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

Примеры скрипта

1. Скрипт при изменении названия объекта добавляет комментарий, содержащий информацию о старом названии

(сравнивает значение атрибута до выполнения операции и после ее выполнения):

if (oldSubject.title != subject.title) {
api.utils.create('comment', ['text': "Старое название: " + oldSubject.title, 'source' : subject.UUID]);
}

(проверяет факт изменения атрибута по наличию его кода в переменной changedAttributes):

if (changedAttributes.contains('title')) {
api.utils.create('comment', ['text': "Старое название: " + oldSubject.title, 'source' : subject.UUID]);
}

2. Скрипт изменяет статус запроса на предыдущий по истории при добавлении комментария пользователем

//ПАРАМЕТРЫ------------------------------------------------------------
//Коды состояний, из которых можно переводить в предыдущее состояние
def ALLOWED_STATES = [
'resumed',
'test2']
//ОСНОВНОЙ БЛОК--------------------------------------------------------
def stateEvt = utils.lastState(subject)
def lastStateCode = stateEvt.stateCode
def currentStateCode = stateEvt.newStateCode
if (ALLOWED_STATES.contains(subject.state))
{
utils.edit(subject, ['state' : lastStateCode])
logger.debug("change sc: " + subject.title + " state from: " + currentStateCode+" to: " + lastStateCode + " successful")
}

3. Скрипт при принятии запроса в персональную ответственность переводит запрос в указанный статус.

//ПАРАМЕТРЫ------------------------------------------------------------
//Коды состояний запроса, для которых будет работать скрипт.
def ALLOWED_STATES = ['registered', 'test3'] 
//Состояние, в которое запрос будет переведен, если запрос принят в персональную ответственность
def TARGET_STATE = 'accepted' 
//ОСНОВНОЙ БЛОК--------------------------------------------------------
if (subject.responsibleEmployee != null && ALLOWED_STATES.contains(subject.state))
{
utils.edit(subject, ['state' : TARGET_STATE])
}

Особенности для пользовательских событий

Скрипт задает действие, которое автоматически будет выполняться при наступлении пользовательского события с объектом.

Пользовательское событие — произвольное действие с объектом, определяемое пользовательским сценарием (скриптом).

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

  • params — значения параметров действия по событию, заполняемых в интерфейсе на форме выполнения пользовательского действия по событию, см. Настройка параметров пользовательского действия.

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

    Чтобы использовать другую логику переменной params, необходимо заменить в существующих скриптах название своей переменной "params" на какое-то другое.

  • source — строка, способ вызова события (OBJECT_LIST из списка объектов, OBJECT_CARD из карточки).
  • cardObject — объект, из карточки которого было вызвано событие. Переменная доступна, если событие вызвано из карточки объекта.
  • subjects — объекты, выбранные в списке объектов (если событие вызвано из списка объектов), или текущий объект (если событие вызвано из карточки объекта).

    Переменная содержит только те объекты, относительно которых у текущего пользователя есть право на выполняемое действие. Если прав нет, subjects = null.

  • subject — произвольный объект из коллекции subjects (если событие вызвано из списка объектов), или текущий объект (если событие вызвано из карточки объекта). Если у текущего пользователя нет права на выполняемое действие, subject = null
  • list — все объекты списка. Количество объектов коллекции ограничивается 1000.

    Переменная доступна, если событие вызвано из списка объектов.

    Метод limitExceeded() возвращает true, если лимит превышен, и часть объектов списка не попали в данную коллекцию. Возвращает false, если в коллекции 1000 и меньше объектов.

  • result — устанавливает действие, производимое после пользовательского события. Используется только для синхронных действий по событию.

    Методы, доступные в переменной result см. Скрипты на пользовательские события (кнопка-скрипт)

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

  • params = null, если действие на пользовательское событие с настроенными параметрами было инициировано из мобильного приложения.
  • geo — информация о местоположении мобильного устройства, при инициации события из мобильного клиента.

    В переменной хранятся сведения о широте (latitude) и долготе (longitude) текущего местоположения мобильного устройства.

    Значение переменной может быть null, зависит от разрешения использования геолокации на мобильном устройстве и настройки элемента меню карточки объекта в мобильном приложении, вызывающего данное действие по событию (включен параметр "Передавать геопозицию устройства").

  • queuedDate — дата и время добавления действия в очередь синхронизации для действий, выполненных в офлайн-режиме работы мобильного приложения (время передается в часовом поясе сервера). Если действие было выполнено онлайн, то queuedDate = null.

    Описание работы офлайн-режима и действий, доступных в нем:

  • isFromMobile: true — действие по событию вызвано из мобильного приложения; false — нет.

Особенности скрипта

Особенности скрипта для веб приложения:

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

Особенности скрипта для мобильного приложения:

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

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

def objParams = [:];
  if (params?.totalValueJson)
{
  utils.edit(subject, [totalValueJson: params?.totalValueJson]);
  modules.dynamicFieldsEA.saveEmbeddedApplitactionData(subject, objParams, user)
}
utils.edit(obj, objParams);

Особенности передачи атрибутов на формы

ДЛЯ ЛЮБОГО КЛАССА. Скрипт передает атрибуты на форму редактирования:

  • Атрибуты типа metaClass .

    Результат выполнения:

    • начальный статус "зарегистрирован" — форма открывается, сохранение формы не возможно (ошибка "Объект уже находится в новом статусе");
    • начальный статус другой или его нет — форма открывается и сохраняется, тип объекта не изменяется.
  • Атрибуты типа states.

    Результат выполнения: форма не открывается.

  • Атрибуты типа license.

    Результат выполнения: форма не открывается.

  • Атрибут типа secGroups.

    Результат выполнения:

    • атрибут не заполнен — форма открывается и сохраняется, атрибут заполняется;
    • атрибут заполнен — внутренняя ошибка приложения.

ДЛЯ ЛЮБОГО КЛАССА. Скрипт передает атрибуты на форму добавления:

  • Атрибуты типа metaClass .

    Результат выполнения: форма открывается и сохраняется, атрибут заполняется.

  • Атрибуты типа states.

    Результат выполнения: форма не открывается.

  • Атрибуты типа license.

    Результат выполнения: форма не открывается.

  • Атрибут типа secGroups.

    Результат выполнения: форма открывается и сохраняется, атрибут заполняется.

Для класса "Запрос" (serviceCall). Скрипт передает атрибуты на форму редактирования:

  • Атрибуты типа client.

    Результат выполнения: форма открывается, сохранение формы не возможно (ошибка "Указано несколько клиентов привязки").

  • Атрибуты типа agreement/service.

    Результат выполнения:

    • значение подходит остальной привязке — форма открывается и сохраняется, значение атрибута изменяется;
    • значение НЕ подходит остальной привязке — форма открывается, сохранение формы не возможно (ошибка "Отсутствие связи").
  • Атрибуты типа metaClass .

    Результат выполнения:

    • начальный статус "зарегистрирован" — форма открывается, сохранение формы не возможно (ошибка "Объект уже находится в новом статусе");
    • начальный статус другой или его нет — форма открывается и сохраняется, тип объекта не изменяется.

Для класса "Запрос" (serviceCall). Скрипт передает атрибуты на форму добавления:

  • Атрибуты типа metaClass и agreement/service.

    Результат выполнения: форма открывается, сохранение формы не возможно (внутренняя ошибка приложения).

  • Атрибуты типа client (передается команда или отдел).

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

Пример скрипта

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

subjects.each {
object ->
utils.edit(object, ['subscribers':object.subscribers + user])
}