Relatório Complexo


#1

boa noite,

Tenho um relatório bastante complexo o qual precisa de consulta em várias tabelas e processamento dos dados.
Vi que para exibir o relatorio tenho algumas regras e alternativas:
-Precisarei de uma tabela com os dados.
-Posso ter uma view mais ela não seria suficiente para mim.
-Pensei em uma tabela temporaria armazenando os dados do relatório, mais como ficaria acessos simultaneos ao relatório? Tem que excluir os dados?

Numa aplicação fora do Adempiere eu criaria um DTO com os atributos que vou exibir no relatório e enviaria uma coleção desse para o jasper processar sem ter essa coleção no banco.
Qual a melhor maneira de fazer isso no Adempiere?


#2

fgiordani,

Para fazer isso no ADempiere eu vejo duas alternativas.

1 - Usar uma stored procedure que faça todo o seu processamento e te retorne uma tabela da forma que você quer.

2 - Usar um processo Java mesmo, que faz o que você precisa com os dados, e após isso, joga em uma tabela temporária estes dados e mostra para o usuário.

Na segunda alternativa, você precisa pensar em uma solução para apagar estes dados temporários.

Uma das alternativas é tentar deixar uma coluna com um nome de uma Transaction que você pode criar usando as classes do próprio ADempiere, vc guarda só o nome delas em 1 das colunas, isso deve tornar os dados únicos e se outro usuário tentar entrar ao mesmo tempo, não vai ter problema.

Lembrando que a transaction foi só uma idéia de como gerar uma identificação única para cada vez que roda o relatório, tem que fechar elas.

Também creio que você pode também utilizar o seu approach do DTO, basta utilizar o processo customizado e jogar diretamente ao Jasper que está integrado ao ADempiere.

Depois se vc puder colocar um post sobre a saída que você utilizou, é um problema interessante!

Abraços.


#3

Alvaro, na solução 2, não precisa criar uma coluna com o nome da transaction.

Basta apenas em seu código, sempre utilizar transaction no sql.

Pois se dois usuários usarem o mesmo relatório, não tem problemas, pois são transactions diferentes.


#4

ola amontenegro,

Primeiramete fiz um processo java com uma tabela temporária e funcionou.
Para a tabela temporária ( T_* ) é obrigatório ter um atributo AD_PInstance_ID o qual criei com base na clase MTReport da seguinte forma:

	private I_AD_PInstance getAD_PInstance() throws Exception {
		if (instance == null) {
			Class<?> clazz = MTable.getClass(I_AD_PInstance.Table_Name);
			try {
				Constructor<?> constructor = null;
				constructor = clazz.getDeclaredConstructor(new Class[] { Properties.class, int.class, String.class });
				instance  = (I_AD_PInstance) constructor.newInstance(new Object[] { getCtx(), new Integer(getAD_PInstance_ID()), get_TrxName() });
			} catch (Exception e) {
				log.log(Level.SEVERE, "(id) - Table=" + MTTRPlanoManutencao.Table_Name + ",Class=" + clazz, e);
				log.saveError("Error", "Table=" + MTTRPlanoManutencao.Table_Name + ",Class=" + clazz);
				throw e;
			}
		}
		return instance ;
	}

Dessa forma atribui o código da instancia para cada registro da tabela temporária.
Depois de processar a classe é montada a query para a tabela temporária. O Adempiere adiciona automaticamente no where o código da instancia criada (Ainda tenho que ver como ele faz no código fonte).
Obs.: Não achei muitas referências sobre como funciona ou como deveria ser aplicada essa tabela (AD_PInstance) a não ser o que vi no código fonte, mas funcionou.

O problema é que o mesmo parâmetro que passo para o processo para montar a tabela temporária é aplicado a consulta e nao atende ao meu requisito. Quero que tudo o que foi criado seja retornado sem aplicar critério algum.

Seria minha segunda alternativa, e inicialmente achei que funcionasse da seguinte forma:

  CallableStatement cs = con.prepareCall("{funcao_procedure}");  
  ResultSet rs = cs.executeQuery();  

,mais ele apenas executa sem pegar o retorno, e dessa forma não vai funcionar ja só vai mudar a maneira de montar a tabela temporaria e o critério que mencionei anteriormente continuaria sendo adicionado ao where.
Obs.: Com a procedure tbem da para utilizar o recurso da tabela AD_PInstance.

Por fim acho que essa é a minha solução, mais não estou achando documentação.
Qual seria o procedimento para fazer esse processo? (Criar processo/relatorio, criar classe com implementacao especifica, estender alguma classe, …)

Agradeço sua atenção


#5

Bom dia pessoal.
Este topico obteve alguma solucao ?
estou com o mesmo problema