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
.