Ir para o conteúdo principal

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)
Diego Gonçalves de Almeida (Assessor)
Jônatas Legal (Técnico em Tecnologia da Informação e Comunicação) (Assessor)
Rodrigo Stefano Sales Nascimento (Assessor)

Equipe do estudo CAOS

Alvo

Sistema Governa

Origem
  • Objetivo estratégico: Separar Carta Remessa na sua geração de relatório por Identificador.
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ário

FEBRABANEBRABAN – 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 ComoGeração é gerada ada Carta Remessa?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


Figura 1: Menu de emissão de carta remessa

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 RabbitMQ
Separação dos Relatórios

O RabbitMQ é um software de mensagem assíncrona de código aberto, que implementaAtualmente, o protocolosistema AMQPGoverna (Advanced Message Queuing Protocol). Ele é amplamente utilizado como um intermediário de mensagens entre diferentes sistemas e serviços distribuídos.

O RabbitMQ fornece uma plataforma robusta para a troca de mensagens, permitindo que aplicativos e serviços se comuniquem de maneira eficiente e confiável. Ele utiliza filas de mensagens para armazenar e entregar as mensagens entregera os produtoresrelatórios eda consumidores,Carta garantindo a entrega ordenada e controlada.

2.3 TelasRemessa em questão

3

etapas: image.pngimage.png

image.pngNa 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 2.4Etapa Objeto2, JSONa função gerarRelatorioCartaRemessa()

Oé objetochamada JSONcom recebidoa pelo serviçolista de mensageriadetalhes RabbitMQda éCarta provenienteRemessa de ações realizadasobtida na entidadeetapa "Servidor"1. noEsta sistema e-Estado. Dentre as ações inclui-se: criação, atualizaçfunção degera dadosum relatório baseado nos detalhes fornecidos e exclusão.

retorna

Oum objetoByteArrayOutputStream JSONque contém diversos campos que representam os dados do servidor,relatório.

como

Na identificaçEtapa 3, a função,o matrícula,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 vínculo, datamodelo de admissão,carta entreremessa
      outros.if Essas(CartaRemessaModeloEnum.eCartaConsignacao(cartaRemessa.getCartaRemessaModeloEnum())) informações{
          // Busca os detalhes da carta remessa consignação cruciaispelo 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 acompanharos epróximos registrarelementos
              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 históricoforam dosbuscados servidoresna no sistema. Abaixo pode-se conferir iteração objetoanterior
  deif retorno(CartaRemessaModeloEnum.eCartaConsignacao(cartaRemessa.getCartaRemessaModeloEnum())) do{
      serviç// Busca os detalhes da carta remessa consignação rabbitMQ.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;
}

 

QuandoEtapa a2 ação- éAbstractCartaRemessaMB.java INSERT,- oMétodo RabbitMQ retorna o seguinte objeto:gerarRelatorioCartaRemessa

{public "id":StreamedContent 215349,gerarRelatorioCartaRemessa(String "matricula":numeroCarta, 600003369,String "tipo_vinculo_id":nomeCartaRemessa, 7,String "data_admissao":mesReferencia, "15/12/2022",String "concurso_id":lotacaoCodigo)
null,throws "numero_decreto": null,
  "data_decreto": null,
  "numero_diario_oficial": null,
  "data_diario_oficial": null,
  "data_posse": null,
  "data_efetivo_exercicio": null,
  "cargo_efetivo_id": null,
  "cargo_cds_id": null,
  "funcao_id": null,
  "unidade_vinculo_id": 2,
  "previdencia_id": null,
  "vinculo_original_id": null,
  "estado_id": null,
  "municipio_id": null,
  "poder_id": null,
  "regime_id": null,
  "conta_fgts": null,
  "unidade_pagamento_id": null,
  "conta_pagamento_id": null,
  "padrao_id": null,
  "horas_semanais": null,
  "horas_extras": null,
  "registro_ponto_id": null,
  "pessoa_id": 1758202,
  "plantonista": null,
  "habilidade_cargo_efetivo_id": null,
  "inscricao_concurso": null,
  "nota_final_concurso": null,
  "classificacao_concurso": null,
  "pcd": null,
  "negro": null,
  "processo_judicial": null,
  "ocupa_cargo_publico": null,
  "processo_sei": null,
  "oficio_apresentacao": null,
  "municipio_concurso_lotacao_id": null,
  "data_desligamento": null,
  "siape": null,
  "atividade_privativa_cargo": null,
  "matricula_antiga": null,
  "matricula_nome": "600003369 - Lucas Teste",
  "estado": null,
  "municipio": null,
  "departamento_id": "",
  "cargo_efetivo": null,
  "cargo_cds": null,
  "concurso": null,
  "funcao": null,
  "padrao": null,
  "pessoa":RelatorioGeracaoExcecao {
  "id": 1758202,
    "nome": "Lucas Teste",
    "data": "2023-06-23T08:34:21.500402"
  },
  "pessoa_fisica":try {
      
    "pessoa_id":List<CartaRemessaDetalheVisao> 1758202,listaCartaRemessaDetalheVisao "estado_civil_id":= 2,this.buscarListaCartaRemessaDetalheVisao();
  
      "sexo_id":// 1,Removida "escolaridade_id":a null,geração "tipo_sanguineo_id":do null,arquivo "cpf":para "22******50"o banco a pedido do cliente
      // ByteArrayOutputStream relatorioCartaRemessaViaBanco = geradorCartaRemessa.gerarRelatorioCartaRemessa(
      // super.getEmpresaAutenticada(),
      "data_nascimento":// "2003-05-10"this.cartaRemessa, listaCartaRemessaDetalheVisao, IRelatorioCartaRemessaGerador.ViaCartaRemessa.BANCO);
      
      ByteArrayOutputStream relatorioCartaRemessaViaFinanceiro = geradorCartaRemessa.gerarRelatorioCartaRemessa(
              super.getEmpresaAutenticada(), "falecimento":this.cartaRemessa, null,listaCartaRemessaDetalheVisao,
              "raca":IRelatorioCartaRemessaGerador.ViaCartaRemessa.FINANCEIRO);
      
      null,return "pcd":this.gerarStreamZip(relatorioCartaRemessaViaFinanceiro, null,numeroCarta, "tipo_nacionalidade":nomeCartaRemessa,
              null,mesReferencia, "nacionalidade": null,
    "pais": null,
    "estado": null,
    "naturalidade": null,
    "data_entrada": "2003-05-10",
    "pis_pasep": null,
    "email": "sor*****@g****.com",
    "doador_de_sangue": null,
    "raca_id": 5,
    "tipo_nacionalidade_id": 2,
    "pais_id": 1,
    "nacionalidade_id": 1,
    "estado_id": 21,
    "naturalidade_id": 5582lotacaoCodigo);
      
  }, "poder":catch null,(Exception "previdencia": null,
  "regime": null,
  "registro_ponto": null,
  "tipo_vinculo":e) {
      "id":throw 7,new "nome": "Estagiário",
    "grupo": nullRelatorioGeracaoExcecao(e);
  },
  "unidade_vinculo": {
    "id": 2,
    "instituicao_id": 1,
    "unidade_id": null,
    "responsavel_id": 1744688,
    "nome": "Superintendência Estadual de Tecnologia da Informação e Comunicação",
    "sigla": "SETIC",
    "gestora": 1,
    "orcamentaria": 1,
    "administrativa": 1,
    "cnpj": "17.*****/******",
    "id_departamento_sinvrea": null,
    "tipo_normatizacao_id": 2,
    "numero_normatizacao": "27.577",
    "staff": null,
    "colegiada": null,
    "codigo_orcamentario": "110007",
    "data_normatizacao": "2022-11-04",
    "extincao_organograma_id": null,
    "endereco_id": 49685,
    "departamento_id": null,
    "orgao_sei_id": 73,
    "unidade_sei_id": null,
    "data_criacao": null
  },
  "unidade_pagamento": null,
  "vinculo_original": null,
  "nome": "Lucas Teste"
}

Quando 

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 UPDATE,para o RabbitMQnome 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 seguintearquivo objeto:

zip
{para download com nome definido
  return new DefaultStreamedContent(is, "id": 1534244,
  "nome": "JESSE ELIAS VIEIRA CAMPOS                    "application/zip", "cpf": "00******56",
  "data_nascimento": "****-**-**",
  "rg": {
    "registro": 3**6,
    "rg": "1******5",
    "orgao_emissor": "SSP",
    "estado": "RO",
    "data_emissao": "15/02/2008"
  },
  "nome_mae": null,
  "data_nascimento_mae": null,
  "sexo": 1,
  "estado_civil": 1,
  "raca": 2,
  "tipo_sanguineo": 1,
  "escolaridade": 5,
  "nacionalidade_bacen": 1058,
  "naturalidade": "Porto Velho",
  "pis": {
    "pessoa_id": 1534244,
    "tipo_documento_id": 11,
    "numero": "1*******7"
  },
  "titulo_eleitor": {
    "pessoa_id": 1534244,
    "tipo_documento_id": 3,
    "registro": 4***7,
    "numero": "0**********6",
    "complemento1": "0*2",
    "complemento2": "0**7",
    "data_emissao": null
  },
  "endereco": {
    "rua": "Rua *******",
    "numero": ****,
    "complemento": "RE******** *****A",
    "bairro": "Nova Esperança",
    "cep": 7*****8,
    "cidade": {
      "id": 5582,
      "nome": "Porto Velho",
      "cod_ibge": 1100205,
      "estado_id": 21
    },
    "estado": {
      "id": 21,
      "nome": "Rondônia",
      "sigla": "RO",
      "codigo_ibge": 11,
      "pais_id": 1
    }
  },
  "deficiencias": [],
  "parentes": []zipNome);
}

2.43 CamposSeparação Integradosdos Relatórios por Lotação

OsWORK seguintesIN campos podem refletir-se em ambos os sistemas:PROGRESS....

Tabela GovernaCampoGovernae-Estado

Obs

rh.servidorMatrículamatriculamatricula 
--Data de Admissão
admissao
objeto servidor.data_admissao 
--Data do Efetivo Exercício
data_efetivo_exercicio
objeto servidor.data_efetivo_exercicio 
--Data de Progressão
data_progressao
não existe campo que possa ser utilizado no objeto de retorno 
--Tipo de Admissão
tipo_admissao
[Admissão primeiro emprego,
Admissão com emprego anterior,
Transf. com ônus para cedente,
Transf. sem ônus para cedente,
Outros]
não existe campo que possa ser utilizado no objeto de retorno 
--tempo de serviço Federal
tempo_anterior_federal
 não existe campo que possa ser utilizado no objeto de retorno 
--tempo de serviço Estadual
tempo_anterior_estadual
 não existe campo que possa ser utilizado no objeto de retorno 
--tempo de serviço Municipal
tempo_anterior_municipal
 não existe campo que possa ser utilizado no objeto de retorno 
--tempo de serviço Afastamento
tempo_anterior_afastamento
 não existe campo que possa ser utilizado no objeto de retorno 
rh.servidor_desligamentoData do Desligamentodata_desligamentoobjeto servidor.data_desligamento 
rh.lotacao_mensalLotação de Contratação
 (id, descricao)
descricao objeto servidor.municipio_concurso_lotacao_id 
admin.pessoa_fisicaPessoa
(id, nome)
nomeobjeto servidor.pessoa
campos pessoa.id e pessoa.nome
propriedade nome = Protected - Precisa usar getNome(id) ou setNome(nome)
--CPFcpfobjeto servidor.pessoa_fisica.cpf 
--RGrgobjeto servidor.pessoa_fisica.rg.rg 
--data de Nascimentodata_nascimentoobjeto servidor.pessoa_fisica.data_nascimento 
3. Possíveis Soluções

ParaWORK osIN campos que não existem no objeto JSON de retorno do serviço RabbitMQ, a seguinte solução pode ser considerada:PROGRESS....

  • Verificar se os campos existem no banco do e-Estado e adicioná-los ao objeto JSON caso existam
História

O quê: Eu, dev, preciso criar uma propriedade Matrícula na entidade de Servidorxxxxxxxxxxxxxxxxxxxxxx

Por quê: para realizar a integração de dados de Informações cadastradas no sistema e-Estadoxxxxxxxxxxxxxxxxxxxxxxxxx

Regras e Validações --
Pontuação 2?
História

O quê: Eu, dev, preciso criar uma propriedade Data do Efetivo Exercício na entidade de Servidor

Por quê: para realizar a integração de dados de Informações cadastradas no sistema e-Estado

Regras e Validações--
Pontuação2
História

O quê: Eu, dev, preciso criar uma propriedade Data do Desligamento na entidade de Servidor

Por quê: para realizar a integração de dados de Informações cadastradas no sistema e-Estado

Regras e Validações--
Pontuação2
História

O quê: Eu, dev, preciso criar uma propriedade Lotação de Contratação na entidade de Servidor

Por quê: para realizar a integração de dados de Informações cadastradas no sistema e-Estado

Regras e Validações--
Pontuação2
História

O quê: Eu, dev, preciso criar uma propriedade Pessoa na entidade de Servidor

Por quê: para realizar a integração de dados de Informações cadastradas no sistema e-Estado

Regras e Validações--
Pontuação2
História

O quê: Eu, dev, preciso criar uma propriedade CPF na entidade de Servidor

Por quê: para realizar a integração de dados de Informações cadastradas no sistema e-Estado

Regras e Validações--
Pontuação2
História

O quê: Eu, dev, preciso criar uma propriedade RG na entidade de Servidor

Por quê: para realizar a integração de dados de Informações cadastradas no sistema e-Estado

Regras e Validações--
Pontuação2
História

O quê: Eu, dev, preciso criar uma propriedade Data de Nascimento na entidade de Servidor

Por quê: para realizar a integração de dados de Informações cadastradas no sistema e-Estado

Regras e Validações--
Pontuação2
História

O quê: Eu, dev, preciso criar uma propriedade a entidade de Servidor

Por quê: para realizar a integração de dados de Informações cadastradas no sistema e-Estado

Regras e Validações--
  
4. Conclusão

NesteAo estudo,estudar analisamoso código fonte do Governa, foi possível identificar a integração entre os sistemas e-Estado e Governa, focando nos dados da entidade "Servidor" e suas correspondências em ambos os sistemas. Através dessa análise, chegamos a algumas conclusões:

A integração entre os sistemas e-Estado e Governa requer a associação correta dos campos compartilhados entre eles, como matrícula, datafuncionalidade de admissão, data do efetivo exercício, data do desligamento, lotaçgeração de contratação,Carta nomeRemessa e CPF.

Algunsde camposseus importantesrelató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 possuemsepara correspondênciaos diretarelatórios nospor sistemas, como data de progressãlotação, tipo de admissão eque tempospode dedemonstrar serviço (federal, estadual, municipal e afastamento). Esses campos requeremser uma avaliaçlimitação maisem aprofundadacenários eem buscaque é necessário agrupar os relatórios por possíveisessa soluções, como adiçinformação de campos.o.

5.

Com Referênciasbase

nessa

Comoanálise, Disponibilizaré opossível RabbitMQconcluir que é necessário fazer modificações no código fonte para múltiplosseparar consumos:os relatórios PDF por lotação.

https://documentos.sistemas.ro.gov.br/books/spikes-estudos-tecnicos/page/como-disponibilizar-o-rabbitmq-para-multiplos-consumos.

 

AMQP - Documentação oficial:

https://www.amqp.org/

 

RabbitMQ - Documentação oficial:

https://www.rabbitmq.com/documentation.html