Структура данных отчета

Определение структуры данных

При создании или редактировании отчета по умолчанию отображается вкладка Report structure:

report structure
Figure 1. Структура данных отчета
Общие свойства отчета

Верхняя часть содержит поля для ввода общих свойств отчета:

  • Name – название отчета. Название может быть локализовано на вкладке Localization.

  • Group – группа отчетов. Используется для группировки в стандартном браузере отчетов.

  • Default templateшаблон вывода отчета .

  • System code – необязательный код, который можно использовать для идентификации отчета в коде приложения.

Определение полос отчетов

Важным элементом структуры данных отчета является иерархия полос – Report bands.

Полоса отчета имеет следующие параметры:

  • Band name – имя полосы, уникальное в отчете. Оно может содержать только латинские буквы, цифры и символы подчеркивания. Более того, если имя полосы начинается с header, ее данные не будут отображены в выводе таблицы.

  • Orientation – ориентация полосы: Horizontal, Vertical или Crosstab.

    • Horizontal – полосы копируются вниз, могут содержать подполосы.

    • Vertical – полосы копируются вправо.

    • Crosstab – полосы копируются вправо и вниз в виде матрицы.

  • Parent band – родительская полоса.

Каждая полоса включает в себя один или несколько наборов данных. При запуске отчета наборы данных преобразуются в списки строк, где каждая строка содержит сопоставление пар имя-значение. Полоса появляется в отчете столько раз, сколько строк в ее самом длинном наборе данных.

Имена полей могут быть использованы в шаблоне отчета и будут заменены соответствующими значениями из набора данных при создании отчета. При описании наборов данных вы можете использовать внешние параметры отчета и поля из других полос – это позволяет создавать связанные полосы.

Каждый отчет имеет полосу Root. В ней можно создавать наборы данных и ссылаться на их поля из других полос, но ее нельзя использовать в шаблоне отчета.

Значение столбца Dataset name используется только для удобства пользователя.

Типы наборов данных

Набор данных SQL

Набор данных SQL создается в результате выполнения SQL-запроса. Рекомендуется использовать псевдонимы для полей результатов запроса с использованием оператора as. Также рекомендуется заключать псевдонимы в двойные кавычки, чтобы предотвратить возможное преобразование регистра СУБД:

select u.name as "userName", u.login as "userLogin"
from jmxrpr_user u

В запросе можно использовать входные параметры отчета и поля родительских полос. К параметрам следует обращаться по имени, заключенному в ${}, например, ${dateFrom}. К полям родительской полосы следует обращаться аналогично, добавляя название полосы перед именем поля: ${band1.field1}.

Ниже приведен пример SQL-запроса с параметром groupId, полученным из родительской полосы group, и внешним параметром enabled.:

select u.name as "userName", u.login as "userLogin"
from jmxrpr_user u
where u.group_id = ${group.groupId}
    and u.enabled = ${enabled}
    and u.delete_ts is null

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

Выбор хранилища данных

По умолчанию запросы выполняются к основной базе данных. Если вы хотите запросить дополнительное хранилище данных, укажите его имя в поле Data store.

Предварительная обработка запросов в полосах

Если вам нужно динамически изменять запрос SQL/JPQL в зависимости от входных параметров отчета или значений параметров из родительской полосы, вы можете использовать предварительную обработку SQL. Механизм шаблонов позволяет вам изменять запросы SQL/JPQL с помощью Groovy. Чтобы активировать эту возможность, установите флажок Preprocess query as Groovy template под редактором полос. Результирующий запрос будет обработан механизмом GStringTemplateEngine, который будет иметь доступ к:

  • параметрам отчета: ${<parameter_name>},

  • значениям из родительских полос: ${<band_name>.<parameter_name>}.

Давайте рассмотрим следующий пример: в зависимости от того, передан ли параметр отчета createTs2, вам нужно выбрать одно из условий запроса: e.create_ts < ${createTs2} или e.create_ts < current_timestamp.

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

select e.create_ts, e.id, e.vin from ref_car e
where
e.create_ts >= ${createTs1}
and
<% out << (createTs2 != null  ? 'e.create_ts < ${createTs2}' : 'e.create_ts < current_timestamp')%>

Таким образом, если параметр createTs2 не передан, исходный запрос будет преобразован в следующий результирующий запрос:

select e.create_ts, e.id, e.vin from ref_car e
where
e.create_ts >= ${createTs1}
and
e.create_ts < current_timestamp

Если передан createTs2, то для полосы будет использоваться следующий результирующий запрос:

select e.create_ts, e.id, e.vin from ref_car e
where
e.create_ts >= ${createTs1}
and
e.create_ts < ${createTs2}

Набор данных JPQL

Набор данных JPQL создается в результате выполнения запроса JPQL. Результирующие поля запроса должны иметь псевдонимы, указанные с помощью оператора as. Аналогично SQL-запросу, в запросе JPQL можно использовать входные параметры отчета и поля родительских полос.

Ниже приведен пример запроса JPQL с параметром groupId, полученным из родительской полосы group, и внешним параметром enabled:

select u.name as userName, u.login as userLogin
from jmxrpr_User u
where u.group.id = ${group.groupId}
    and u.enabled = ${enabled}

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

Вы также можете использовать Link field для объединения нескольких наборов данных, использовать Data store для запроса дополнительного хранилища данных или активировать предварительную обработку запроса, установив флажок Preprocess query as Groovy template под редактором полос.

Набор данных Groovy

Набор данных Groovy создается в результате выполнения скрипта Groovy. Скрипт возвращает объект типа List<Map<String, Object>>. Каждый элемент этого списка – объект типа Map<String, Object> – соответствует одной записи набора данных.

В скрипт передаются следующие объекты:

  • params – отображение внешних параметров отчета. Ниже приведен пример получения значения параметра:

    def active = params['active']
  • parentBand – родительская полоса как объект типа com.haulmont.yarg.structure.BandData. Этот объект позволяет получить значение поля родительской полосы, вызвав метод getParameterValue(), например:

    def groupId = parentBand.getParameterValue('groupId')
  • currentAuthentication - объект типа io.jmix.core.security.CurrentAuthentication, связанный с текущим аутентифицированным пользователем. Например:

    def user = currentAuthentication.getUser()
  • metadata – объект типа io.jmix.core.Metadata, предоставляющий доступ к метаданным приложения. Например:

    def metaClass = metadata.getClass('jmxrpr_User')
  • dataManager – объект типа io.jmix.core.DataManager, который обеспечивает функциональность CRUD. Например:

    def book = dataManager.load(Book).id(bookId).fetchPlan("book.edit").one()
  • timeSource – объект типа io.jmix.core.TimeSource, используемый для получения текущего времени. Например:

    def currentDate = timeSource.currentTimestamp()
  • applicationContext - объект типа org.springframework.context.ApplicationContext, который предоставляет доступ к управляемым бинам. Например:

    def accountService = applicationContext.getBean(AccountService);

Набор данных Entity

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

Источник данных создается из внешнего параметра типа Entity, который должен быть описан на вкладке Parameters and Formats. Значение в поле Entity parameter name должно совпадать с именем параметра.

Шаблон отчета должен содержать поля с именами атрибутов сущностей. Имена атрибутов могут использовать имена из существующего фетч-плана, если установлен флажок Use existing fetch plan, или могут быть выбраны по нажатию кнопки Select entity attributes.

Поскольку механизм создания отчетов всегда перезагружает объекты в наборе данных Entity из БД, его нельзя использовать для сущностей DTO или экземпляров сущностей JPA, не сохраненных в базе данных. Вместо него используйте набор данных Groovy и обращайтесь к сущности, переданной в качестве параметра следующим образом:

def entity = params['entity']

return [['title': entity.title,
        'description': entity.description]]

Набор данных List of Entities

Набор данных List of entities создается с использованием списка экземпляров сущностей JPA.

Источник данных создается с использованием внешнего параметра, представляющего собой List of entities, который должен быть описан на вкладке Parameters and Formats. Значение в поле Entity parameter name должно соответствовать псевдониму параметра.

Шаблон отчета должен содержать поля с именами атрибутов сущностей. Имена атрибутов могут использовать имена из существующего фетч-плана, если установлен флажок Use existing fetch plan, или могут быть выбраны по нажатию кнопки Select entity attributes.

Поскольку механизм создания отчетов всегда перезагружает объекты в наборе данных List of entities из БД, его нельзя использовать для сущностей DTO или экземпляров сущностей JPA, не сохраненных в базе данных. Вместо него используйте набор данных Groovy и обращайтесь к сущности, переданной в качестве параметра следующим образом:

return params['entities'].collect {[
    'title': it.title,
    'description': it.description
]}

Набор данных JSON

Набор данных JSON генерируется на основе данных JSON. Эти данные могут быть получены из следующих источников:

  1. Groovy script

    Скрипт, предоставленный пользователем, должен возвращать данные JSON в виде строки.

    Например:

    return ''' 
            {
              "items": [
                {
                  "name": "Java Concurrency in practice",
                  "price": 15000
                },
                {
                  "name": "Clear code",
                  "price": 13000
                },
                {
                  "name": "Scala in action",
                  "price": 12000
                }
              ]
            }
            '''
  2. URL

    Механизм создания отчетов выполнит HTTP-запрос GET по URL-адресу.

    Например:

    https://jsonplaceholder.typicode.com/users
  3. Parameter of a String type

    Внешний параметр отчета строкового типа, содержащий данные JSON, должен быть описан на вкладке Parameters and Formats.

Полученное дерево JSON запрашивается с помощью запроса JSONPath. Например, вы можете использовать JSONPath $.store.book[*], чтобы вернуть все книги из следующего дерева JSON:

{
    "store": {
    "book": [
            {
                "category": "reference",
                "author": "Nigel Rees",
                "title": "Sayings of the Century",
                "price": 8.95
            },
            {
                "category": "fiction",
                "author": "Evelyn Waugh",
                "title": "Sword of Honour",
                "price": 12.99,
                "isbn": "0-553-21311-3"
            }
    ],
    "bicycle": {
        "color": "red",
        "price": 19.95
    }
}
}

Для получения более подробной информации о выражениях JSONPath обратитесь к the документации JSONPath.

Выводимые отчетом поля, которые имеют типы данных Date, DateTime или Time, не поддерживают формат, определенный java.text.SimpleDateFormat`. Чтобы установить правильный формат, следует написать скрипт Groovy.

Для этого перейдите на вкладку Parameters and Formats редактора отчетов и откройте редактор formatter. Например, в случае поля bookPublication.dateTime Groovy-скрипт будет выглядеть следующим образом:

import java.text.SimpleDateFormat

def simpleOldDateFormat = new SimpleDateFormat('yyyy-MM-dd HH:mm')
def simpleNewDateFormat = new SimpleDateFormat('dd/MM/yyyy HH:mm')
def oldDate = simpleOldDateFormat.parse(value)

return simpleNewDateFormat.format(oldDate)