CNPJ Alfanumérico — Plano de Adaptação
Status: ✅ Implementado (2026-03-12)
Prazo externo: 1º de julho de 2026 (novos CNPJs alfanuméricos entram em vigor)
Impacto: 16 pontos de alteração em 10 arquivos (4 backend, 6 frontend)
Contexto
A partir de julho/2026, a Receita Federal emitirá CNPJs com caracteres alfanuméricos nos 12 primeiros dígitos (base), mantendo os 2 últimos como dígitos verificadores numéricos. CNPJs existentes permanecem 100% numéricos.
Formato: AA.AAA.AAA/AAAA-DD (A = alfanumérico, D = dígito verificador)
Algoritmo de Validação (Módulo 11 — SERPRO)
O algoritmo é unificado — a mesma fórmula funciona para CNPJs numéricos e alfanuméricos.
Conversão de caractere para valor
valor = charCodeAt(caractere) - 48| Caractere | ASCII | Valor |
|---|---|---|
0 | 48 | 0 |
9 | 57 | 9 |
A | 65 | 17 |
Z | 90 | 42 |
Cálculo dos Dígitos Verificadores
DV1 — pesos [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2] sobre posições 0-11:
soma = Σ (valor[i] × peso[i]) para i = 0..11
resto = soma % 11
DV1 = (resto < 2) ? 0 : 11 - restoDV2 — pesos [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2] sobre posições 0-12:
soma = Σ (valor[i] × peso[i]) para i = 0..12
resto = soma % 11
DV2 = (resto < 2) ? 0 : 11 - restoImplementação
const getVal = (ch: string) => ch.charCodeAt(0) - 48;Funciona identicamente para ambos os formatos:
getVal('3')→51 - 48=3getVal('A')→65 - 48=17
Estado atual do sistema
Compatível (sem alteração necessária)
| Local | Por quê |
|---|---|
escolas.cnpj (TEXT, nullable) | Campo TEXT, constraint valida apenas length = 14 |
usuarios.codigo (TEXT) + tipo_codigo = 'cnpj' | Campo TEXT, sem restrição de conteúdo |
UNIQUE e INDEX sobre cnpj | Funcionam com texto alfanumérico |
Lookups no banco (escolas.cnpj = valor) | Normalização preserva letras |
Exibição read-only (inscricoes.tsx, pagamentos-escola.tsx, etc.) | Exibem valor armazenado |
Alterações implementadas
Frontend — Helpers (src/lib/masks.ts)
| Função | Alteração |
|---|---|
unmaskCNPJ() | Nova — remove apenas .-/, preserva letras |
maskCNPJ() | Aceita alfanumérico ([^a-zA-Z0-9] em vez de \D) |
isValidCNPJFormat() | Usa unmaskCNPJ em vez de unmask |
isValidCNPJ() | Algoritmo unificado charCodeAt - 48 |
unmask() | Sem alteração — continua apenas para CPF/CEP/telefone/INEP |
Frontend — Auth (src/lib/auth.ts)
| Função | Alteração |
|---|---|
normalizarCodigo() | Condicional: se contém letras, preserva; senão, remove não-dígitos |
identificarTipoCodigo() | Detecta CNPJ alfanumérico (14 chars com letras) |
formatarCNPJ() | Usa slice posicional em vez de regex numérico |
Frontend — PDF (src/lib/pdf-helpers.ts)
| Local | Alteração |
|---|---|
| L48, L151 | Substituiu regex inline por formatarCNPJ() importado |
Frontend — Componentes
| Arquivo | Alteração |
|---|---|
login-unified.tsx | aplicarMascaraCodigo detecta letras → maskCNPJ alfanumérico |
CadastroTrialPage.tsx | unmask(cnpj) → unmaskCNPJ(cnpj) |
CadastroFormulario.tsx | unmask(cnpj) → unmaskCNPJ(cnpj) |
admin-escolas.tsx | unmask(formData.cnpj) → unmaskCNPJ(formData.cnpj) |
Backend — Shared
| Arquivo | Descrição |
|---|---|
_shared/cnpj-validator.ts | Novo — normalizarCNPJ, isValidCNPJ, normalizarCodigo, identificarTipoCodigo |
Backend — Edge Functions
| Arquivo | Alteração |
|---|---|
send-otp/index.ts | Normalização condicional + mensagem "14 caracteres" |
verify-otp/index.ts | Normalização condicional |
cadastro-escola-publica/index.ts | replace(/\D/g, "") → replace(/[.\-\/]/g, "").toUpperCase() (2 locais) |
Testes unitários
Arquivo: src/lib/__tests__/cnpj-alfanumerico.test.ts
unmaskCNPJpreserva letrasmaskCNPJformata alfanumérico corretamenteisValidCNPJvalida CNPJ numérico existente (regressão)isValidCNPJrejeita DVs incorretos em alfanuméricoidentificarTipoCodigodetecta CNPJ alfanumériconormalizarCodigopreserva letras quando presentesformatarCNPJformata alfanumérico
Compatibilidade retroativa
✅ Total — CNPJs numéricos existentes continuam funcionando sem alteração. O algoritmo charCodeAt - 48 produz resultados idênticos ao parseInt para caracteres 0-9.
Referências
- SERPRO — Cálculo DV CNPJ Alfanumérico
- Documento técnico:
calculodvcnpjalfanaumerico.pdf - Auditoria e implementação: 2026-03-12