Как сделать форму где строки = дням выбранного месяца

Есть вот такой код

CLASS Type;
name = DATA STRING (Type);

CLASS Plan;
date = DATA DATE (Plan);
type = DATA Type (Plan);
amount = DATA INTEGER (Plan);

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

Что-то вот такого плана (этот код не работает)

filterYear = DATA LOCAL INTEGER;
filterMonth = DATA LOCAL Month;

FORM planReport 
    OBJECTS dp = (d = DATE, p = Plan)
    PROPERTIES extractDay(d), type(p), amount(p)
    FILTERS 
            d >= toDateFormat((CONCAT '-', filterYear(), filterMonth(), 1), 'YYYY-MM-DD')
        AND
            d <= lastDayOfMonth(toDateFormat((CONCAT '-', filterYear(), filterMonth(), 1), 'YYYY-MM-DD'))
;

Ответы (1 шт):

Автор решения: Aliaksei Kirkouski

Обычный FILTERS >= и <= (без других фильтров) на объект примитивного типа DATE (а также INTEGER, STRING и т.д.) не сработает, так как это не сможет скомпилироваться в обычный SQL-запрос на получение всех ключей (а именно разновидностей дат).

Чтобы решить эту проблему, в системно модуле Time есть свойство iterate :

iterate(DATE dt, DATE from, DATE to) = RECURSION dt==from AND from IS DATE AND to IS DATE STEP dt==sum($dt, 1) AND dt<=to CYCLES IMPOSSIBLE;

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

Таким образом, код выше нужно преобразовать вот в такой :

filterYear = DATA LOCAL INTEGER ();
filterMonth = DATA LOCAL Month ();

FORM planReport 
   OBJECTS dp = (d = DATE, p = Plan)
   PROPERTIES extractDay(d), type(p), amount(p)
   FILTERS iterate(d, 
                   toDateFormat((CONCAT '-', filterYear(), filterMonth(), 1), 'YYYY-MM-DD'),
                   lastDayOfMonth(toDateFormat((CONCAT '-', filterYear(), filterMonth(), 1), 'YYYY-MM-DD'))
;

Однако, учитывая, что DATE и Plan никак не связаны, то в результате будет декартово произведение. Возможно нужно посчитать amount для DATE при помощи GROUP SUM/MAX/AGGR на основе Plan, а затем уже выводить все свойства только для объекта класса DATE (OBJECTS d = DATE).

→ Ссылка