Módulos do guia

Nível 2 · Consulta e relatórios · Módulo 07

Relatórios

Duração estimada: 2h30 a 3h30

Você vai sair sabendo

  • →Criar uma view pelo Dicionário, para que ela viaje no 2Pack
  • →Montar um relatório padrão com Report View e Print Format, sem Java
  • →Filtrar o relatório com parâmetros que batem com as colunas da view
  • →Criar um relatório Jasper com o arquivo dentro do plugin
  • →Saber quando usar cada tipo de relatório

Checkpoint: 0 de 6

ver .md

Antes de começar

  • Módulo 06 concluído: o processo gerou visitas de manutenção, então há dados para listar.
  • Para a parte 2 (Jasper), instale o Jaspersoft Studio 6.21. A versão importa: o iDempiere 14 usa a biblioteca JasperReports 6.21.0, e um relatório salvo por uma versão mais nova do Studio pode não abrir.

O que você vai construir

O supervisor da GardenWorld quer saber quantas visitas cada técnico fez no mês, de que tipo e quantos produtos foram usados. Você vai entregar isso de dois jeitos:

  • Relatório padrão do iDempiere: uma view, um Report View e um formato de impressão gerado sozinho. Nenhuma linha de Java, e o usuário pode reorganizar colunas, agrupar e exportar para Excel.
  • Relatório Jasper: layout livre, com cabeçalho e logotipo, para quando o documento sai da empresa.

Os tipos de relatório

TipoComo funcionaUse quando
Padrão (Report View)Uma view ou tabela + um Print FormatListagens e totais para uso interno. É o primeiro a tentar
JasperArquivo .jrxml desenhado no Jaspersoft StudioO layout importa: documento para cliente, etiqueta, formulário
Cubo calculadoUm processo Java grava numa tabela temporária T_, e o relatório lê delaA lógica é complexa demais para uma view

Parte 1: o relatório padrão

1. A view, pelo Dicionário

Você poderia criar a view com CREATE VIEW no psql. O problema: ela não iria no 2Pack, e o próximo ambiente não teria a view. Criando pelo Dicionário, a definição fica no banco como dado e o Pack In recria a view no destino.

Como System, na janela Table and Column, crie a tabela:

CampoValor
DB Table NameEDU_RV_Visita
NameVisitas (relatório)
Viewmarcado
Data Access LevelClient+Organization
Entity TypeEDU

O prefixo RV_ é o costume do core para views de relatório.

Na aba View Component, crie um componente:

CampoValor
NameEDU_RV_Visita
Sql FROMFROM EDU_Visita v
Entity TypeEDU

Na aba View Column do componente, crie as colunas. DB Column Name é o nome na view; Column SQL é a expressão:

SeqDB Column NameColumn SQL
10AD_Client_IDv.AD_Client_ID
20AD_Org_IDv.AD_Org_ID
30EDU_Visita_IDv.EDU_Visita_ID
40EDU_DataVisitav.EDU_DataVisita
50SalesRep_IDv.SalesRep_ID
60C_BPartner_IDv.C_BPartner_ID
70EDU_TipoVisitav.EDU_TipoVisita
80EDU_IsUrgentev.EDU_IsUrgente
90EDU_IsConcluidav.EDU_IsConcluida
100Qty(SELECT COALESCE(SUM(l.Qty),0) FROM EDU_VisitaLinha l WHERE l.EDU_Visita_ID=v.EDU_Visita_ID)

Volte à aba Table e clique em View Validate. O iDempiere monta o CREATE OR REPLACE VIEW a partir dos componentes e roda no banco. Confira:

SELECT * FROM EDU_RV_Visita LIMIT 5;

Agora clique em Create Columns from DB: o iDempiere lê as colunas da view e cria os registros de coluna. Revise duas referências que ele não tem como adivinhar:

ColunaReferenceReference Key
SalesRep_IDTableAD_User - Internal
EDU_TipoVisitaListEDU_TipoVisita

Isso faz o relatório mostrar o nome do técnico e o nome do tipo, e não o ID e o código.

2. O Report View

Conceito: o Report View liga um relatório a uma tabela ou view. Pode ter um filtro fixo (Sql WHERE) que vale sempre.

Na janela Report View, crie:

CampoValor
NameEDU_RV_Visita
TableEDU_RV_Visita
Entity TypeEDU

3. O relatório e os parâmetros

Na janela Report and Process, crie:

CampoValor
Search KeyEDU_VisitasPorTecnico
NameVisitas por Técnico
Data Access LevelClient+Organization
Entity TypeEDU
Reportmarcado
Report ViewEDU_RV_Visita

Sem Classname: quem roda é o motor de relatórios do core.

Na aba Parameter:

SeqNameDB Column NameReferenceDetalhes
10TécnicoSalesRep_IDTableReference Key: AD_User - Internal
20Data da VisitaEDU_DataVisitaDateRange marcado
30Tipo de VisitaEDU_TipoVisitaListReference Key: EDU_TipoVisita

É aqui que o relatório padrão economiza código: cada parâmetro vira um filtro na coluna da view com o mesmo DB Column Name. Parâmetro vazio não filtra. Com Range, a tela pede "de" e "até" e o filtro vira um intervalo.

Crie a entrada de menu com Action Report e rode Role Access Update como GardenAdmin.

4. Rode e ajuste o formato

Como GardenAdmin, rode Visitas por Técnico sem filtros. Na primeira execução, o iDempiere cria sozinho um Print Format com todas as colunas do Report View.

Agora deixe o relatório útil:

  1. No visualizador, abra o Report Wizard (botão de personalização na barra do relatório).
  2. Esconda AD_Client_ID, AD_Org_ID e EDU_Visita_ID.
  3. Ordene e agrupe por Técnico, e peça a soma de Qty.
  4. Salve. O formato vale para todos os usuários desse cliente.

Rode de novo filtrando por um técnico e pelo mês atual. Teste também a exportação para Excel e PDF, que vem pronta.

Parte 2: o mesmo relatório em Jasper

5. Desenhe no Jaspersoft Studio

Crie um relatório em branco VisitasPorTecnico.jrxml conectado ao seu banco de desenvolvimento, com esta consulta:

SELECT v.EDU_DataVisita, u.Name AS Tecnico, bp.Name AS Cliente,
       v.EDU_TipoVisita, v.Qty
FROM EDU_RV_Visita v
JOIN AD_User u ON u.AD_User_ID = v.SalesRep_ID
JOIN C_BPartner bp ON bp.C_BPartner_ID = v.C_BPartner_ID
WHERE v.AD_Client_ID = $P{AD_CLIENT_ID}
  AND ($P{SalesRep_ID} IS NULL OR v.SalesRep_ID = $P{SalesRep_ID})
  AND ($P{EDU_DataVisita1} IS NULL OR v.EDU_DataVisita >= $P{EDU_DataVisita1})
  AND ($P{EDU_DataVisita2} IS NULL OR v.EDU_DataVisita <= $P{EDU_DataVisita2})
ORDER BY u.Name, v.EDU_DataVisita

Declare os parâmetros no relatório com estes nomes e tipos:

ParâmetroTipoDe onde vem
AD_CLIENT_IDjava.lang.IntegerO iDempiere envia sempre (cliente logado)
SalesRep_IDjava.lang.IntegerParâmetro do processo
EDU_DataVisita1java.sql.Timestamp"De" do parâmetro com Range
EDU_DataVisita2java.sql.Timestamp"Até" do parâmetro com Range

A regra dos nomes: o parâmetro chega com o DB Column Name; num Range, chega como dois, com sufixo 1 e 2. Além dos seus, o iDempiere sempre envia AD_CLIENT_ID, AD_ORG_ID, AD_USER_ID, AD_ROLE_ID, AD_PINSTANCE_ID e RECORD_ID.

Monte o layout: agrupe por Tecnico, com a soma de Qty no rodapé do grupo.

6. O arquivo mora no plugin

Crie a pasta reports no plugin, salve o .jrxml nela e inclua a pasta no build.properties:

bin.includes = META-INF/,\
               .,\
               OSGI-INF/,\
               reports/

Sem essa linha, o arquivo funciona no Eclipse e some quando o plugin vira um jar (módulo 12).

7. Cadastre o processo Jasper

Na janela Report and Process, crie outro registro:

CampoValor
Search KeyEDU_VisitasPorTecnicoJasper
NameVisitas por Técnico (PDF)
Data Access LevelClient+Organization
Entity TypeEDU
Reportmarcado
Jasper Reportbundle:com.gardenworld.visitas:reports/VisitasPorTecnico.jrxml

Copie os parâmetros Técnico e Data da Visita do relatório anterior (mesmos DB Column Names). Preenchido o Jasper Report, o iDempiere passa a execução para o motor do Jasper, sem Classname.

O prefixo bundle: diz: procure o arquivo dentro do plugin com.gardenworld.visitas. O iDempiere compila o .jrxml na primeira execução. Outros prefixos aceitos:

PrefixoOnde está o arquivo
bundle:plugin:caminhoDentro de um plugin (o recomendado)
attachment:arquivo.jrxmlAnexado ao próprio registro do processo
/caminho/absolutoNo sistema de arquivos do servidor

Crie o menu, rode Role Access Update e teste.

8. Commit

Inclua no Pack Out, na ordem: a tabela EDU_RV_Visita (o Pack In recria a view no destino), os dois relatórios (Process/Report já leva o Report View junto) e os dois itens de menu. Gere o 2Pack_1.0.3.zip.

git add .
git commit -m "Visitas 1.0.3: relatórios padrão e Jasper de visitas por técnico"

Checkpoint

0 de 6 itens

Erros comuns

SintomaCausa provávelCorreção
View Validate falhaErro de SQL em alguma Column SQLMonte o SELECT à mão no psql com as mesmas expressões e corrija
O relatório não filtraDB Column Name do parâmetro diferente do nome da coluna na viewTem de ser idêntico
Relatório mostra IDs em vez de nomesReferência da coluna da view ficou como númeroPasso 1: ajuste Reference e Reference Key
Relatório vazio ou erro de acessoFaltou AD_Client_ID ou AD_Org_ID na viewInclua as duas colunas e rode View Validate de novo
Jasper: "report not found"Caminho do bundle: errado ou pasta fora do build.propertiesConfira nome do plugin, pasta e arquivo
Jasper: parâmetro sempre nuloNome ou tipo diferente no .jrxmlRange chega como Nome1 e Nome2; _ID chega como Integer
Jasper abre dados de outra empresaConsulta sem filtro por AD_CLIENT_IDPasso 5

Desafio

Crie o relatório Produtos mais usados em visitas: por produto, a quantidade total e em quantas visitas apareceu, com filtro por período. Use o relatório padrão. Você vai precisar de uma segunda view, com GROUP BY na Other SQL Clause do componente.

Referência

Cubo calculado

Quando a lógica não cabe numa view, o relatório lê de uma tabela temporária preenchida por um processo Java:

  • A tabela começa com T_ e tem as colunas AD_Client_ID, AD_Org_ID e AD_PInstance_ID.
  • O processo (módulo 06) grava as linhas com o getAD_PInstance_ID() da execução.
  • O processo é marcado como Report, com Classname e um Report View apontando para a tabela T_.
  • Para tabelas T_, o motor de relatórios filtra só pela execução (AD_PInstance_ID), sem transformar os parâmetros em filtro: quem usa os parâmetros é o seu Java.

Onde cada parte do relatório vive

ParteOnde ficaVai no 2Pack?
View (componentes e colunas)Dicionário (Table and Column)Sim, no tipo Table
Report ViewDicionárioSim, junto do processo
Processo e parâmetrosDicionárioSim
Print FormatDados do clienteSó se incluído com o tipo PrintFormat
.jrxmlPluginVai no jar, não no 2Pack

Próximo módulo

08 · Consulta e navegação: Info Window, mensagens traduzíveis, índices, quick info, configurações do sistema e auditoria.