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
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
| Tipo | Como funciona | Use quando |
|---|---|---|
| Padrão (Report View) | Uma view ou tabela + um Print Format | Listagens e totais para uso interno. É o primeiro a tentar |
| Jasper | Arquivo .jrxml desenhado no Jaspersoft Studio | O layout importa: documento para cliente, etiqueta, formulário |
| Cubo calculado | Um processo Java grava numa tabela temporária T_, e o relatório lê dela | A 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:
| Campo | Valor |
|---|---|
| DB Table Name | EDU_RV_Visita |
| Name | Visitas (relatório) |
| View | marcado |
| Data Access Level | Client+Organization |
| Entity Type | EDU |
O prefixo RV_ é o costume do core para views de relatório.
Na aba View Component, crie um componente:
| Campo | Valor |
|---|---|
| Name | EDU_RV_Visita |
| Sql FROM | FROM EDU_Visita v |
| Entity Type | EDU |
Na aba View Column do componente, crie as colunas. DB Column Name é o nome na view; Column SQL é a expressão:
| Seq | DB Column Name | Column SQL |
|---|---|---|
| 10 | AD_Client_ID | v.AD_Client_ID |
| 20 | AD_Org_ID | v.AD_Org_ID |
| 30 | EDU_Visita_ID | v.EDU_Visita_ID |
| 40 | EDU_DataVisita | v.EDU_DataVisita |
| 50 | SalesRep_ID | v.SalesRep_ID |
| 60 | C_BPartner_ID | v.C_BPartner_ID |
| 70 | EDU_TipoVisita | v.EDU_TipoVisita |
| 80 | EDU_IsUrgente | v.EDU_IsUrgente |
| 90 | EDU_IsConcluida | v.EDU_IsConcluida |
| 100 | Qty | (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:
| Coluna | Reference | Reference Key |
|---|---|---|
SalesRep_ID | Table | AD_User - Internal |
EDU_TipoVisita | List | EDU_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:
| Campo | Valor |
|---|---|
| Name | EDU_RV_Visita |
| Table | EDU_RV_Visita |
| Entity Type | EDU |
3. O relatório e os parâmetros
Na janela Report and Process, crie:
| Campo | Valor |
|---|---|
| Search Key | EDU_VisitasPorTecnico |
| Name | Visitas por Técnico |
| Data Access Level | Client+Organization |
| Entity Type | EDU |
| Report | marcado |
| Report View | EDU_RV_Visita |
Sem Classname: quem roda é o motor de relatórios do core.
Na aba Parameter:
| Seq | Name | DB Column Name | Reference | Detalhes |
|---|---|---|---|---|
| 10 | Técnico | SalesRep_ID | Table | Reference Key: AD_User - Internal |
| 20 | Data da Visita | EDU_DataVisita | Date | Range marcado |
| 30 | Tipo de Visita | EDU_TipoVisita | List | Reference 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:
- No visualizador, abra o Report Wizard (botão de personalização na barra do relatório).
- Esconda
AD_Client_ID,AD_Org_IDeEDU_Visita_ID. - Ordene e agrupe por Técnico, e peça a soma de Qty.
- 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âmetro | Tipo | De onde vem |
|---|---|---|
AD_CLIENT_ID | java.lang.Integer | O iDempiere envia sempre (cliente logado) |
SalesRep_ID | java.lang.Integer | Parâmetro do processo |
EDU_DataVisita1 | java.sql.Timestamp | "De" do parâmetro com Range |
EDU_DataVisita2 | java.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:
| Campo | Valor |
|---|---|
| Search Key | EDU_VisitasPorTecnicoJasper |
| Name | Visitas por Técnico (PDF) |
| Data Access Level | Client+Organization |
| Entity Type | EDU |
| Report | marcado |
| Jasper Report | bundle: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:
| Prefixo | Onde está o arquivo |
|---|---|
bundle:plugin:caminho | Dentro de um plugin (o recomendado) |
attachment:arquivo.jrxml | Anexado ao próprio registro do processo |
/caminho/absoluto | No 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
Erros comuns
| Sintoma | Causa provável | Correção |
|---|---|---|
| View Validate falha | Erro de SQL em alguma Column SQL | Monte o SELECT à mão no psql com as mesmas expressões e corrija |
| O relatório não filtra | DB Column Name do parâmetro diferente do nome da coluna na view | Tem de ser idêntico |
| Relatório mostra IDs em vez de nomes | Referência da coluna da view ficou como número | Passo 1: ajuste Reference e Reference Key |
| Relatório vazio ou erro de acesso | Faltou AD_Client_ID ou AD_Org_ID na view | Inclua as duas colunas e rode View Validate de novo |
| Jasper: "report not found" | Caminho do bundle: errado ou pasta fora do build.properties | Confira nome do plugin, pasta e arquivo |
| Jasper: parâmetro sempre nulo | Nome ou tipo diferente no .jrxml | Range chega como Nome1 e Nome2; _ID chega como Integer |
| Jasper abre dados de outra empresa | Consulta sem filtro por AD_CLIENT_ID | Passo 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 colunasAD_Client_ID,AD_Org_IDeAD_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
| Parte | Onde fica | Vai no 2Pack? |
|---|---|---|
| View (componentes e colunas) | Dicionário (Table and Column) | Sim, no tipo Table |
| Report View | Dicionário | Sim, junto do processo |
| Processo e parâmetros | Dicionário | Sim |
| Print Format | Dados do cliente | Só se incluído com o tipo PrintFormat |
.jrxml | Plugin | Vai 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.