0013 — Município informado pelo nome, resolvido por consulta e guardado em cache¶
Status: Aceita Data: 2026-09-29
Contexto¶
A issue #11 pediu que o
nfse onboard --sem-rede resolvesse o código IBGE do município sem rede. Com
--sem-rede, ou quando a consulta ao cadastro público falha, o município é o
único campo que o onboard deixa em branco sem ter nada a oferecer. E é o pior
de digitar: sete dígitos que ninguém sabe de cabeça, com um erro que não
aparece em lugar nenhum. A Sefin aceita qualquer código válido, e a nota vai
para a cidade errada.
A proposta original era embutir a tabela do ANEXO_A no binário. O trabalho
chegou a ser feito (PR #19, refs/pull/19/head) e foi fechado sem merge. A
ADR 0012 registrou o motivo, que é do autor
do projeto: não carregar um segundo cadastro inteiro dentro do binário.
A issue continuou aberta. O problema é real; só a solução tinha sido recusada.
Decisão¶
Resolver o problema sem a tabela, com três peças. Cada uma vale por si.
1. O código carrega a própria conferência. Um código de município do IBGE
tem o prefixo da UF nos dois primeiros dígitos e um dígito verificador no
último. Isso pega um dígito trocado, um código TOM da Receita (4 dígitos) ou um
código de UF, sem tabela e sem rede. O pkg/codmun faz essa conferência, e
ela passa a valer em todo lugar por onde um código entra: --municipio,
prestador.municipio no config check, servico.municipio_prestacao na nota
e a resposta do cadastro público (#12).
O IBGE numerou nove municípios sem dígito válido; eles estão listados no
código, e um teste confere o algoritmo contra os 5570 códigos do ANEXO_A.
2. O nome é resolvido pela lista do estado, uma vez. --municipio
"Curitiba/PR" pede ao serviço de localidades do IBGE a lista de municípios da
UF (/estados/PR/municipios) e procura o nome nela. A lista inteira vai
para o cache em disco que o DANFSe já usa
(ADR 0012). A UF é obrigatória: 232 nomes se
repetem entre estados, e escolher um poria a nota na cidade errada sem que nada
reclamasse. A consulta revela ao IBGE a UF de quem emite, e não o município.
3. O cache torna o nome utilizável sem rede. Depois da primeira consulta,
qualquer município daquela UF é resolvido com --sem-rede. Um nome que nunca
foi consultado, sem rede, gera um erro que diz as duas saídas: informar o
código ou rodar uma vez com rede.
Consequências¶
- O binário não cresce. A decisão da ADR 0012 continua de pé.
--sem-rederesolve o código, mas não o nome, na primeira vez. É o custo de não embutir a tabela, e é o ponto em que a proposta original era melhor. Quem roda sem rede na primeira vez precisa do código. A diferença é que agora um código errado é recusado na hora, em vez de virar uma nota na cidade errada.- Todo código de município digitado à mão passa a ser conferido. Um
nfse.yamlque oconfig checkaceitava pode passar a ser recusado. Isso só acontece se o código estiver errado, e nesse caso as notas emitidas com ele foram para a cidade errada. - O cache também é conferido. Ele é um JSON no diretório de cache do
usuário e é compartilhado com o DANFSe, e o
onboardgrava o que encontra nele nonfse.yaml. Toda entrada que entra no cache, é lida dele ou sai dele passa pelas mesmas regras da lista. Um nome que duas entradas respondem não resolve para nenhuma delas. - A lista do IBGE é conferida, não aceita de boa-fé. Todo código que vem nela precisa ser válido e da UF pedida. Senão, a resposta é descartada inteira: uma lista que pode pôr um nome no código errado é pior do que nenhuma.
- A normalização dos nomes é testada contra a tabela oficial. Acentos,
caixa, espaços e pontuação caem, e
Alta Floresta D'Oesteealta floresta doesteviram a mesma chave. Um teste lê oANEXO_Ae garante duas coisas: que dois municípios da mesma UF nunca dão a mesma chave, e que nenhuma letra dos nomes oficiais escapa da normalização. A tabela entra nos testes, não no binário.
Alternativas consideradas¶
Embutir a tabela (PR #19). Resolve tudo offline, desde a primeira vez. Foi recusada pelo autor, e a razão está na ADR 0012.
Pedir ao usuário um arquivo com a tabela (--tabela-municipios
ANEXO_A.xlsx). Funcionaria offline, mas empurra para o usuário a tarefa de
achar a planilha certa no portal, justo o trabalho que o onboard existe para
poupar.
Consultar o município pelo nome direto no IBGE. O serviço não tem busca por nome. Consultar a lista da UF custa uma requisição, e ela serve para todas as consultas seguintes.
Aprendizado¶
"Não embutir a tabela" parecia fechar a porta do --sem-rede. Não fechou. O
que o --sem-rede precisava de verdade era não deixar passar um código errado,
e isso cabe em nove exceções e um dígito verificador. O nome é conveniência, e
a conveniência pode depender da rede uma vez.