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

How-to: WHILE

Пример 1

Условие

Есть заказ, для которого задана дата.

CLASS Order 'Заказ';

date 'Дата' = DATA DATE (Order);

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

Решение

countOrders (DATE date) = GROUP SUM 1 BY date(Order o);

messageCountOrders 'Посчитать кол-во заказов' (DATE dFrom, DATE dTo) {
// Вариант 1
LOCAL date = DATE ();
date() <- dFrom;

WHILE date() <= dTo DO {
MESSAGE 'Кол-во заказов за ' + date() + ' : ' + OVERRIDE countOrders(date()), 0.0;
date() <- sum(date(), 1);
}

// Вариант 2
FOR iterate(DATE date, dFrom, dTo) DO
MESSAGE 'Кол-во заказов за ' + date + ' : ' + OVERRIDE countOrders(date()), 0.0;
}

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

Для добавления к дате одного дня используется свойство sum, определенное в системном модуле Time.

Пример 2

Условие

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

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

sum 'Сумма' = DATA NUMERIC[14,2] (OrderDetail);
discountSum 'Сумма скидки' = DATA NUMERIC[14,2] (OrderDetail);

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

Решение

distributeDiscount 'Распределить скидку' (Order o, NUMERIC[14,2] discount)  {
LOCAL discount = NUMERIC[14,2] ();
discount() <- discount;

LOCAL leftSum = NUMERIC[14,2] (OrderDetail);
leftSum(OrderDetail d) <- sum(d) WHERE order(d) == o;

WHILE discount() > 0 DO {
// находим строку с наибольшей "оставшейся" суммой
FOR OrderDetail d == [ GROUP LAST OrderDetail od ORDER leftSum(od), od BY order(od)](o) DO {
discountSum(d) <- MIN leftSum(d), discount();
discount() <- discount() (-) discountSum(d);
}
IF (GROUP SUM 1 IF leftSum(OrderDetail d) > 0) THEN
BREAK; // не осталось больше чего расписывать
}
}

Пример 3

Условие

Задана логика изменения остатка для книги следующим образом :

CLASS Book 'Книга';

CLASS Ledger 'Изменение остатка';
date 'Дата' = DATA DATE (Ledger);
book 'Книга' = DATA Book (Ledger);
quantity 'Кол-во' = DATA NUMERIC[14,2] (Ledger);

Нужно создать действие, которое посчитает накопленный остаток (интеграл) за определенный интервал времени.

Решение

calculateIntegral (DATE dFrom, DATE dTo)  {
LOCAL date = DATE();
date() <- dFrom;

LOCAL balance = NUMERIC[14,2] (Book);
balance(Book b) <- [ GROUP SUM quantity(Ledger l) IF date(l) < dFrom BY book(l)](b);

LOCAL cumBalance = NUMERIC[14,2] (Book);

WHILE date() <= dTo DO {
cumBalance(Book b) <- cumBalance(b) (+) balance(b); //
balance(Book b) <- balance(b) (+) [ GROUP SUM quantity(Ledger l) BY book(l), date(l)](b, date());
date() <- sum(date(), 1);
}

FOR cumBalance(Book b) DO {
MESSAGE 'Накопленный остаток по книге ' + b + ' : ' + cumBalance(b);
}
}