# PROC001 - Núcleo de validação e formatação de CNPJ

<table border="1" id="bkmrk-%C2%A0-projeto%2Fsistema%3Age" style="border-collapse: collapse; width: 100.123%; height: 68px;"><tbody><tr style="border-style: solid;"><td rowspan="3" style="width: 26.6667%; height: 68px; border-color: black; border-top-style: hidden; border-left-style: hidden; border-bottom-style: hidden;">  
[![image-1762776253666.png](https://docs.softensistemas.com.br/uploads/images/gallery/2025-11/scaled-1680-/image-1762776253666.png)](https://docs.softensistemas.com.br/uploads/images/gallery/2025-11/image-1762776253666.png)

</td><td style="width: 49.9999%; height: 10px; border-color: black; border-style: solid;"><span style="color: #000000;">**Projeto/Sistema:**</span>  
<span style="color: #000000;">GERENCIEAQUI - MIGRAÇÃO CNPJ ALFANUMERICO (NT 2026.004)</span></td><td class="align-center" style="width: 23.3333%; height: 10px; border-color: black; border-style: solid;"><span style="color: #000000;">**Versão do *Template:***</span>  
<span style="color: #000000;">1.2</span></td></tr><tr style="border-style: solid;"><td style="width: 49.9999%; height: 29px; border-color: black; border-style: solid;"><span style="color: #000000;">**Processo:**</span>  
<span style="color: #000000;">PROC001 - Núcleo de validação e formatação de CNPJ</span></td><td class="align-center" style="width: 23.3333%; height: 29px; border-color: black; border-style: solid;"><span style="color: #000000;">**Versão do Documento:**</span>  
<span style="color: #000000;">1.0</span></td></tr><tr style="border-style: solid;"><td style="width: 49.9999%; height: 29px; border-color: black; border-style: solid;"><span style="color: #000000;">**Responsável(eis):** </span>  
<span style="color: #000000;">Luís Leite</span></td><td class="align-center" style="width: 23.3333%; height: 29px; border-color: black; border-style: solid;"><span style="color: #000000;">**Data:** </span>

<span style="color: #000000;">05/01/2026</span>

</td></tr></tbody></table>

##### <span style="color: #000000;">**1. Introdução**</span>

<span style="color: #000000;">Este processo descreve a adaptação dos utilitários centrais de CNPJ do projeto GerencieAqui (CnpjUtil moderno, CnpjUtil legado, CpfOrCnpjUtil, ValidaCNPJ e ModValidador) para suportar o CNPJ Alfanumérico previsto pela NT 2026.004 (Instrução Normativa RFB nº 2.229/2024), com entrada em produção em 01/07/2026.</span>  
<span style="color: #000000;">O CNPJ Alfanumérico mantém 14 caracteres, sendo as 12 primeiras posições alfanuméricas (letras maiúsculas A–Z e dígitos 0–9) e os 2 últimos dígitos verificadores numéricos. A máscara de exibição XX.XXX.XXX/XXXX-XX permanece inalterada. O cálculo dos DV usa o valor de cada caractere por ASCII menos 48 (módulo 11), o que já é implementado pelo ModValidador atual.</span>  
<span style="color: #000000;">Esta especificação é a FUNDAÇÃO de toda a migração — todas as demais frentes (NF-e, NFC-e, CT-e, MDF-e, NFS-e, DCE, integrações, banco e front-end) reutilizam estes utilitários. A correção do núcleo deve ser a primeira entrega da iniciativa.</span>

##### <span style="color: #000000;">**2. Processo**</span>

<span style="color: #000000;">O núcleo de CNPJ é exercido em três fluxos: (1) validação, quando o sistema verifica se uma string informada é um CNPJ válido (componentes JSF, APIs REST, parsers); (2) limpeza/normalização, quando o sistema recebe o CNPJ com máscara e precisa armazená-lo apenas com os 14 caracteres úteis; (3) formatação, quando o sistema precisa exibir o CNPJ ao usuário ou em relatórios/XML/arquivos bancários.</span>  
<span style="color: #000000;">Todas estas três operações precisam ser revistas: as regex \\d{14} rejeitam letras, as limpezas via replaceAll("\\D","") apagam letras silenciosamente, e a formatação por replaceFirst com grupos \\d falha quando há letras. A correção concentrada no núcleo resolve, em cascata, dezenas de pontos espalhados pelo sistema.</span>

<table cellpadding="9" cellspacing="0" id="bkmrk-processo-envolvidos-" width="100%"><tbody><tr valign="top"><td bgcolor="#acb9ca" style="border-style: solid; border-color: black;" width="27%"><span style="font-size: small; color: #000000;">**Processo**</span>

</td><td bgcolor="#acb9ca" style="border-style: solid; border-color: black;" width="19%"><span style="font-size: small; color: #000000;">**Envolvidos**</span>

</td><td bgcolor="#acb9ca" style="border-style: solid; border-color: black;" width="27%"><span style="font-size: small; color: #000000;">**Dados de Entrada**</span>

</td><td bgcolor="#acb9ca" style="border-style: solid; border-color: black;" width="27%"><span style="font-size: small; color: #000000;">**Dados de Saída**</span>

</td></tr><tr valign="top"><td style="border-style: solid; border-color: black;" width="27%"><span style="font-size: small; color: #000000;">Processo</span>

</td><td style="border-style: solid; border-color: black;" width="19%"><span style="font-size: small; color: #000000;">N/A</span>

</td><td style="border-style: solid; border-color: black;" width="27%"><span style="font-size: small; color: #000000;">N/A</span>

</td><td style="border-style: solid; border-color: black;" width="27%"><span style="font-size: small; color: #000000;">N/A</span>

</td></tr></tbody></table>

#### **Processos Relacionados** 

- - - - - -

- <span style="font-family: Arial, serif;"><span style="font-size: small;">PROC002 — Adaptação de Cadastros</span></span>

#### **Especificação Funcional**

- - - - - -

#### **<span style="color: #000000;">PROC001 - Núcleo de validação e formatação de CNPJ</span>:**

##### ***Descrição dos Campos:***

<table border="1" cellpadding="7" cellspacing="0" id="bkmrk-campo-tipo-tamanho-o" style="width: 843px;"><tbody><tr valign="top"><td bgcolor="#acb9ca" style="width: 168px; border-style: solid; border-color: black;"><span style="color: #000000;">**Campo**</span>

</td><td bgcolor="#acb9ca" style="width: 102px; border-style: solid; border-color: black;"><span style="color: #000000;">**Tipo**</span>

</td><td bgcolor="#acb9ca" style="width: 88px; border-style: solid; border-color: black;"><span style="color: #000000;">**Tamanho**</span>

</td><td bgcolor="#acb9ca" style="width: 165px; border-style: solid; border-color: black;"><span style="color: #000000;">**Obrig. ?**</span>

</td><td bgcolor="#acb9ca" style="width: 119px; border-style: solid; border-color: black;"><span style="color: #000000;">**Máscara**</span>

</td><td bgcolor="#acb9ca" style="width: 201px; border-style: solid; border-color: black;"><span style="color: #000000;">**Observações**</span>

</td></tr><tr><td style="width: 168px; border-style: solid; border-color: black;" width="135"><span style="color: #000000;"><span style="font-family: Arial, serif;"><span style="font-size: small;">CNPJ (entrada)</span></span></span>

</td><td style="width: 102px; border-style: solid; border-color: black;" width="78"><span style="color: #000000;"><span style="font-family: Arial, serif;"><span style="font-size: small;">Texto</span></span></span>

</td><td style="width: 88px; border-style: solid; border-color: black;" width="65"><span style="color: #000000;"><span style="font-family: Arial, serif;"><span style="font-size: small;">14 ou 18</span></span></span>

</td><td style="width: 165px; border-style: solid; border-color: black;" width="78"><span style="color: #000000;"><span style="font-family: Arial, serif;"><span style="font-size: small;">-</span></span></span>

</td><td style="width: 119px; border-style: solid; border-color: black;" width="117"><span style="color: #000000;"><span style="font-family: Arial, serif;"><span style="font-size: small;">99.999.999/9999-99 (legado) ou \*9.\*\*\*.\*\*\*/\*\*\*\*-99 (alfanumérico)</span></span></span>

</td><td style="width: 201px; border-style: solid; border-color: black;" width="193"><span style="color: #000000;"><span style="font-family: Arial, serif;"><span style="font-size: small;">As 12 primeiras posições alfanuméricas A–Z e 0–9; as 2 últimas posições numéricas (DV).</span></span></span>

</td></tr><tr><td style="width: 168px; border-style: solid; border-color: black;" width="135"><span style="color: #000000;"><span style="font-family: Arial, serif;"><span style="font-size: small;">CNPJ (armazenado)</span></span></span>

</td><td style="width: 102px; border-style: solid; border-color: black;" width="78"><span style="color: #000000;"><span style="font-family: Arial, serif;"><span style="font-size: small;">Texto</span></span></span>

</td><td style="width: 88px; border-style: solid; border-color: black;" width="65"><span style="color: #000000;"><span style="font-family: Arial, serif;"><span style="font-size: small;">14</span></span></span>

</td><td style="width: 165px; border-style: solid; border-color: black;" width="78"><span style="color: #000000;"><span style="font-family: Arial, serif;"><span style="font-size: small;">Sim</span></span></span>

</td><td style="width: 119px; border-style: solid; border-color: black;" width="117"><span style="color: #000000;"><span style="font-family: Arial, serif;"><span style="font-size: small;">-</span></span></span>

</td><td style="width: 201px; border-style: solid; border-color: black;" width="193"><span style="color: #000000;"><span style="font-family: Arial, serif;"><span style="font-size: small;">Sempre em maiúsculas, sem pontuação. Coluna varchar(14) a varchar(20) já existente.</span></span></span>

</td></tr><tr><td style="width: 168px; border-style: solid; border-color: black;" width="135"><span style="color: #000000;"><span style="font-family: Arial, serif;"><span style="font-size: small;">CNPJ (exibido)</span></span></span>

</td><td style="width: 102px; border-style: solid; border-color: black;" width="78"><span style="color: #000000;"><span style="font-family: Arial, serif;"><span style="font-size: small;">Texto</span></span></span>

</td><td style="width: 88px; border-style: solid; border-color: black;" width="65"><span style="color: #000000;"><span style="font-family: Arial, serif;"><span style="font-size: small;">18</span></span></span>

</td><td style="width: 165px; border-style: solid; border-color: black;" width="78"><span style="color: #000000;"><span style="font-family: Arial, serif;"><span style="font-size: small;">N/A</span></span></span>

</td><td style="width: 119px; border-style: solid; border-color: black;" width="117"><span style="color: #000000;"><span style="font-family: Arial, serif;"><span style="font-size: small;">XX.XXX.XXX/XXXX-XX</span></span></span>

</td><td style="width: 201px; border-style: solid; border-color: black;" width="193"><span style="color: #000000;"><span style="font-family: Arial, serif;"><span style="font-size: small;">-</span></span></span>

</td></tr><tr><td style="width: 168px; border-style: solid; border-color: black;" width="135"><span style="color: #000000;"><span style="font-family: Arial, serif;"><span style="font-size: small;">Dígitos Verificadores</span></span></span>

</td><td style="width: 102px; border-style: solid; border-color: black;" width="78"><span style="color: #000000;"><span style="font-family: Arial, serif;"><span style="font-size: small;">Numérico</span></span></span>

</td><td style="width: 88px; border-style: solid; border-color: black;" width="65"><span style="color: #000000;"><span style="font-family: Arial, serif;"><span style="font-size: small;">2</span></span></span>

</td><td style="width: 165px; border-style: solid; border-color: black;" width="78"><span style="color: #000000;"><span style="font-family: Arial, serif;"><span style="font-size: small;">Sim</span></span></span>

</td><td style="width: 119px; border-style: solid; border-color: black;" width="117"><span style="color: #000000;"><span style="font-family: Arial, serif;"><span style="font-size: small;">99</span></span></span>

</td><td style="width: 201px; border-style: solid; border-color: black;" width="193"><span style="color: #000000;"><span style="font-family: Arial, serif;"><span style="font-size: small;">Calculado por módulo 11 com pesos 5,4,3,2,9,8,7,6,5,4,3,2 sobre (char-48).</span></span></span>

</td></tr></tbody></table>

##### ***Regras de Negócio:***

**1. Algoritmo de validação dos DV (mantido):** O cálculo permanece módulo 11 sobre os 12 primeiros caracteres, utilizando o valor (char-48) de cada posição: '0'→0 … '9'→9, 'A'→17 … 'Z'→42. ModValidador.java já realiza esta operação corretamente (linhas 179, 192).  
**2. Limpeza preservando letras**: CnpjUtil.clean (linha 35) deve substituir replaceAll("\\D", "") por replaceAll("\[^A-Za-z0-9\]", "") e em seguida toUpperCase(). Isto preserva as letras do CNPJ alfanumérico e elimina a corrupção silenciosa do dado.  
**3. Padrão de validação simples:** CnpjUtil.isValidSimple (linha 31) deve trocar matches("\\d{14}") por matches("\[A-Z0-9\]{12}\[0-9\]{2}") sobre o valor limpo, e contemplar variação com máscara: matches("\[A-Z0-9\]{2}\\.\[A-Z0-9\]{3}\\.\[A-Z0-9\]{3}/\[A-Z0-9\]{4}-\[0-9\]{2}").  
**4. Formatação agnóstica:** CnpjUtil.format (linhas 38–47) deve usar replaceFirst("(.{2})(.{3})(.{3})(.{4})(.{2})", "$1.$2.$3/$4-$5") em vez de grupos \\d, suportando qualquer caractere.  
**5. Consolidação do util legado @Deprecated:** O CnpjUtil legado em util/CnpjUtil.java (com isCNPJValido / isCNPJ / imprimeCNPJ via charAt-48 e substring) é tecnicamente compatível com alfanumérico mas mantém duplicidade. Consolidar no util moderno e marcar para remoção em release subsequente.  
**6. Caracteres repetidos:** A verificação matches("^(\\d)\\1\*$") em CnpjUtil.java (linha 16) já não casa com alfanumérico — sem quebra. Avaliar estender para detectar também sequências repetidas de letras (ex.: AAAAAAAAAAAA00).  
**7. Desambiguação CPF × CNPJ em CpfOrCnpjUtil:** A distinção continua por comprimento (11 vs 14) sobre o valor limpo. Toda lógica que dependa de "ser numérico" para classificar precisa ser revista — um valor de 14 caracteres com letras é necessariamente CNPJ.

©SOFTEN SISTEMAS 2026