AutoReport
O AutoReport é um serviço do BIS com a finalidade de criar relatórios e gráficos de forma automatizada utilizando a estrutura de dados do BIS.
Funcionamento e Objetivos
A finalidade desta ferramenta é permitir que o desenvolver simplesmente passe uma consulta, similar à um SQL mas utilizando a estrutura do BIS, para que a própria ferramente recupere os dados. E depois disso, a partir de algumas informações de estrutura a própria ferramente estrutura os dados retornados do banco de forma coerente e gera objetos que possam ser traduzidos em diversas interfaces para o usuário. Onde interface neste caso pode ser um Grid/Tabela/Tree na UI, um gráfico na UI com opções de iteração, ou mesmo as informações impressas em PDF, exportar para arquivos como Excel, CSV, etc..
Como utilizar o AutoReport
Para criar um relatório, o primeiro passo é criar um AutoReportDefinition. Esta classe de nome sugestivo, tem as definições do relatório. Nela montamos o que seria similar ao SELECT para ser utilizado no banco de dados e recuperar as informações para serem exibidas.
![]() |
Criando o AutoReport
final AccountBankStatementVO_ v_ = AccountBankStatementVO_.VO;
AutoReportDefinition<AccountBankStatementVO> def = new AutoReportDefinition<AccountBankStatementVO>(AccountBankStatementVO.class);
// Código configurando o Definition (descrito na sessão do AutoReportDefinition)
|
Com o definition criado, podemos criar o AutoReport para recuperar os dados:
![]() |
Instanciando o AutoReport
AutoReport<CFlowCategoryTreeNodeVO> rpt = new AutoReport<CFlowCategoryTreeNodeVO>(def, provider);
rpt.refresh();
|
![]() |
|
Uma observação aqui é a chamada do método .refresh(). Este método faz com que o AutoReport leia a definition e faça a consulta no banco de dados. O AutoReport aplica o "LazyLoad", assim nesse método ele fará a consulta e buscará apenas os IDs dos objetos aplicando todas as demais regras de WHERE, GROUPBY e ORDER BY. Somente a medida em que solicitarmos os blocos de dados é que serão consultados na base de dados.
Para obter os dados do AutoReport, devemos chamar os métodos .fetch(), conforme exemplo:
![]() |
Recuperando os Dados do AutoReport
for (int i = 0; i < rpt.size(); i += 10) {
List<Object[]> data = rpt.fetch(i, 10);
for (Object[] row : data) {
for (int j = 0; j < row.length; j++) {
System.out.print("Coluna " + j + ": " + row[j] + " / ");
}
System.out.println(";");
}
}
System.out.println("----------");
|
O exemplo acima recupera os dados em blocos de 10 registros e os imprime no console. (Código simples mas útil para DEBUG dos dados retornados no relatório.)
O método fetch aceita dois argumentos, indicando um offSet (a partir de qual registro desejamos) e um total (indicando o total de registros desejados). Desta forma conseguimos recuperar em blocos para exibir ou processar as informações do relatório.
Vale lembrar que o AutoReport não tem nenhum tipo de cache dos valores dos registros retornados. Isto significa que uma vez que foi solicitado e retornado, o AutoReport não armazena nada. Assim, a cada vez que os métodos de fetch são chamados uma nova consulta é realizada no banco de dados. Aqui entramos em um dilema. Buscar linha a linha no banco de dados, podemos não ocupar a memória com muitas informações, mas certamente criamos um overhead de processamento no banco de dados, já que a cada requisição feita, o banco precisa separar os dados, organizar e filtrar antes de devolve-los. Além de todo o stack de chamadas entre o método e o acesso ao banco.
![]() |
|
AutoReportDefinition
SELECT
Imagine que desejamos criar um relatório com os dados dos lançamentos financeiros das conta do BIS. Para isso precisamos definir com o AutoReport buscará os dados:
Exemplo de criação do Definition:
![]() |
Criando o AutoReportDefinition
final AccountBankStatementVO_ v_ = AccountBankStatementVO_.VO;
AutoReportDefinition<AccountBankStatementVO> def = new AutoReportDefinition<AccountBankStatementVO>(AccountBankStatementVO.class);
|
Note que o definition é instanciado com a classe que servirá de referência (tabela principal do Select) para que o BISDAO faça os joins e buscas no banco de dados.
Uma vez criado o definition, precisamos agora informar que colunas desejamos que sejam recuperadas. Similar ao SELECT do banco de dados, aqui selecionamos os campos dos VOs que queremos para que esses dados estejam disponíveis no relatório.
Note que é possível utilizar a estrutura do BISField para definir funções e outras operações para serem executadas diretamente no banco de dados.
![]() |
Seleção das Colunas
AutoReportColumn columnID = def.addSelect(BISField.field("id"));
AutoReportColumn columnDate = def.addSelect(BISField.field(v_.date()));
AutoReportColumn columnDisplayline = def.addSelect(BISField.field(v_.displayLine()));
AutoReportColumn columnOperation = def.addSelect(BISField.field(v_.operation()));
AutoReportColumn columnValue = def.addSelect(BISField.field(v_.value()));
AutoReportColumn columnDisplayline = def.addSelect(BISField.field(v_.accountStatementList().displayLine()));
AutoReportColumn columnCatMapID = def.addSelect(BISField.field(v_.accountStatementList().billPaymentVO().categoryMapList().id()));
AutoReportColumn columnCat = def.addSelect(
BISField.coalesce(
BISField.field(v_.accountStatementList().categoryMapList().categoryVO().name()),
BISField.field(v_.accountStatementList().billPaymentVO().categoryMapList().categoryVO().name())));
AutoReportColumn columnCatValue = def.addSelect(
BISField.coalesce(
BISField.field(v_.accountStatementList().categoryMapList().value()),
BISField.field(v_.accountStatementList().billPaymentVO().categoryMapList().value())));
|
Utilizando a estrutura dos MetaObject para selecionar o campo SEMPRE a partir do objeto utilizado como raiz, o AutoReport utilizará o BISDAO para unir as tabelas e trazer os dados coerentemente. Portanto, a parte do "FROM" do SQL é criada automaticamente pelo BISDAO.
![]() |
|
WHERE
Uma vez familiarizado com a estrutura do BISMO, a parte de "WHERE" (filtro dos dados do relatório) não tem nenhum segredo. Basta criar o BISMO e associa-lo ao AutoReportDefinition para que ele seja utilizado. Exemplo:
![]() |
Filtrando os dados do AutoReport
BISMO mo = new BISMO();
mo.greaterThanOrEqualTo(v_.date(), LocalDate.of(2019, 11, 1));
mo.lessThan(v_.date(), LocalDate.of(2019, 12, 1));
mo.equal(v_.accountVO().id(), 1);
def.setBISMO(mo);
|
ORDER BY
Assim como a parte do WHERE, a parte do ORDER BY no AutoReport não tem segredos em relação à estrutura já utilizada no BISDAO.
![]() |
Ordenando os dados do AutoReport
BISOrderBy orderBy = BISOrderBy.createInstance(v_.date());
def.setOrderBy(orderBy);
|
GROUP BY
O GroupBy tem exatamente a mesma funcionalidade do GROUP BY no SQL.
Para configurar o GroupBy no AutoReportDefinition utilizaremos a mesma sintaxe utilizada na parte do SELECT. O GroupBy aceita as mesmas funções e colunas definidas pela estrutura do BISField.
![]() |
Definindo colunas de GroupBy para a consulta
def.addGroupBy(BISField.field(v_.id()));
|