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
| Ponto | Descrição |
|---|---|
| Entrada | A pasta mensal mais recente (AAAA-MM) do compartilhamento público de dados CNPJ da Receita Federal |
| Saída | A 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 dispara | Só 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
.ziptem 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.
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/statusa 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
.zipaparece 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
| Problema | O que acontece com a base atual |
|---|---|
| Servidor da Receita fora do ar ou algum arquivo sem conseguir baixar | Continua no ar; a execução termina como erro |
| Espaço em disco insuficiente | Continua no ar; a mensagem diz quanto espaço é necessário |
Nenhum Estabelecimentos*.zip na pasta ou nenhuma linha montada | Continua no ar |
| Um arquivo falha na leitura | A base nova entra no ar sem os dados daquele arquivo; a execução termina como concluido_com_falhas |
| Cancelamento pelo master | Continua no ar |
| Backend reiniciado no meio | Continua 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. |