Обработчик события — запускает определенное действие в системе после того, как событие произошло. Более подробная информация в официальной справке ELMA365.
Создадим обработчик события, который будет отслеживать ("перехватывать") изменение значения определённой контекстной переменной элемента приложения и логировать историю этих изменений.
Рассмотрим пример на основе пользовательского приложения Дисконтная карта (discount_card) в разделе CRM (_clients). В приложении настроен следующий контекст:
![[IMG]](https://community.elma365.com/assets/0KHQutGA0LjQvdGI0L7RgiAyOC0wMS0yMDIyIDEwMDczMDE2NDMzNTc3NTY=.jpg)
В примере мы будем отслеживать изменение значения переменной Размер скидки, % (код: percent_discount, тип Число (целое)) и записывать историю изменений в переменную История изменения скидки (код: discount_history, тип: Строка).
Реализация обработчика
1. Создадим пользовательский модуль в разделе Администрирование > Модули.
2. На вкладке Обработка событий создадим новое событие:
- Домен события — элементы приложений.
- Событие — обновление элемента.
- Тип обработчика — запуск скрипта.
- Фильтр типа объекта — наше приложение Дисконтная карта.
![[IMG]](https://community.elma365.com/ru/assets/0KHQutGA0LjQvdGI0L7RgiAwNi0wMi0yMDI1IDE5MDkwNTE3Mzg4NTQ2Mjg=.jpg)
3. На вкладке Настройки в нашем модуля создадим переменную Дисконтная карта с типом Приложение > Дисконтная карта. Это необходимо для дальнейшего поиска определённого элемента в сценарии модуля (так как глобальные константы Global в модулях недоступны).
![[IMG]](https://community.elma365.com/ru/assets/0KHQutGA0LjQvdGI0L7RgiAwMi0wNi0yMDIyIDEwMzQxMTE2NTQxNTE3MDA=.jpg)
4. Перейдём на вкладку Сценарии созданного обработчика. На данной вкладке будет создан метод по умолчанию:
async function action(): Promise<void> {}
Код обработчика необходимо реализовать в данном методе:
Код:
async function action(): Promise<void> {
//выполняем поиcк элемента по id, discount_card - контекстная переменная из настроек модуля
const apcard = await Namespace.params.fields.discount_card.app.search().where(a => a.__id.eq(Context.data.__item!.id)).first();//получаем элемент приложения
if (apcard) {
let oldPercent = EventContext.OldItem.data.percent_discount;//получаем значение переменной percent_discount до изменения
let newPercent = EventContext.NewItem.data.percent_discount;//получаем значение переменной percent_discount после изменения
//сравниваем percent_discount до и после изменения. Если они не совпадают, значит в данном событии было изменено значение percent_discount
if (oldPercent != newPercent) {
const createdBy = Context.data.__createdByName;//получаем автора изменений
//формируем строку с записью истории
const history = `${Context.data.__createdAt.format("DD.MM.YYYY HH:mm:ss")} - Пользователь ${createdBy} изменил размер скидки по карте. Предыдущее значение: ${oldPercent ? oldPercent : null}, новое значение: ${newPercent ? newPercent : null}
`
apcard!.data.discount_history = apcard!.data.discount_history ? apcard!.data.discount_history + history : history;
//сохраняем элемент приложения
await apcard!.save();
}
}
}
В Context.data.__item хранится сам элемент приложения, по которому произошло событие, без привязки к значениям полей до и после изменения. Здесь можно обратиться к параметрам:
- namespace — код раздела;
- code — код приложения;
- id — Id элемента приложения, по которому произошло событие.
В EventContext.OldItem.data хранится значение контекста элемента приложения до изменения. Название переменной, значение которой нужно получить, необходимо указывать через точку. EventContext содержит строго типизированные данные элемента приложения.
В EventContext.NewItem.data хранится значение контекста элемента приложения после изменения. Название переменной, значение которой нужно получить, необходимо указывать через точку. EventContext содержит строго типизированные данные элемента приложения.
Также в EventContext.OldItem.fields/EventContext.NewItem.fields доступны настройки типизированного контекста приложения.
В Context.data.oldItem хранится значение контекста элемента приложения до изменения. Название переменной, значение которой нужно получить, необходимо указывать через точку. Автоподстановка здесь не поддерживается.
В Context.data.item хранится значение контекста элемента приложения после изменения. Название переменной, значение которой нужно получить, необходимо указывать через точку. Автоподстановка здесь не поддерживается.
Context.data.oldItem и Context.data.item использовались до версии 2023.6 (до появления типизации приложения в настройках обработчика в поле "Фильтр типа объекта).
Результат работы данного обработчика на скриншоте:
![[IMG]](https://community.elma365.com/ru/assets/0KHQutGA0LjQvdGI0L7RgiAwNi0wMi0yMDI1IDE5MzM0NDE3Mzg4NTYwNDg=.jpg)
На форме просмотра элемента приложения в блоке История изменения размера скидки размещена переменная discount_history с отключённой опцией Показывать название на форме.
Небольшой лайфхак
Для просмотра структуры Context, который формируется в событии, можно отправить HTTP-запрос на сайт webhook.site/.
Для этого перейдите на сайт webhook.site/, включите параметр Auto Navigate и скопируйте значение в строке Your unique URL.
В коде обработчика события реализуйте следующий код:
Код:
async function action(): Promise<void> {
fetch("https://webhook.site/205c73d1-2036-4e8c-8901-b31ca1a556b1", {
method: "POST",
body: JSON.stringify((<any>Context).json()),
})
}
Где https://webhook.site/205c73d1-2036-4e8c-8901-b31ca1a556b51 – ваше значение unique URL.
Инициализируйте нужное событие, например, изменение элемента приложения. В результате выполнения данного обработчика, вы получите HTTP-запрос на сайте https://webhook.site, где можно будет просмотреть Context в блоке Raw Content.
![[IMG]](https://community.elma365.com/assets/0KHQutGA0LjQvdGI0L7RgiAyOC0wMS0yMDIyIDExMzgyMzE2NDMzNTgwMjM=.jpg)
После отладки обработчика с помощью сайта webhook.site не забудьте снять обработчик с публикации, чтобы он перестал выполнять настроенные действия!