Estudo Técnico para separar a Carta Remessa em PDF por Identificador
Data de elaboração | 17/07/2023 |
---|---|
Responsável pelo estudo |
Ádrian Rabelo Mendes (Assessor) |
Equipe do estudo | CAOS |
Alvo |
Sistema Governa |
Origem |
|
Objetivo | para que seja atendida a demanda de agilizar a demanda diária de desbloqueios de pagamentos e a respectiva disponibilização das cartas remessas em cada processo SEI (demanda Nº: 0031.072694/2022-33) |
GlossárioEBRABAN – Federação Brasileira de Bancos
CNAB240 – Centro Nacional de Automação Bancária
1. Introdução
A carta remessa é um documento ou arquivo eletrônico contendo detalhes de uma transação ou série de transações a serem processadas por um banco ou outra instituição financeira. Estes detalhes podem incluir informações sobre o remetente e o destinatário do pagamento, o valor da transação, a data da transação, entre outros.
Atualmente, as Cartas Remessa são produzidas em um formato padrão definido pela Federação Brasileira de Bancos (FEBRABAN), conhecido como CNAB240. Este formato estruturado facilita o processamento automatizado das transações pelos bancos e é amplamente aceito em todo o setor bancário brasileiro.
No sistema Governa, a geração da carta remessa é feita por um processo que envolve várias etapas. Neste estudo, iremos explorar estas etapas em detalhes, e fornecer recomendações para a implementação da separação dos relatórios nela gerados.
2. Desenvolvimento
2.1 Geração da Carta Remessa
A carta remessa pode ser gerada através do seguinte menu no sistema Governa, módulo de Recursos Humanos:
Movimentação Mensal > Controle Bancário > Carta Remessa > Emitir
Na figura 2, na tela de emissão de Carta Remessa, podemos observar diversas opções para que o usuário possa escolher no evento da geração da mesma.
Para gerar a Carta remessa, o usuário precisará preencher todos os campos obrigatórios, marcados com asterisco * e acionar o botão Executar. Se a carta remessa nas condições que o usuário escolheu já foi gerada, o botão Baixar Relatório estará ativo, permitindo assim, que o usuário faça download do arquivo gerado.
Ao clicar no botão Executar, o sistema começará a realizar as etapas do método executar() na classe CartaRemessaMB.java, conforme podemos ver nos métodos comentados do código abaixo.
CartaRemessaMB.java - Método executar
public void executar() {
try {
// Verifica se há permissão para o usuário inserir sem validar o mês fechado.
isPermissaoBotaoInserirSemValidarMesFechado();
// Define a lista de verbas selecionadas nas verbas da carta remessa
this.cartaRemessa.setVerbas(verbaSelecionadaList);
// Define o mês de referência buscando da classe pai
String mesRefLogado = super.getMesReferenciaFormatado();
// Define a lista de cartaRemessaid de acordo com o retorno do método
// executar(cartaremessa, mesRefLogado) da instância da classe
// CartaRemessaBO. Essa por sua vez, é responsável por gerar as cartas
// remessas e retorna uma lista com as id’s caso sejam geradas.
this.listaCartaRemessaid = cartaRemessaBO.executar(this.cartaRemessa,mesRefLogado);
// Se gerou carta, entao gera o relatório
if (!listaCartaRemessaid.isEmpty()) {
// Define o modelo de acordo com o modelo da carta remessa enviado pelo usuário
setModelo(this.cartaRemessa.getModelo());
// Gera o arquivo zip de saída contendo os relatórios
file = this.gerarRelatorioCartaRemessa("", CartaRemessaModeloEnum.parse(
cartaRemessa.getModelo()).getDescricaoFormatada(), MesReferenciaUtil
.converterMesAnoParaAnoMesReferencia(
cartaRemessa.getMesReferencia()).toString(), ""
);
// Envia uma mensagem para o usuário informando que o registro foi //cadastrado com sucesso
super.enviarMensagemInfo(msgServico.getMsgGenericaRegistroCadastradoComSucesso(EntidadeRhEnum.CARTA_REMESSA));
// Envia uma mensagem para o usuário informando que o relatório foi gerado
super.enviarMensagemInfo(msgServico.getMensagem(MensagemChaveRh.CARTA_REMESSA_IMPRIMIR_RELATORIO));
} else {
// Envia uma mensagem para o usuário informando que não foi gerado carta remessa
super.enviarMensagemInfo(msgServico.getMensagem(MensagemChaveRh.CARTA_REMESSA_NAO_GERADAS));
}
// Captura os erros caso ocorram e retornam ao usuário a mensagem do erro
} catch (RestricaoNegocioExcecao e) {
log.warn(e.getMessage());
super.enviarMensagemErro(e.getMessage());
} catch (CampoObrigatorioNaoInformadoExcecao e) {
log.warn(e.getMessage());
super.enviarMensagemErro(msgServico.getMsgGenericaCampoObrigatorioNaoInformado(
e.getCamposNaoInformadosFormatado()));
} catch (RelatorioGeracaoExcecao e) {
log.error(e.getMessage(), e);
super.enviarMensagemErro(msgServico.getMsgGenericaErroInesperado(e.getMessage()));
} finally {
System.gc();
}
}
CartaRemessaBO.java - Método executar
public List<Long> executar(CartaRemessa cartaRemessa, String mesRefLogado)
throws RestricaoNegocioExcecao, CampoObrigatorioNaoInformadoExcecao {
// Gera logs
log.info("Gerando carta remessa [{}]", cartaRemessa.getMesReferencia());
log.info("Gerando carta remessa mesReferencia Logado [{}]", mesRefLogado);
// Valida se os campos obrigatórios foram preenchidos
validarCamposObrigatorios(cartaRemessa);
// realiza uma série de verificações de regras de negócios em um objeto CartaRemessa.
// Primeiro, verifica se o modelo de CartaRemessa é uma "Carta Acerto" e se certas condições são cumpridas.
// Se não forem, uma exceção é lançada. Em seguida, se o objeto CartaRemessa tiver um número, o método
// verifica se já existe um arquivo bancário associado a esse número e modelo. Se existir, outra exceção
// é lançada. Depois, procura uma CartaRemessa existente com o mesmo número e, se encontrada, atualiza os
// valores de lotacaoInicial e lotacaoFinal e o modelo do objeto CartaRemessa original, e então exclui
// a CartaRemessa encontrada.
validarRegraNegocio(cartaRemessa);
// Instancia a interface ICartaRemessaServiço de acordo com o modelo da carta remessa
ICartaRemessaServico cartaRemessaServico = cartaRemessaServicoFabrica.getServico(cartaRemessa.getCartaRemessaModeloEnum());
// Chama o método gerarCartaRemessa(cartaRemessa, mesRefLogado do serviço cartaRemessaServiço
return cartaRemessaServico.gerarCartaRemessa(cartaRemessa, mesRefLogado);
}
CartaRemessaAcertoSalarioLiquidoServico.java - Método gerarCartaRemessa
public List<Long> gerarCartaRemessa(CartaRemessa cartaRemessa, String mesRefLogado) throws RestricaoNegocioExcecao {
// Log
log.debug("Gerando o Acerto da Carta Remessa do Tipo {}", cartaRemessa.getCartaRemessaModeloEnum().getDescricaoFormatada());
// Retorna o resultado da função gerarAcerto(cartaRemessa, mesRefLogado)
return gerarAcerto(cartaRemessa, mesRefLogado);
}
AbstractCartaRemessaServico.java - Método gerarAcerto
protected List<Long> gerarAcerto(CartaRemessa cartaRemessa, String mesRefLogado) throws RestricaoNegocioExcecao {
// cria lista de objetos do tipo CartaRemessaDetalhe
List<CartaRemessaDetalhe> cartaRemessaDetalheList = cartaRemessaDetalhePersistencia.buscarCartaRemessaDetalheGerarCartaRemessaDoisAcerto(
QueryUtil.prepararParametro(cartaRemessa.getLotacaoInicial()), cartaRemessa.getLotacaoFinal(),
QueryUtil.prepararParametro(cartaRemessa.getMatriculaInicial()), QueryUtil.prepararParametro(cartaRemessa.getMatriculaFinal()),
QueryUtil.prepararParametro(cartaRemessa.getIdentificadorUnidadeGestora()), QueryUtil.prepararParametro(cartaRemessa.getRotina()),
MesReferenciaUtil.converterMesAnoParaAnoMesReferencia(cartaRemessa.getMesReferencia()),
QueryUtil.prepararParametro(cartaRemessa.getCartaRemessaModeloEnum().getDuasPosicoesFinais()));
// Adiciona diversos parâmetros ao final da lista cartaRemessaDetalheList
cartaRemessaDetalheList.addAll(cartaRemessaDetalhePersistencia.buscarCartaRemessaDetalheGerarCartaRemessaAcerto(
QueryUtil.prepararParametro(cartaRemessa.getLotacaoInicial()), cartaRemessa.getLotacaoFinal(),
QueryUtil.prepararParametro(cartaRemessa.getMatriculaInicial()), QueryUtil.prepararParametro(cartaRemessa.getMatriculaFinal()),
QueryUtil.prepararParametro(cartaRemessa.getIdentificadorUnidadeGestora()), QueryUtil.prepararParametro(cartaRemessa.getRotina()),
MesReferenciaUtil.converterMesAnoParaAnoMesReferencia(cartaRemessa.getMesReferencia()),
QueryUtil.prepararParametro(cartaRemessa.getCartaRemessaModeloEnum().getDuasPosicoesFinais())));
// retorna o resultado da função montarCartaAcerto(cartaRemessa, cartaRemessaDetalheList, mesRefLogado)
return montarCartaAcerto(cartaRemessa, cartaRemessaDetalheList, mesRefLogado);
}
AbstractCartaRemessaServico.java - Método montarCartaAcerto
private List<Long> montarCartaAcerto(CartaRemessa cartaRemessa, List<CartaRemessaDetalhe> detalhes, String mesRefLogado)
throws RestricaoNegocioExcecao {
// Verifica se a lista de detalhes da carta de remessa está vazia. Se estiver, retorna uma lista vazia.
if (detalhes.isEmpty()) {
return Collections.emptyList();
}
// Verifica se ja tem algum arquivo bancário gerado sem retorno
List<Long> servidoresParaAcerto = new ArrayList<>();
detalhes.forEach(item -> servidoresParaAcerto.add(item.getServidorMensal().getId()));
// A lista de chave sera utilizada para verificar se o servidor/pensao
// judicial/pensao vitalicia ja tiveram acerto gerado, ou carta sem retorno
List<String> detalhesChaves = new ArrayList<>();
detalhes.forEach(item -> detalhesChaves.add(item.getChave()));
// Busca os servidor que ja tem acerto
List<ArquivoBancario> arquivoJaGerado = new ArrayList<>();
int cont = 0;
int it = servidoresParaAcerto.size();
List<Long> idsServidorTemp = new ArrayList<>();
for (Long id : servidoresParaAcerto) {
idsServidorTemp.add(id);
cont++;
if (idsServidorTemp.size() == 2000 || cont == it) {
arquivoJaGerado.addAll(cartaRemessaDetalhePersistencia.buscarServidorQueJaTenhamAcerto(idsServidorTemp,
MesReferenciaUtil.converterMesAnoParaAnoMesReferencia(cartaRemessa.getMesReferencia()), cartaRemessa.getModelo(),
cartaRemessa.getRotina()));
idsServidorTemp.clear();
}
}
// Verifica se ja teve algum retorno com sucesso, caso tenha o mesmo sera
// retirado da nova carta
List<String> retirar = new ArrayList<>();
for (String chave : detalhesChaves) {
arquivoJaGerado.stream().forEach(arq -> {
if (chave.equals(arq.getChave())
&& ("00".equals(arq.getStatusRetorno()) || "BD".equals(arq.getStatusRetorno()) || "".equals(arq.getStatusRetorno()))) {
retirar.add(arq.getChave());
}
});
}
// Remove os servidores que ja teve sucesso
detalhes = detalhes.stream().filter(item -> !retirar.contains(item.getChave())).collect(Collectors.toList());
// Remover os servidores que estao sem arquivo, ou seja, ja estao em carta mais
// não tem arquivo gerado
arquivoJaGerado.clear();
retirar.clear();
List<CartaRemessaDetalhe> servidoresSemArquivo = new ArrayList<>();
cont = 0;
it = servidoresParaAcerto.size();
idsServidorTemp = new ArrayList<>();
for (Long id : servidoresParaAcerto) {
idsServidorTemp.add(id);
cont++;
if (idsServidorTemp.size() == 2000 || cont == it) {
servidoresSemArquivo.addAll(cartaRemessaDetalhePersistencia.buscarServidorQueJaTenhamAcertoENaoTermArquivoBancario(idsServidorTemp,
MesReferenciaUtil.converterMesAnoParaAnoMesReferencia(cartaRemessa.getMesReferencia()), cartaRemessa.getModelo(),
cartaRemessa.getRotina()));
idsServidorTemp.clear();
}
}
servidoresSemArquivo.forEach(item -> retirar.add(item.getChave()));
detalhes = detalhes.stream().filter(item -> !retirar.contains(item.getChave())).collect(Collectors.toList());
// Se não tiver resultado envia mensagem
if (detalhes.isEmpty()) {
throw new RestricaoNegocioExcecao(mensagemServicoRh.getMensagem(MensagemChaveRh.MENSAGEM_GERACAO_CARTA_REMESSA_SEM_RESULTADO));
}
// Agrupa os detalhes da carta remessa restantes por lotacaoMensalId e armazena em um mapa.
Map<Long, List<CartaRemessaDetalhe>> cartaRemessaDetalhePorLotacaoMensalId = new HashMap<>();
detalhes.forEach(item -> {
Long lotacaoMensalId = item.getCartaRemessa().getLotacaoMensal().getId();
if (cartaRemessaDetalhePorLotacaoMensalId.containsKey(lotacaoMensalId)) {
cartaRemessaDetalhePorLotacaoMensalId.get(lotacaoMensalId).add(item);
} else {
cartaRemessaDetalhePorLotacaoMensalId.put(lotacaoMensalId, new ArrayList<CartaRemessaDetalhe>(Arrays.asList(item)));
}
});
List<Long> cartaRemessaGeradaIdList = new ArrayList<>();
List<String> matriculasJaEnviadas = new ArrayList<>();
// Para cada lotacaoMensalId, cria uma nova carta remessa. Calcula o valor total da nova
// carta remessa somando os valores de todos os detalhes da carta remessa que pertencem a essa lotacaoMensalId.
for (Long chave : cartaRemessaDetalhePorLotacaoMensalId.keySet()) {
List<CartaRemessaDetalhe> cartaRemessaDetalheMapList = cartaRemessaDetalhePorLotacaoMensalId.get(chave);
// Soma Total da Carta Remessa
Fracao valorTotalCarta = new Fracao(0d);
// Lista para armazenas os detalhes da carta remessa
List<CartaRemessaDetalhe> cartaRemessaDetalheList = new ArrayList<>();
// Cria a Carta Remessa
CartaRemessa novaCartaRemessa = criarCartaRemessa(cartaRemessa.getRotinaCalculoEnum(), cartaRemessa.getCartaRemessaModeloEnum(),
cartaRemessaDetalheMapList.get(0).getCartaRemessa().getLotacaoMensal().getContaDebito().getContaDebito(),
cartaRemessaDetalheMapList.get(0).getCartaRemessa().getLotacaoMensal().getContaDebito().getConvenio(),
cartaRemessaDetalheMapList.get(0).getCartaRemessa().getLotacaoMensal().getContaDebito().getAgencia(),
cartaRemessaDetalheMapList.get(0).getCartaRemessa().getLotacaoMensal(), cartaRemessa.getNumero());
for (CartaRemessaDetalhe item : cartaRemessaDetalheMapList) {
if (item.getValor() > 0d) {
if (!matriculasJaEnviadas.contains(item.getChave())) {
matriculasJaEnviadas.add(item.getChave());
valorTotalCarta = valorTotalCarta.somarCom(new Fracao(item.getValor()));
cartaRemessaDetalheList.add(item);
}
}
}
// Atualiza os dados bancários para os detalhes da carta de remessa,
// salva a nova carta de remessa, e salva os detalhes da carta de remessa.
if (!cartaRemessaDetalheList.isEmpty()) {
atualizarDadosBancarios(cartaRemessaDetalheList);
// Valor Total da Carta
novaCartaRemessa.setValor(valorTotalCarta.doubleValor());
// Salva a Carta Remessa
salvarCartaRemessa(novaCartaRemessa);
// Salva os Itens da Carta Remessa Detalhe
salvarCartaRemessaDetalhe(novaCartaRemessa, cartaRemessaDetalheList, mesRefLogado);
// preenche a lista com todos os ids das carta remessas geradas
cartaRemessaGeradaIdList.add(novaCartaRemessa.getId());
}
}
// Retorna uma lista de IDs de todas as cartas de remessa que foram geradas
return cartaRemessaGeradaIdList;
}
Como podemos perceber no código acima, dentro do método montarCartaAcerto, nas linhas 78 a 86 , a organização de cartas remessa por lotação mensal já é executada de forma integral. Isso é feito por meio da construção de um mapa, no qual o ID da lotação mensal atua como chave, e os detalhes da carta remessa que correspondem àquela lotação mensal se tornam os valores associados a essa chave. Essa estruturação permite que todas as cartas remessa sejam automaticamente categorizadas de acordo com a respectiva lotação mensal.
2.2 Separação dos Relatórios
Atualmente, o sistema Governa gera os relatórios da Carta Remessa em 3 etapas:
Na Etapa 1, a função buscarListaCartaremessaDetalheVisao() é chamada para buscar os detalhes da Carta Remessa. Os detalhes são retornados como uma lista de objetos CartaRemessaDetalheVisao.
Na Etapa 2, a função gerarRelatorioCartaRemessa() é chamada com a lista de detalhes da Carta Remessa obtida na etapa 1. Esta função gera um relatório baseado nos detalhes fornecidos e retorna um ByteArrayOutputStream que contém os dados do relatório.
Na Etapa 3, a função gerarStreamZip() é chamada com o ByteArrayOutputStream gerado na etapa 2. Esta função define o nome do arquivo zip, prepara um fluxo de download com o arquivo para o relatório, que pode ser enviado para o cliente para download.
Etapa 1 - CartaRemessaBO - Método - BuscarListaCartaRemessaDetalheVisao
public List<CartaRemessaDetalheVisao> buscarListaCartaremessaDetalheVisao(CartaRemessa cartaRemessa, List<Long> idsCarta) {
// Verifica se a lista de idsCarta possui menos de 2000 elementos
if (idsCarta.size() < 2000) {
// Verifica o tipo de modelo de carta remessa
if (CartaRemessaModeloEnum.eCartaConsignacao(cartaRemessa.getCartaRemessaModeloEnum())) {
// Busca os detalhes da carta remessa consignação pelo idCartaRemessaDetalhe
return cartaRemessaDetalheConsignacaoRepositorio
.findCartaRemessaDetalheVisaoByIdCartaRemessaDetalhe(QueryUtil.preparaParametroListaNaoVazia(idsCarta));
} else {
// Busca os detalhes da carta remessa pelo idCartaRemessaDetalhe
return cartaRemessaDetalheRepositorio
.findCartaRemessaDetalheVisaoByIdCartaRemessaDetalhe(QueryUtil.preparaParametroListaNaoVazia(idsCarta));
}
}
List<CartaRemessaDetalheVisao> lista = new ArrayList<>();
List<Long> idsCartaTemp = new ArrayList<>();
// Itera sobre os idsCarta
for (int i = 0; i < idsCarta.size(); i++) {
// Adiciona o idCarta atual na lista temporária idsCartaTemp
idsCartaTemp.add(idsCarta.get(i));
// Verifica se atingiu o limite de 2000 elementos na lista temporária
if (i % 2000 == 0) {
// Verifica o tipo de modelo de carta remessa
if (CartaRemessaModeloEnum.eCartaConsignacao(cartaRemessa.getCartaRemessaModeloEnum())) {
// Busca os detalhes da carta remessa consignação pelo idCartaRemessaDetalhe na lista temporária
lista.addAll(cartaRemessaDetalheConsignacaoRepositorio
.findCartaRemessaDetalheVisaoByIdCartaRemessaDetalhe(QueryUtil.preparaParametroListaNaoVazia(idsCartaTemp)));
// Limpa a lista temporária para os próximos elementos
idsCartaTemp.clear();
} else {
// Busca os detalhes da carta remessa pelo idCartaRemessaDetalhe na lista temporária
lista.addAll(cartaRemessaDetalheRepositorio
.findCartaRemessaDetalheVisaoByIdCartaRemessaDetalhe(QueryUtil.preparaParametroListaNaoVazia(idsCartaTemp)));
// Limpa a lista temporária para os próximos elementos
idsCartaTemp.clear();
}
}
}
// Busca os detalhes restantes que não foram buscados na iteração anterior
if (CartaRemessaModeloEnum.eCartaConsignacao(cartaRemessa.getCartaRemessaModeloEnum())) {
// Busca os detalhes da carta remessa consignação pelo idCartaRemessaDetalhe na lista temporária
lista.addAll(cartaRemessaDetalheConsignacaoRepositorio
.findCartaRemessaDetalheVisaoByIdCartaRemessaDetalhe(QueryUtil.preparaParametroListaNaoVazia(idsCartaTemp)));
} else {
// Busca os detalhes da carta remessa pelo idCartaRemessaDetalhe na lista temporária
lista.addAll(cartaRemessaDetalheRepositorio
.findCartaRemessaDetalheVisaoByIdCartaRemessaDetalhe(QueryUtil.preparaParametroListaNaoVazia(idsCartaTemp)));
}
return lista;
}
Etapa 2 - AbstractCartaRemessaMB.java - Método gerarRelatorioCartaRemessa
public StreamedContent gerarRelatorioCartaRemessa(String numeroCarta, String nomeCartaRemessa, String mesReferencia, String lotacaoCodigo)
throws RelatorioGeracaoExcecao {
try {
List<CartaRemessaDetalheVisao> listaCartaRemessaDetalheVisao = this.buscarListaCartaRemessaDetalheVisao();
// Removida a geração do arquivo para o banco a pedido do cliente
// ByteArrayOutputStream relatorioCartaRemessaViaBanco = geradorCartaRemessa.gerarRelatorioCartaRemessa(
// super.getEmpresaAutenticada(),
// this.cartaRemessa, listaCartaRemessaDetalheVisao, IRelatorioCartaRemessaGerador.ViaCartaRemessa.BANCO);
ByteArrayOutputStream relatorioCartaRemessaViaFinanceiro = geradorCartaRemessa.gerarRelatorioCartaRemessa(
super.getEmpresaAutenticada(), this.cartaRemessa, listaCartaRemessaDetalheVisao,
IRelatorioCartaRemessaGerador.ViaCartaRemessa.FINANCEIRO);
return this.gerarStreamZip(relatorioCartaRemessaViaFinanceiro, numeroCarta, nomeCartaRemessa,
mesReferencia, lotacaoCodigo);
} catch (Exception e) {
throw new RelatorioGeracaoExcecao(e);
}
}
Etapa 3 - AbstractCartaRemessaMB.java - Método gerarStreamZip
private StreamedContent gerarStreamZip(ByteArrayOutputStream relatorioCartaRemessaViaFinanceiro, String numeroCarta, String modeloArquivo, String mesReferencia, String lotacaoCodigo) throws IOException {
// Removido geração do arquivo para o banco a pedido do cliente
// ArquivoOutputStream relatorioOutBanco = new ArquivoOutputStream(relatorioCartaRemessaViaBanco,
// String.format(IRelatorioCartaRemessaGerador.ARQUIVO_PDF_BANCO, numeroCarta, modeloArquivo, mesReferencia, lotacaoCodigo));
// recebe o relatorioCartaRemessaViaFinanceiro como entrada e utiliza a formatação adequada para o nome do arquivo PDF financeiro, utilizando os parâmetros fornecidos.
ArquivoOutputStream relatorioOutFinanceiro = new ArquivoOutputStream(relatorioCartaRemessaViaFinanceiro,
String.format(IRelatorioCartaRemessaGerador.ARQUIVO_PDF_FINANCEIRO, numeroCarta, modeloArquivo, mesReferencia, lotacaoCodigo));
// Aqui, é criado um ByteArrayOutputStream chamado out para armazenar os dados do arquivo ZIP. A função ZipUtil.zipar() é chamada para compactar o relatorioOutFinanceiro e armazenar o resultado no out.
ByteArrayOutputStream out = new ByteArrayOutputStream();
ZipUtil.zipar(out, relatorioOutFinanceiro);
// permite que os dados do arquivo ZIP sejam lidos a partir de um fluxo de entrada.
InputStream is = new ByteArrayInputStream(out.toByteArray());
gerouRelatorio = true;
// O nome do arquivo ZIP é formatado e é removido qualquer espaço em branco ou acentuação indesejada utilizando funções auxiliares.
String zipNome = String.format(IRelatorioCartaRemessaGerador.ARQUIVO_ZIP, numeroCarta, modeloArquivo, mesReferencia, lotacaoCodigo)
.replace(" ", "");
zipNome = StringUtil.removerAcentos(zipNome);
// retorna o arquivo zip para download com nome definido
return new DefaultStreamedContent(is, "application/zip", zipNome);
}
2.3 Separação dos Relatórios por Lotação
WORK IN PROGRESS....
3. Possíveis Soluções
WORK IN PROGRESS....
História |
O quê: Eu, dev, preciso criar xxxxxxxxxxxxxxxxxxxxxx Por quê: para xxxxxxxxxxxxxxxxxxxxxxxxx |
Regras e Validações | -- |
Pontuação | ? |
4. Conclusão
Ao estudar o código fonte do Governa, foi possível identificar a funcionalidade de geração de Carta Remessa e de seus relatórios em PDF. O processo atual consiste em buscar os detalhes da carta remessa, gerar os relatórios em PDF, criar um arquivo ZIP contendo os relatórios. No entanto, o código não separa os relatórios por lotação, o que pode demonstrar ser uma limitação em cenários em que é necessário agrupar os relatórios por essa informação.
Com base nessa análise, é possível concluir que é necessário fazer modificações no código fonte para separar os relatórios PDF por lotação.