Скрипт кастомизации оповещения

Категория скрипта "Кастомизация оповещений действий по событию".

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

Скрипт кастомизации уточняет параметры отправки оповещения или само отправляемое сообщение.

С помощью скрипта кастомизации можно изменить следующие параметры:

  • Параметры отправки оповещения: адрес и имя отправителя, адрес технической поддержки и т.д.
  • Получатели оповещения:
    • Список адресов-получателей оповещения.
    • Список сотрудников-получателей оповещения.
  • Получатели копии (скрытой копии) оповещения:
    • Список адресов-получателей копии (скрытой копии) оповещения.
    • Список сотрудников-получателей копии (скрытой копии) оповещения.
  • Тема оповещения.
  • Заголовок оповещения.
  • Список файлов, прикрепляемых к оповещению.

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

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

  • Форма добавления действия по событию (оповещение), см. Оповещение по email.
  • Форма редактирования действия по событию (оповещение).

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

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

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

Нет возвращаемого значения.

Некоторые значения можно вложить в ассоциативный массив для последующего использования в теле оповещения.

Пример: notification.scriptParams['comm'] = "Это самый важный текст" .

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

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

  • 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 — текущий объект, над которым производится действие.

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

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

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

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

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

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

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

    • true — комментарий, заполненный при смене ответственного или при смене статуса, приватный;
    • false — комментарий не приватный.
  • notification — текущее оповещение, для которого выполняется настройка.
    • notification.parameters (пример 1).
      • from — адрес отправителя.

        При изменении параметра в скрипте, важно учитывать ограничения используемого сервера, например, для сервера smtp.gmail.com допустимо использовать только подтвержденные реальные адреса.

        Чтобы подменять адрес отправителя, необходимо выполнить настройку своего почтового клиента. Пример настройки можно посмотреть в справке почтового клиента (пример настройки для Gmail).

      • name — имя отправителя;
      • feedbackAddress — адрес электронной почты, на который будут автоматически отсылаться сообщения о серверных ошибках;
      • outgoingServer — код подключения к серверу исходящей почты;
      • characterEncoding — кодировка текста, по умолчанию 'UTF-8';
      • transliterateSubject — транслитерация заголовков писем, по умолчанию false.

    Адрес электронной почты для отправки оповещения должен отличаться от email для подключения к серверу входящей почты.

    Сравнение, поиск, изменение и удаление email адресов в notification.to, notification.cc, notification.bcc может производиться с учетом регистра. Регистрозависимость email адреса устанавливается в конфигурационном файле dbaccess.properties (параметр use.Email.allow.uppercase), см. dbaccess.properties

    • notification.to — ассоциативный список адресов-получателей оповещения <Адрес электронной почты (email сотрудника, выбранный при создании оповещения; email сотрудника, обладающего выбранными ролями; дополнительный email адрес, введенный в специальное поле) : Имя адресата>.

      Переменная позволяет:

      • изменять или добавлять адреса-получателей оповещения (пример 2);
      • удалять электронный адрес из списка получателей оповещения (пример 3).
    • notification.toEmployee — список сотрудников, которые будут добавлены к списку получателей оповещения (пример 4).
    • notification.toRemoveEmployee — список сотрудников, которые будут удалены из списка получателей оповещения.
    • notification.cc — ассоциативный список адресов-получателей копии оповещения <Адрес электронной почты : Имя адресата> (пример 5).
    • notification.ccEmployee — список сотрудников-получателей копии оповещения (пример 7).

      В настройках одного оповещения не допускается одновременное использование методов notification.cc, notification.ccEmployee (notification.bcc, notification.bccEmployee) и переменной currentRecipient, см. Переменная "currentRecipient". При сохранении настроек оповещения будет выведено сообщение об ошибке.

    • notification.bcc — ассоциативный список адресов-получателей скрытой копии оповещения <Адрес электронной почты : Имя адресата> (пример 8).
    • notification.bccEmployee — список сотрудников-получателей скрытой копии оповещения (пример 10).
    • notification.subject — тема оповещения (пример 11).

      В теме оповещения допустимо использование глобальных переменных, возвращающих значение определенного атрибута или комментария объекта. Переменные начинаются с символа $ и заключаются в фигурные скобки {}, например, ${subject.title}.

      При использовании переменных тема оповещения должна заключаться в одинарные кавычки.

      В этом случае строка в атрибуте будет восприниматься как есть и произвольный groovy-код, указанный в атрибуте выполнен не будет. При использовании двойных кавычек этот код будет выполнен, что приведет к возможности несанкционированного редактирования объекта и уязвимости.

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

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

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

  • isFromMobile: true — действие по событию вызвано из мобильного клиента; false — нет.
  • cardObject — объект, из карточки которого было инициировано действие.

    Если действие инициировано НЕ из карточки объекта, то cardObject = null.

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

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

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

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

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

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

  • lang — локаль текущего оповещения, для которого выполняется настройка.

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

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

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

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

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

  • Текст оповещения через notification изменять не допускается.
  • Скрипт кастомизации оповещения доступен, если действие по событию — "Оповещение".
  • Сначала выполняется скрипт, затем генерируется текст оповещения!
  • Если включена локализация, то при выполнении скрипта вместо одного оповещения формируется несколько экземпляром оповещений — по одному на каждый язык. Скрипт кастомизации выполняется отдельно для каждого оповещения на каждом языке, в той локали, которая используется в формируемом оповещении.

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

1. Изменение параметров отправки оповещения:

  • адрес отправителя на 'sample@company.com';
  • имя отправителя на 'Иванов Иван Иванович';
  • адрес электронной почты, на который будут автоматически отсылаться сообщения о серверных ошибках на 'feedback@company.com'.
def parameters = notification.parameters;
parameters.from = 'sample@company.com'; 
parameters.name = 'Иванов Иван Иванович'; 
parameters.feedbackAddress = 'feedback@company.com'; 

2. Изменение или добавление адреса 'name@company.com' в список получателей оповещения:

notification.to['name@company.com'] = 'Title';

3. Удаление электронного адреса 'name@company.com' из списка получателей оповещения:

notification.to.remove('name@company.com');

4. Добавление одного сотрудника в список получателей оповещения:

notification.toEmployee << empl;

5. Изменение или добавление адреса 'name@company.com' в список получателей копии оповещения:

notification.cc['name@company.com'] = 'Title';

6. Удаление электронного адреса 'name@company.com' из списка получателей копии оповещения:

notification.cc.remove('name@company.com');

7. Добавление одного сотрудника в список получателей копии оповещения:

notification.ccEmployee << empl;

8. Изменение или добавление адреса 'name@company.com' в список получателей скрытой копии оповещения:

notification.bcc['name@company.com'] = 'Title';

9. Удаление электронного адреса 'name@company.com' из списка получателей скрытой копии оповещения:

notification.bcc.remove('name@company.com');

10. Добавление одного сотрудника в список получателей скрытой копии оповещения:

notification.bccEmployee << empl;

11. Замена темы оповещения на 'Пример темы оповещения':

notification.subject = 'Пример темы оповещения';

12. Добавление метки в начало темы оповещения:

notification.subject = 'Метка: ' + notification.subject;

13. Добавление или изменение заголовка оповещения:

notification.setHeader('In-Reply-To', '52D635DD.90108@company.com')'

где:

  • 'In-Reply-To' (headerName) — название заголовка.
  • '52D635DD.90108@company.com' (headerValue) — значение указанного заголовка

14. Список файлов, прикрепляемых к оповещению:

def files = utils.files(subject)
notification.attachments.addAll(files)

15. Добавление значения "Это самый важный текст" для последующего использования в теле оповещения:

notification.scriptParams['comm'] = "Это самый важный текст"

Использование в тексте оповещения или теме:

${notification.scriptParams['comm']}

16. Добавление контактного email-адреса в список получателей оповещения

Copy
//Категория: Кастомизация оповещения
//Назначение: Скрипт добавляет контактный email-адреса в список получателей оповещения.
        
//ПАРАМЕТРЫ----------------------------------------------------------
def CLIENT_EMAIL = 'clientEmail' // Код атрибута "Контактный е-мэйл"
def CLIENT_NAME = 'clientName' // Код атрибута "Контактное лицо"

//ОСНОВНОЙ БЛОК------------------------------------------------------
def clientEmail = subject[CLIENT_EMAIL]
notification.to[clientEmail] = subject[CLIENT_NAME]

17. Исключение автора действий из получателей оповещения

Copy
//Категория: Кастомизация оповещения
//Назначение: Скрипт исключает автора действий из получателей оповещения.
 
//ОСНОВНОЙ БЛОК-----------------------------------------------------
if(null != user) // текущий пользователь - не суперпользователь
{
notification.to.remove(user.email)
}

18. Отправка оповещений с разных адресов в зависимости от клиента основной привязки запроса

Copy
//Категория: Кастомизация оповещения
//Назначение: Скрипт для отправки писем с разных адресов в зависимости от типа клиента основной привязки запроса.

//ПАРАМЕТРЫ----------------------------------------------------------
def CLIENT_MATACLASS='fiz' 
// код типа клиента, для которого оповещения должны отправляться с другого адреса
def EMAIL_FOR_CUSTOM_CLIENS='support@company.ru' 
// адрес, с которого будет отправляться письмо для выбранного типа клиентов.

//ОСНОВНОЙ БЛОК------------------------------------------------------
if(CLIENT_MATACLASS.equals(subject.client.metaClass['_case']))
{
notification.parameters.from=EMAIL_FOR_CUSTOM_CLIENS
notification.parameters.feedbackAddress=EMAIL_FOR_CUSTOM_CLIENS
}

19. Прикрепление к оповещению файлов текущего объекта (subject):

Если указан атрибут LINKED, то скрипт прикрепляет файлы связанного бизнес-объекта.

Copy
//Категория: Кастомизация оповещения
//Назначение: Скрипт прикрепляет к оповещению файлы текущего объекта (subject).
//Если указан атрибут LINKED, то скрипт прикрепляет файлы связанного бизнес-объекта.

//ПАРАМЕТРЫ----------------------------------------------------------
def LINKED = 'linked' //атрибут текущего объекта типа "Ссылка на бизнес-объект"

//ФУНКЦИИ------------------------------------------------------------
def exctractAttr(object, String code)
{
try
{
if(code)
return object[code]
}
catch (e)
{
logger.error "не удалось извлечь атрибут '$code'"
}
return null
}
def addFilesToAttachments(files)
{
notification.attachments.addAll(files)
logger.debug "к оповещению прикреплено ${files.size()} файлов"
}
 
//ОСНОВНОЙ БЛОК------------------------------------------------------
logger.debug "Прикрепление файлов текущего объекта..."
addFilesToAttachments(utils.files(subject))
logger.debug "Прикрепление файлов связанного объекта..."
def linked = exctractAttr(subject, LINKED)
addFilesToAttachments(linked ? utils.files(linked) : [])

20. Добавление в текст оповещения последнего комментария к объекту

Если комментарий отсутствует в оповещении указано "отсутствует".

Copy
//Категория: Кастомизация оповещения
//Назначение: Cкрипт отправляет в письме оповещения последний комментарий, если комментарий отсутствует в оповещении указано "отсутствует"

//ИСПОЛЬЗОВАНИЕ ПЕРЕМЕННОЙ-------------------------------------------
// В тело оповещения вставляется переменная: ${notification.scriptParams['comm']}

//ОСНОВНОЙ БЛОК------------------------------------------------------
def commentList = utils.comments(subject)
notification.scriptParams['comm'] = commentList.isEmpty() ? "отсутствует" : commentList[commentList.size() - 1].text

21. Добавление получателей оповещения из атрибутов

Copy
//Категория: Кастомизация оповещения
 //Назначение:
 /**
  * Данный скрипт оперирует следующими понятиями:
  * - ПОЛУЧАТЕЛЬ
  *      Атрибут содержащий данные необходимые для отправки оповещения.
  *      Получатели могут быть либо строкой, либо ссылкой на бизнес-объект, либо набором ссылок на бизнес-объекты, либо обратной сссылкой.
  *      Если получатель - строка, она должна содержать адрес эл. почты.
  *      Если получатель - ссылка(ки) на бизнес-объект, бизнес-объект должен иметь атрибут с кодом "email" (например, класс "Сотрудник")

  * - ТЕКУЩИЙ ОБЪЕКТ (subject)
  *      Объект который стал причиной отправки оповещения. Например, если оповещение вызвано сменой статуса запроса, текущим объектом будет запрос.
       
  * - ПОЛУЧАТЕЛЬ ТЕКУЩЕГО ОБЪЕКТА - задается параметром RECIPIENTS.
        
  * - СВЯЗАННЫЙ ОБЪЕКТ - задается параметром LINKED_OBJECTS
  *      Объект связанный с текущим при помощи одного из атрибутов.
  *      Атрубуты связи могут иметь любой из следующих типов:
  *          - ссылка на бизнес-объект
  *          - набор ссылок на бизнес-объекты
  *          - обратная ссылка
  *      Бизнес-объект может быть любого типа.

  * - ПОЛУЧАТЕЛЬ СВЯЗАННОГО ОБЪЕКТА - задается параметром LINKED_RECIPIENTS.
  *
  * Алгоритм работы:
  *      Скрипт ищет ПОЛУЧАТЕЛЕЙ оповещения в атрибутах ТЕКУЩЕГО ОБЪЕКТА и/или в атрибутах СВЯЗАННЫХ ОБЪЕКТОВ.
  *      Если находит, добавляет к списку получателей оповещения. Если не находит, пишет сообщение в лог и продолжает поиск.
  */
        
//ПАРАМЕТРЫ----------------------------------------------------------
def RECIPIENTS = [
//получатели текущего объекта (коды атрибутов объекта subject)
'',
''
]
def LINKED_OBJECTS = [
//связанные объекты (коды атрибутов объекта subject)
'',
''
]
def LINKED_RECIPIENTS = [
//получатели связаных объектов (коды атрибутов связанных объектов)
'',
''
]
def LOGGING_IS_ENABLED = false // true - логирование включено, false - логирование отключено
//ФУНКЦИИ------------------------------------------------------------
def foreach(objects, Closure closure)
{
if(!objects)
return false
if(objects instanceof Collection)
objects.each(closure)
else
closure(objects)
return true
}
def extractAttribute(object, String attribute)
{
try
{
object[attribute]
}
catch (e)
{
null
}
}
//ОСНОВНОЙ БЛОК------------------------------------------------------
def countOfRecipients = 0
def log = { message ->
if(LOGGING_IS_ENABLED) logger.debug(message)
}
def error = { message ->
if(LOGGING_IS_ENABLED) logger.error("Не удалось добавить получателей ($message)")
}
def addEmail = { String email, String title ->
log("Добавление получателя: '$title <$email>'")
notification.to[email] = title
countOfRecipients++
}
def addRecipientsByCodes = { object, attributes ->
attributes.findAll().each {
log("Обработка атрибута: '$it'")
def recipient = extractAttribute(object ,it)
if(!recipient)
{
error("атрибут не существует или пуст")
return
}
if(recipient instanceof String)
addEmail(recipient, '')
else
{
foreach(recipient) {
def email = extractAttribute(it, 'email')
if(!email)
{
error("объект ${it.getMetainfo()}='${it.title}' не содержит атрибут 'email' или он пуст")
return
}
addEmail(email, it.title)
}
}
}
}
log("Скрипт добавления получателей оповещения")
log("Поиск по атрибутам объекта subject: ${subject.getMetainfo()} = '${subject.title}'")
addRecipientsByCodes(subject, RECIPIENTS)
log("Поиск по связанным объектам")
LINKED_OBJECTS.findAll().each { attribute ->
log("Обаботка атрибута связи: '$attribute'")
def object = extractAttribute(subject, attribute)
if(!object)
{
error("атрибут не существует или пуст")
return
}
def result = foreach(object) {
log("Обработка связанного объекта: ${it.getMetainfo()} = '${it.title}'")
addRecipientsByCodes(it, LINKED_RECIPIENTS)
}
if(!result)
error("атрибут пуст")
}
log("Всего добавлено получателей: $countOfRecipients")

Пример настройки

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

1. Создайте атрибут типа "Строка" с кодом incomingCode в классе объектов "Запрос" (serviceCall), см. Настройка атрибутов класса и типа объектов.

2. В скрипте обработки почты настройте заполнение атрибута с кодом incomingCode значением переменной incomingServer. Переменная incomingServer содержит код подключения к серверу входящей почты, с которым связан обработчик почты, см. Скрипт правила обработки входящей почты:

attrs.incomingCode = incomingServer

3. В скрипте кастомизации оповещения добавьте строки:

if (subject.incomingCode == '59aeaf4b-12f0-492f-935c-603da2c22918')

{notification.parameters.outgoingServer = '5aef57e2-9f13-40f1-9ef9-a4d262013c1c'

}

где 59aeaf4b-12f0-492f-935c-603da2c22918 — идентификатор подключения входящей почты;

где 5aef57e2-9f13-40f1-9ef9-a4d262013c1c — идентификатор подключения исходящей почты.

* идентификатор формируется автоматически при создании подключения и отображается в адресной строке карточки подключения.