Importação da base CNPJ

A importação é a única forma de atualizar a base do TermoLeads. Ela é disparada pelo master na tela Dados da Receita Federal (/master/dados-receita) e roda inteira no backend, em segundo plano: baixa o mês mais recente publicado pela Receita, lê os arquivos, monta uma tabela nova e, no fim, troca a tabela atual por ela.

O backend não baixa nada sozinho ao subir. Sem o master disparar, a base fica como está.

Entradas e saídas

PontoDescrição
EntradaA pasta mensal mais recente (AAAA-MM) do compartilhamento público de dados CNPJ da Receita Federal
SaídaA tabela cnpj substituída pela base do mês, as tabelas de domínio regravadas e uma linha no histórico cnpj_import_execucao
Quem disparaSó o master (isMaster no token do TermoAuth)

As etapas

O progresso mostra em que etapa a importação está. Os nomes abaixo são os da tela, com o valor que o backend devolve em etapa.

1. Download (baixando)

O backend lista as pastas do WebDAV público da Receita, escolhe a pasta de mês mais recente e lista os .zip dela com os tamanhos. Os arquivos são baixados para DOWNLOAD_DIR/AAAA-MM/, até três ao mesmo tempo (CNPJ_CONCURRENCIA).

  • Cada arquivo tem até 6 tentativas, com espera crescente entre elas.
  • Um download interrompido é retomado de onde parou, e arquivo que já está completo no disco é pulado.
  • Depois de baixado, o .zip tem a integridade conferida. Se estiver corrompido, é apagado e baixado de novo do zero.
  • Se algum arquivo falhar depois de todas as tentativas, a importação para aqui: importar um mês pela metade trocaria uma base boa por uma incompleta.

2. Preparação (preparando)

Cada .zip é classificado pelo início do nome (Estabelecimentos, Empresas, Socios, Simples, Cnaes, Motivos, Municipios, Naturezas, Paises, Qualificacoes); arquivo com outro nome é ignorado e registrado no log. Sem nenhum Estabelecimentos*.zip, a importação para, porque não há o que montar.

Em seguida vem a conferência de espaço em disco: as partições temporárias precisam do tamanho dos CSVs descompactados mais 10%. Sem espaço, a importação para com a mensagem de quanto falta. Por fim, restos de uma execução anterior (tabela nova incompleta e partições no disco) são apagados. A tabela cnpj atual não é tocada.

3. Leitura e particionamento (importando)

As tabelas de domínio, que são pequenas, viram mapas de código e descrição na memória. Se o arquivo de um domínio não veio na pasta ou falhou na leitura, o mapa é carregado da tabela que já está no banco.

Empresas, sócios, Simples e estabelecimentos são lidos uma única vez e reescritos em 512 partições no disco, separadas por faixa de CNPJ básico. O banco fica de fora desta etapa: é só leitura e escrita sequencial em disco.

4. Montagem das linhas (montagem)

Para cada faixa, em ordem crescente, o backend carrega na memória as empresas, o Simples e os sócios daquela faixa, percorre os estabelecimentos da mesma faixa e monta a linha completa de cada um, com todas as descrições. As linhas entram na tabela nova, cnpj_novo, criada sem índices para a carga ser mais rápida. Cada partição é apagada assim que é usada, e o disco vai esvaziando conforme a montagem anda.

Se a montagem terminar sem nenhuma linha, a importação para e a base atual é mantida.

5. Índices (indices)

A tabela nova ganha a chave primária e todos os índices que a cnpj tem hoje, lidos do próprio banco. Esta etapa pode levar alguns minutos.

6. Virada

Numa única transação, a tabela cnpj é removida, a cnpj_novo recebe o nome dela (junto com a chave primária e os índices) e as tabelas de domínio são regravadas com os dados do mês. Quem consulta vê a base antiga até o fim da transação e a nova logo depois, nunca uma tabela vazia. Depois disso vêm a atualização das estatísticas do PostgreSQL (ANALYZE) e a remoção das partições que sobraram.

Limpeza dos arquivos da Receita

Os arquivos da Receita têm problemas conhecidos, tratados na leitura para que uma linha ruim não derrube o arquivo inteiro:

  • Codificação. Os CSVs vêm em Latin-1 e são convertidos para UTF-8 sem perder nenhum acento.
  • Bytes nulos. Alguns campos trazem o caractere nulo como lixo de preenchimento; ele é removido antes da leitura.
  • Quebras de linha dentro de campos. O leitor de CSV reagrupa campos entre aspas que contêm quebra de linha.
  • Linhas malformadas. Registro com número de colunas diferente do esperado é descartado e contado.
  • Estabelecimento sem CNPJ completo ou com CNPJ repetido. É descartado e contado; no caso de repetição, vale a primeira ocorrência.

O total de linhas descartadas aparece por arquivo e no resumo da importação.

Cancelamento

Durante a importação, o master pode clicar em Cancelar importação e confirmar no diálogo. O backend para no próximo ponto seguro (entre arquivos, a cada lote de linhas e antes dos índices e da virada), apaga as partições e a tabela nova e registra a execução como cancelado.

A virada não é cancelável

O último ponto de cancelamento é logo antes da virada. Depois dele a transação acontece e a importação vai até o fim.

Acompanhamento na tela

  • Início idempotente. Clicar em importar com uma importação já em andamento só devolve o progresso atual; não abre uma segunda execução.
  • Progresso ao vivo. A tela consulta GET /api/importar/status a cada 700 milissegundos. A barra geral avança pelos bytes baixados (até 30%), pelos bytes lidos (até 60%), pelas linhas montadas (até 96%) e fica em 96% durante os índices, até concluir.
  • Detalhe por arquivo. Cada .zip aparece com o estado (pendente, baixando ou importando, concluído ou falha), as linhas lidas e as descartadas.
  • Log. As últimas 200 mensagens do backend ficam visíveis na tela.
  • Histórico. Abaixo do painel, a tela lista as últimas 50 execuções gravadas no banco, com mês, situação, arquivos e linhas. As situações possíveis estão em Base CNPJ .

O que pode dar errado

ProblemaO que acontece com a base atual
Servidor da Receita fora do ar ou algum arquivo sem conseguir baixarContinua no ar; a execução termina como erro
Espaço em disco insuficienteContinua no ar; a mensagem diz quanto espaço é necessário
Nenhum Estabelecimentos*.zip na pasta ou nenhuma linha montadaContinua no ar
Um arquivo falha na leituraA base nova entra no ar sem os dados daquele arquivo; a execução termina como concluido_com_falhas
Cancelamento pelo masterContinua no ar
Backend reiniciado no meioContinua no ar; o progresso em memória se perde e a execução fica no histórico como executando. A próxima importação limpa os restos.
Atualizado em 2026/10/10 15:04