Скрипт шаблона отчета (печатной формы)

Описание скрипта

Скрипт шаблона отчета (печатной формы) предназначен для:

  • извлечения сложных данных, в частности, вычислимых атрибутов;
  • определения параметров отчета (печатной формы).

В теле скрипта шаблона отчета (печатной формы) можно обращаться к получаемым параметрам по их коду.

Скрипт отчета можно условно разделить на два блока: определение параметров отчета и определение логики обработки сформированного запроса.

Место настройки скрипта

На форме добавления и форме редактирования шаблона отчета /печатной формы, см. Добавление и настройка шаблона отчета (печатной формы).

Когда выполняется скрипт

Скрипт выполняется в момент построения отчета.

Результат выполнения скрипта

Скрипт возвращает объект table.

Переменные и их значения

Переменные общей части скрипта:

  • user — текущий пользователь.
  • table — таблица отчета, таблица состоит из множества объектов row (строка таблицы).

Переменные, доступные в теле метода getParameters().

  • user — текущий пользователь.
  • subject — объект, на карточке которого строится отчет.

Переменные user и subject в теле метода getParameters() доступны только для формы добавления параметров отчета. При создании отчетов через методы api.reports эти переменные недоступны.

Переменные, доступные в теле метода getParameters() при использовании скрипта фильтрации в методе setFiltrationScript (см. Фильтрация параметров отчета):

  • params — ассоциативный список выбранных параметров (ключ — код параметра, значение — выбранное значение).

Методы, используемые в скрипте отчета /печатной формы

Режимы работы скрипта

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

Потоковый режим — данные обрабатываются маленькими порциями и между операциями обработки данных сохраняются во временный файл на жестком диске сервера приложения. В потоковом режиме не предусмотрено добавление или удаление новых строк или колонок. Потоковый режим включается директивой в начале скрипта "/*&streamMode*/".

Регистр переменных в приложении Pentaho Report Designer (PRD) должен совпадать с алиасами в sql запросе, см. Настройка шаблона для отчета или печатной формы в Pentaho Report Designer. При использовании потокового режима алиасы, которые формирует база данных, переходят в нижний регистр (если не используются двойные кавычки (")).

Чтобы избежать ошибок при построении отчетов в потоковом режиме, в случае если алиасы sql используют верхний регистр, а переменные в PRD его повторяют, рекомендуется использовать кавычки в наименовании алиасов sql или писать переменные PRD в нижнем регистре.

Примеры использование алиасов:

// В обычном режиме столбец aliasName и переменную в PRD надо называть так же,

// В потоковом режиме столбец aliasname и переменную в PRD надо назвать в нижнем регистре

SELECT column_name AS aliasName FROM table_name

SELECT nUm AS aliasName FROM tbl_servicecall

Примеры скрипта

  1. Скрипт определяет параметры "Строка", "Целое число", "Дробное число", "Логический", "Справочник", "Объект":

    api.parameters.getString("string1", "Строка", "строка по умолчанию"),
    api.parameters.getInteger("integer1", "Целое число", 123),
    api.parameters.getDouble("double1", "Дробное число", 123.45),
    api.parameters.getBoolean("boolean1", "Логический", true),
    api.parameters.getCatalogItem("catalogItem1", "Справочник", "currency", "currency\$1303"),
    api.parameters.getObject("object1", "Сотрудник", "employee", "employee\$54801")
  2. Скрипт определяет параметры "Дата", "Дата/время":

    api.parameters.getDate("date1", "Дата", new Date()),
    api.parameters.getDateTime("dateTime1", "Дата-время", new Date())
  3. Скрипт определяет параметр типа "Временной интервал" (Даты с - по) для построения отчета:

    def getParameters()
    {
    // Дата начала периода
    BEGIN_DATE = 'С' 
    // Дата конца периода
    END_DATE = 'По' 
    
    return [ api.parameters.getDate("beginDate", BEGIN_DATE),
        api.parameters.getDate("endDate", END_DATE) ]
    }
  4. Скрипт вычисляет общее количество запросов и устанавливает в каждую строку процент от общего (в строке таблицы отчета выводится группа запросов, servicecalls — количество запросов в этой группе):

    def all = table.rows.collect {row -> row.servicecalls}.sum()
    table.rows.each() { row ->
    row.percents = String.format("%.2f", row.servicecalls * 100.0 / all) + '%'
    }
    return table
  5. Скрипт настройки новой функции.

    • totalFunction — анализирует все строки отчета;
    • groupFunction — анализирует отдельно каждую группу.
    * totalFunction — анализирует все строки отчета
    
    def getFunctions()
    def usr = user?.login
    {
    return [ api.reports.totalFunction('usr', { rows -> usr }) ]
    }
    * groupFunction — отдельного анализирует каждую группу
    def getFunctions() 
    {
    return [ api.reports.groupFunction('usr', { rows -> api.tx.call() { user?.login } }) ]
    }
  6. Скрипт изменения параметров, заполненных в getParameters до построения отчета:

    def getParameters()
    {
    return [ api.parameters.getObjects('ous', 'Отделы', 'ou', ['ou$19901']) ]
    }
    def getActualParameters(def parameters)
    {
    parameters.ous += utils.findFirst('ou', [:])
    return parameters
    }
    
  7. Скрипт получает текущее значение прямого счетчика в виде ЧЧ:ММ:

    def currentDate = new Date()
    table.rows.each() { row ->
    if(row.timerS.equals("a"))
    {
    row.timerElapsed = utils.formatters.formatLongToTime(row.timerL.longValue() + api.timing.serviceTime(row.serviceTime, row.timeZone, new Date(row.timerB.longValue()), currentDate),false).asString()
    else
    {
    row.timerElapsed = utils.formatters.formatLongToTime(row.timerL.longValue(), false).asString()
    }
    }
    return table
  8. Пример использования метода фильтрации .setFiltrationScript () при определении параметров отчета:

    Copy
    def getParameters() {
       return [ 
         api.parameters.getObject("t1", "Команда", "team")
           .setFiltrationScript({
              return ['team$3601'];
          }),

         api.parameters.getObjects("t2", "Отдел", "ou", ['ou$4202'], ['presentationCode':'4'])
            .setFiltrationScript({
              def ATTRS_FOR_UPDATE_ON_FORMS = ['t1']; 
              if (subject == null)
              { 
                  return ATTRS_FOR_UPDATE_ON_FORMS; 
              }
              return ['ou$4201'];
          }),

         api.parameters.getObject("t3", "Отдел", "ou", 'ou$4202', ['presentationCode':'1'])
            .setFiltrationScript({
              def ATTRS_FOR_UPDATE_ON_FORMS = ['t1']; 
              if (subject == null)
              { 
                  return ATTRS_FOR_UPDATE_ON_FORMS; 
              }
              return ['ou$4201'];
          }),

         api.parameters.getObjects("t4", "Команда", "team", ['team$3601'], ['presentationCode':'1'])
            .setFiltrationScript({
              return ['team$3601'];
          }),
         
         api.parameters.getCatalogItems('t5', 'Справочник', 'priority', ['priority$4501'])
                 .setFiltrationScript({
              return ['priority$4501'];
          }),

         api.parameters.getCatalogItemByCode('t6', 'Справочник', 'priority', 'sss1')
                 .setFiltrationScript({
              return ['priority$4501'];
          }),
         
         api.parameters.getCaseList('t7', 'Набор типов класса', 'ou', ['ou$ou2'])
            .setFiltrationScript({
              return ['ou$ou1'];
          }),
         
         api.parameters.getStates('t8', 'Статус', 'serviceCall', ['registered'])
            .setFiltrationScript({
              return ['registered'];
          }),

         api.parameters.getState('t9', 'Статус', 'serviceCall', 'registered')
            .setFiltrationScript({
              return ['registered'];
          }),
         
         api.parameters.getDate('t10', 'Дата', new Date()-2)
            .setFiltrationScript({
              if (!subject)
              {
                 return [];
              }
              def filter = api.date.filter();
              return [(filter.after(new Date())) : 'Значением может быть только дата в будущем'];
          })
       ] as List;
    }
  9. Пример использования зависимости параметров друг от друга (контекстная переменная params) в методе фильтрации .setFiltrationScript () при определении параметров отчета:

    Copy
    def getParameters() {
       return [ 
         api.parameters.getObject("serviceParam", "Услуга", "slmService"),
         
         api.parameters.getObjects("t3", "Заявки", "serviceCall")
            .setFiltrationScript({
              def ATTRS_FOR_UPDATE_ON_FORMS = ['serviceParam']; 
              if (subject == null)
              { 
                  return ATTRS_FOR_UPDATE_ON_FORMS; 
              }
              return utils.find('serviceCall',['service': params.serviceParam]);
          })
       ] as List;
    }
  10. Пример обращения к получаемым параметрам отчета (печатной формы) по их коду:

    utils.find('serviceCall',['creationDate' : op.between(beginDate,endDate)])