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

FEBRABAN – 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 Como é gerada a 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


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 

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. 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

public 

List<Long>

executar(CartaRemessa

cartaRemessa,

String

mesRefLogado)

throws

RestricaoNegocioExcecao,

CampoObrigatorioNaoInformadoExcecao

{

//

Gera

Ologs protocololog.info("Gerando AMQPcarta (Advancedremessa Message[{}]", QueuingcartaRemessa.getMesReferencia()); Protocol)log.info("Gerando écarta umremessa protocolomesReferencia Logado [{}]", mesRefLogado); // Valida se os campos obrigatórios foram preenchidos validarCamposObrigatorios(cartaRemessa); // realiza uma série de mensagens assíncronas, utilizado para comunicação entre sistemas distribuídos. Ele foi desenvolvido para facilitar a troca de mensagens entre aplicativos e serviços de forma eficiente e confiável.

O AMQP foi projetado para ser independente de plataforma, permitindo a comunicação entre diferentes sistemas e linguagens de programação. Ele define um conjuntoverificações de regras ede formatosnegócios paraem enviar,um rotearobjeto CartaRemessa. // Primeiro, verifica se o modelo de CartaRemessa é uma "Carta Acerto" e receberse mensagens,certas garantindo que elas sejam entregues de maneira ordenada e confiável.

Uma das principais características do AMQP é a utilização de filas de mensagens. As mensagenscondições são publicadascumpridas. em// filasSe 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 podemmodelo. serSe consumidasexistir, poroutra umexceção ou// maisé consumidores,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 umo modelo deda pub/subcarta (publicação/assinatura).remessa IssoICartaRemessaServico permitecartaRemessaServico que= oscartaRemessaServicoFabrica.getServico(cartaRemessa.getCartaRemessaModeloEnum()); aplicativos// enviem e recebam mensagens de forma assíncrona, desacoplandoChama o produtormétodo dagerarCartaRemessa(cartaRemessa, mensagemmesRefLogado do consumidor.

Além das filas, o AMQP também define trocas (exchanges) e vinculações (bindings) para rotear as mensagens para as filas corretas. As trocas recebem mensagens dos produtores e as encaminham para as filas com base em regras de roteamento específicas. As vinculações são utilizadas para definir a relação entre as trocas e as filas.

O AMQP suporta diferentes modelos de entrega de mensagens, como confirmação de entrega (acknowledgment), que garante que as mensagens sejam entregues com sucesso, e qualidade de serviço (QoS),cartaRemessaServiço quereturn permitecartaRemessaServico.gerarCartaRemessa(cartaRemessa, definirmesRefLogado); níveis}

de

 prioridade para as mensagens.

O protocolo AMQP é amplamente utilizado em sistemas distribuídos e arquiteturas orientadas a mensagens, como em aplicações de mensageria, Internet das Coisas (IoT), sistemas financeiros e sistemas de notificação em tempo real.

Em resumo, o protocolo AMQP é um protocolo de mensagens assíncronas que facilita a comunicação entre sistemas distribuídos, oferecendo confiabilidade, flexibilidade e escalabilidade. Ele utiliza filas, trocas e vinculações para rotear as mensagens de forma eficiente e suporta diferentes modelos de entrega e qualidade de serviço.

Figura

1:

Protocolo

AMQP

2.2 RabbitMQ

O RabbitMQ é um software de mensagem assíncrona de código aberto, que implementa o protocolo AMQP (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 entre os produtores e consumidores, garantindo a entrega ordenada e controlada.

2.3 Telas em questão

image.png

image.png

2.4 Objeto JSON 

O objeto JSON recebido pelo serviço de mensageria RabbitMQ é proveniente de ações realizadas na entidade "Servidor" no sistema e-Estado. Dentre as ações inclui-se: criação, atualização de dados e exclusão.

O objeto JSON contém diversos campos que representam os dados do servidor, como identificação, matrícula, tipo de vínculo, data de admissão, entre outros. Essas informações são cruciais para acompanhar e registrar o histórico dos servidores no sistema. Abaixo pode-se conferir o objeto de retorno do serviço rabbitMQ.

Quando a ação é INSERT, o RabbitMQ retorna o seguinte objeto:

{
  "id": 215349,
  "matricula": 600003369,
  "tipo_vinculo_id": 7,
  "data_admissao": "15/12/2022",
  "concurso_id": null,
  "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": {
    "id": 1758202,
    "nome": "Lucas Teste",
    "data": "2023-06-23T08:34:21.500402"
  },
  "pessoa_fisica": {
    "pessoa_id": 1758202,
    "estado_civil_id": 2,
    "sexo_id": 1,
    "escolaridade_id": null,
    "tipo_sanguineo_id": null,
    "cpf": "22******50",
    "data_nascimento": "2003-05-10",
    "falecimento": null,
    "raca": null,
    "pcd": null,
    "tipo_nacionalidade": null,
    "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": 5582
  },
  "poder": null,
  "previdencia": null,
  "regime": null,
  "registro_ponto": null,
  "tipo_vinculo": {
    "id": 7,
    "nome": "Estagiário",
    "grupo": null
  },
  "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 a ação é UPDATE, o RabbitMQ retorna o seguinte objeto:

{
  "id": 1534244,
  "nome": "JESSE ELIAS VIEIRA CAMPOS                    ",
  "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": []
}

2.4 Campos Integrados

Os seguintes campos podem refletir-se em ambos os sistemas:

Tabela Governa Campo Governa e-Estado

Obs

rh.servidor Matrícula matricula matricula  
-- 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_desligamento Data do Desligamento data_desligamento objeto servidor.data_desligamento  
rh.lotacao_mensal Lotação de Contratação
 (id, descricao)
descricao  objeto servidor.municipio_concurso_lotacao_id  
admin.pessoa_fisica Pessoa
(id, nome)
nome objeto servidor.pessoa
campos pessoa.id e pessoa.nome
propriedade nome = Protected - Precisa usar getNome(id) ou setNome(nome)
-- CPF cpf objeto servidor.pessoa_fisica.cpf  
-- RG rg objeto servidor.pessoa_fisica.rg.rg  
-- data de Nascimento data_nascimento objeto servidor.pessoa_fisica.data_nascimento  
3. Possíveis Soluções

Para os campos que não existem no objeto JSON de retorno do serviço RabbitMQ, a seguinte solução pode ser considerada:

  • 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 Servidor

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

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ção 2
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ção 2
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ção 2
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ção 2
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ção 2
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ção 2
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ção 2
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

Neste estudo, analisamos 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, data de admissão, data do efetivo exercício, data do desligamento, lotação de contratação, nome e CPF.

Alguns campos importantes não possuem correspondência direta nos sistemas, como data de progressão, tipo de admissão e tempos de serviço (federal, estadual, municipal e afastamento). Esses campos requerem uma avaliação mais aprofundada e busca por possíveis soluções, como adição de campos.

5. Referências 

Como Disponibilizar o RabbitMQ para múltiplos consumos:

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