Перейти к основному содержимому
Версия: 4.x

How-to: События

Пример 1

Условие

Есть заказ, для которого заданы дата, номер и признак того, является ли он закрытым.

CLASS Order 'Заказ';
isClosed 'Закрыт' = DATA BOOLEAN (Order);
date 'Дата' = DATA DATE (Order);
number 'Номер' = DATA INTEGER (Order);

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

Решение

// Вариант 1
WHEN SET(date(Order o) < currentDate()) DO
isClosed(o) <- TRUE;

// Вариант 2
WHEN CHANGED(currentDate()) AND date(Order o) < currentDate() DO
isClosed(o) <- TRUE;

В первом случае, событие будет выполнено только в одной транзакции в момент изменения выражения внутри оператора SET. А именно в тот момент, когда дата заказа становится меньше текущей даты. Однако, в случае если пользователь вручную изменит дату заказа больше текущей и сохранит, то система автоматически выполнит это событие и закроет заказ. Поэтому второй вариант предпочтительнее, так как оно будет срабатывать только в момент изменения текущей даты в полночь.

Пример 2

Условие

Аналогично Примеру 1, но для заказа заданы строки с количеством, ценой и суммой.

CLASS OrderDetail 'Строка заказа';
order 'Заказ' = DATA Order (OrderDetail) NONULL DELETE;

quantity 'Кол-во' = DATA NUMERIC[15,3] (OrderDetail);
price 'Цена' = DATA NUMERIC[14,2] (OrderDetail);
sum 'Сумма' = DATA NUMERIC[16,2] (OrderDetail);

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

Решение

WHEN LOCAL (CHANGED(quantity(OrderDetail d)) OR CHANGED(price(d)))
AND NOT CHANGED(sum(d)) DO {
sum(d) <- NUMERIC[16,2](quantity(d) * price(d));
}

События с типом LOCAL считают все изменения свойств не относительно состояния базы данных, а относительно значений, которые были на момент изменений, которые вызвали это событие. Проверка на то, что не изменилась sum, нужна чтобы не затереть изменения сделанные предыдущими изменениями. Например, если был импорт строк заказов из файла, при котором записываются количество, цена и сумма, то это событие уже не сработает.

Пример 3

Условие

Аналогично Примеру 2, но для строки заказа задана книга. Для каждой книги также задана цена по умолчанию.

CLASS Book 'Книга';
name 'Наименование' = DATA ISTRING[50] (Book);
price 'Цена' = DATA NUMERIC[14,2] (Book);

book 'Книга' = DATA Book (OrderDetail);
nameBook 'Книга' (OrderDetail d) = name(book(d));

FORM order
OBJECTS o = Order PANEL
PROPERTIES(o) date, number

OBJECTS d = OrderDetail
PROPERTIES(d) nameBook, quantity, price, sum
FILTERS order(d) == o
;

Нужно сделать, чтобы при изменении книги в строку заказа автоматически проставлялась цена. Это событие должно работать только на форме редактирования заказа.

Решение

WHEN LOCAL FORMS order SETCHANGED(book(OrderDetail d)) DO {
price(d) <- price(book(d));
}

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

Без указания конструкции FORMS, это событие работало бы при любом изменении книги строки заказа. Например, при импорте заказа в любой другой форме.

Пример 4

Условие

Аналогично Примеру 1.

Нужно организовать логирование удаления заказов

Решение

CLASS OrderLog 'Лог удаления заказа';
date 'Дата заказа' = DATA DATE (OrderLog);
number 'Номер заказа' = DATA INTEGER (OrderLog);

dateTime 'Дата' = DATA DATETIME (OrderLog);
user 'Пользователь' = DATA User (OrderLog);

WHEN DROPPED(Order o IS Order) DO {
NEW l = OrderLog {
date(l) <- PREV(date(o));
number(l) <- PREV(number(o));

dateTime(l) <- currentDateTime();
user(l) <- currentUser();
}
}

При удалении заказа и срабатывании события с модификатором DROPPED, важно помнить, что объекта уже не существует и все свойства, которые принимают его на вход, будут давать значения NULL. Поэтому нужно обращаться к ним не напрямую, а через модификатор PREV.