| Bellacosa Mainframe e o cnpj alfanumerico sem misterios |
☕ Um Café no Bellacosa Mainframe
CNPJ Alfanumérico sem Mistérios
Quando o Programador COBOL Descobre que o Campo Continua com 14 Posições, mas o Mundo Inteiro ao Redor Dele Precisa Mudar
Durante décadas, o programador COBOL brasileiro olhou para o CNPJ como quem observa uma estrutura absolutamente estável:
99.999.999/9999-99
Quatorze algarismos. Sempre numérico. Frequentemente armazenado em um campo PIC 9(14), talvez compactado em COMP-3, validado por uma rotina de módulo 11 e utilizado como chave em arquivos VSAM, tabelas Db2, mapas BMS, mensagens MQ, arquivos fiscais e milhões de transações batch.
Parecia um daqueles contratos eternos do processamento corporativo.
Mas eis que surge uma nova especificação no horizonte:
AA.AAA.AAA/AAAA-99
O tamanho permanece com 14 posições, a máscara visual continua praticamente igual e os dois dígitos verificadores permanecem numéricos. Porém, as primeiras doze posições passam a aceitar números e letras maiúsculas de A a Z.
Para um usuário comum, isso pode parecer uma pequena mudança de formulário.
Para um programador COBOL, é uma alteração estrutural capaz de atravessar todo o ecossistema corporativo.
É aquele tipo de manutenção em que alguém diz:
“É só permitir letras no CNPJ.”
E três semanas depois existe uma War Room com quarenta pessoas, cinco fornecedores, dois bancos de dados, quatro sistemas satélites e um arquivo histórico criado em 1997 que ninguém sabia que ainda estava em produção.
Bem-vindo, Padawan, ao verdadeiro significado de mudança de domínio de dados.
1. O que é o CNPJ alfanumérico?
O CNPJ alfanumérico é o novo formato do identificador utilizado pelo Cadastro Nacional da Pessoa Jurídica.
A inscrição continuará possuindo 14 posições:
AA.AAA.AAA/AAAA-DV
Onde:
Posições 01 a 08: raiz da entidade
Posições 09 a 12: número de ordem do estabelecimento
Posições 13 e 14: dígitos verificadores numéricos
As primeiras doze posições poderão conter:
0 1 2 3 4 5 6 7 8 9
A B C D E F G H I J K L M
N O P Q R S T U V W X Y Z
Os dois últimos caracteres continuarão sendo algarismos calculados pelo método de módulo 11.
Exemplos possíveis:
12.345.678/0001-95
AA.345.678/0003-29
AA.345.678/000A-29
12.345.678/000A-08
65.9BR.JGJ/0001-03
O último exemplo é apresentado pelo próprio simulador nacional da Receita como um identificador fictício de teste. (Receita Federal)
Observe o detalhe importante: não existe uma posição reservada exclusivamente para letras. Qualquer uma das primeiras doze posições poderá ser alfanumérica.
Portanto, esta validação está errada:
NN.NNN.NNN/AAAA-NN
A definição correta é:
XX.XXX.XXX/XXXX-NN
Em que cada X aceita um algarismo ou uma letra maiúscula.
2. Por que o CNPJ precisou mudar?
A origem da mudança é bastante pragmática: o crescimento contínuo do número de inscrições estava aproximando o modelo exclusivamente numérico de seus limites de capacidade.
Ao introduzir letras nas doze posições principais, a quantidade de combinações possíveis cresce de forma gigantesca.
No formato puramente numérico, do ponto de vista matemático bruto, doze posições oferecem:
10¹² combinações
Com 36 símbolos possíveis por posição — dez algarismos e 26 letras — o espaço teórico passa a ser:
36¹² combinações
Isso corresponde a aproximadamente:
4.738.381.338.321.616.896
Ou cerca de 4,7 quintilhões de combinações teóricas.
Naturalmente, nem todas serão necessariamente usadas: existem regras de geração, reservas técnicas, controle de duplicidade, combinações que podem ser bloqueadas e outras restrições administrativas. Ainda assim, a expansão é monumental.
Segundo a Receita Federal, o objetivo é evitar o esgotamento dos números disponíveis, garantir a continuidade do cadastro e preservar a identificação única das entidades. (Serviços e Informações do Brasil)
É uma solução bastante conhecida na engenharia de sistemas.
Quando o espaço de chaves está ficando pequeno, temos três caminhos principais:
aumentar o tamanho do campo;
mudar a representação;
criar um novo identificador paralelo.
A Receita escolheu ampliar o alfabeto sem aumentar o comprimento.
Essa decisão reduz impactos visuais e documentais, pois o CNPJ continua tendo 14 posições. Entretanto, ela transfere grande parte da complexidade para os sistemas que assumiram, durante décadas, que CNPJ era um número.
3. Quando começa a implantação?
A regulamentação foi estabelecida pela Instrução Normativa RFB nº 2.229, publicada em outubro de 2024, alterando a disciplina cadastral anterior. O projeto oficial estabeleceu julho de 2026 como período de implantação. (Serviços e Informações do Brasil)
Em atualização divulgada pela Receita Federal em julho de 2026, o início operacional foi detalhado para ocorrer a partir de 31 de julho de 2026, com emissão progressiva dos primeiros identificadores no novo formato. (Serviços e Informações do Brasil)
Isso é importante porque documentos antigos podem mencionar genericamente “julho de 2026” ou até “1º de julho”. O planejamento mais recente divulgado pela Receita aponta o final do mês como início efetivo da geração.
Os CNPJs já existentes não serão convertidos, substituídos ou cancelados. Eles continuarão válidos exatamente como estão. O novo formato será utilizado progressivamente em novas inscrições. (Serviços e Informações do Brasil)
Isso cria um mundo de coexistência:
CNPJ antigo: 12.345.678/0001-95
CNPJ novo: AB.3C5.678/00D1-42
Ambos deverão ser aceitos.
Portanto, não existe “migração de todos os CNPJs”. Existe uma migração dos sistemas para aceitar os dois formatos.
Essa diferença parece pequena, mas muda completamente a estratégia de implantação.
4. A grande armadilha: CNPJ nunca deveria ter sido tratado como número
Este é o momento em que o Mestre Bellacosa coloca a caneca sobre a mesa e pergunta ao Padawan:
CNPJ é realmente um número?
Matematicamente, não.
CNPJ é um identificador.
Ele não representa uma quantidade. Você não soma dois CNPJs, não calcula média de CNPJ e não divide um CNPJ por outro.
O fato de ele ter sido historicamente composto apenas por algarismos levou milhares de sistemas a armazená-lo como dado numérico.
Exemplo clássico:
01 WS-CNPJ.
05 WS-CNPJ-BASE PIC 9(12).
05 WS-CNPJ-DV PIC 9(02).
Ou pior:
01 WS-CNPJ PIC 9(14) COMP-3.
O segundo formato economiza espaço, mas impede completamente o armazenamento de letras.
O novo modelo deixa explícito algo que a modelagem já deveria ter reconhecido:
CNPJ é texto estruturado.
A definição mais adequada passa a ser:
01 WS-CNPJ.
05 WS-CNPJ-BASE PIC X(12).
05 WS-CNPJ-DV PIC 9(02).
Ou, para facilitar movimentações:
01 WS-CNPJ-NORMALIZADO PIC X(14).
O termo “normalizado” significa armazenar sem pontuação:
AB3C567800D142
Enquanto a representação formatada seria:
AB.3C5.678/00D1-42
Uma boa arquitetura separa essas duas coisas:
valor canônico: AB3C567800D142
apresentação: AB.3C5.678/00D1-42
Não armazene pontos, barra e hífen na chave principal, salvo quando houver uma justificativa muito específica. Formatação pertence à camada de apresentação.
5. O impacto real em sistemas COBOL
Trocar PIC 9(14) por PIC X(14) é apenas o primeiro passo.
O impacto poderá alcançar:
copybooks;
arquivos sequenciais;
VSAM;
tabelas Db2;
mapas BMS;
telas IMS;
programas online;
jobs batch;
sort cards;
interfaces MQ;
APIs;
JSON e XML;
arquivos SPED;
relatórios;
chaves de indexação;
critérios de pesquisa;
rotinas de mascaramento;
validações de entrada;
programas Java, Natural, PL/I e Assembler integrados;
ferramentas de prevenção a fraude;
trilhas de auditoria;
data warehouses;
data lakes;
planilhas e sistemas departamentais.
Vamos analisar alguns exemplos.
5.1 Copybook antigo
05 CLIENTE-CNPJ PIC 9(14).
Nova definição:
05 CLIENTE-CNPJ PIC X(14).
Parece simples, mas todos os programas que incluem esse copybook precisam ser analisados.
Este comando pode deixar de compilar ou mudar de comportamento:
IF CLIENTE-CNPJ IS NUMERIC
Esta movimentação pode gerar problema:
COMPUTE WS-CHAVE = CLIENTE-CNPJ + 100
Esta classificação pode mudar:
SORT FIELDS=(1,14,ZD,A)
A definição ZD, de zoned decimal, não aceita letras. Será necessário tratar o campo como caractere:
SORT FIELDS=(1,14,CH,A)
Todavia, há uma nova questão: qual será a ordem esperada? Ordem binária EBCDIC? Ordem lógica da aplicação? Ordem usada por um sistema distribuído em ASCII?
6. O Easter egg que todo programador de mainframe precisa conhecer: ASCII não é EBCDIC
O algoritmo oficial do dígito verificador converte cada caractere utilizando seu valor na tabela ASCII, subtraindo 48.
Assim:
'0' ASCII 48 → 48 - 48 = 0
'1' ASCII 49 → 49 - 48 = 1
...
'9' ASCII 57 → 57 - 48 = 9
'A' ASCII 65 → 65 - 48 = 17
'B' ASCII 66 → 66 - 48 = 18
...
'Z' ASCII 90 → 90 - 48 = 42
Observe que A não vale 10. Ela vale 17.
Essa diferença existe porque o cálculo preserva a relação com os códigos ASCII.
Agora vem o perigo: z/OS tradicionalmente utiliza EBCDIC.
No EBCDIC, os valores dos caracteres são diferentes. Além disso, as letras não ocupam necessariamente uma sequência contínua equivalente à encontrada em ASCII.
Portanto, uma implementação como esta é conceitualmente perigosa no mainframe:
COMPUTE WS-VALOR =
FUNCTION ORD(WS-CARACTERE) - 48
Ela pode funcionar em determinada plataforma, compilador ou codificação e falhar em outra.
O algoritmo precisa usar o valor lógico definido pela especificação, e não o código físico local do caractere.
A abordagem segura é mapear explicitamente:
0 → 0
1 → 1
...
9 → 9
A → 17
B → 18
...
Z → 42
Aqui está um maravilhoso Easter egg da modernização brasileira:
Um identificador nacional criado no século XXI obriga o programador COBOL a revisitar uma das guerras de codificação mais antigas da computação: ASCII versus EBCDIC.
No Mainframe, o detalhe nunca desaparece. Ele apenas espera pacientemente dentro de um byte.
7. Como calcular o dígito verificador
O cálculo continua utilizando módulo 11, mas agora cada caractere precisa ser convertido para seu valor numérico lógico.
Para o primeiro dígito verificador, aplicam-se os seguintes pesos às doze primeiras posições:
Posição: 01 02 03 04 05 06 07 08 09 10 11 12
Peso: 5 4 3 2 9 8 7 6 5 4 3 2
Cada valor é multiplicado pelo peso correspondente.
Depois:
RESTO = SOMA MOD 11
A regra do dígito é:
Se RESTO for 0 ou 1:
DV = 0
Senão:
DV = 11 - RESTO
Para o segundo dígito, o primeiro DV é anexado ao final e aplicam-se os pesos:
Posição: 01 02 03 04 05 06 07 08 09 10 11 12 DV1
Peso: 6 5 4 3 2 9 8 7 6 5 4 3 2
O mesmo cálculo de módulo 11 é repetido. A Receita mantém documentação técnica e arquivos de referência específicos para esse algoritmo. (Serviços e Informações do Brasil)
8. Estrutura COBOL recomendada
Uma estrutura didática poderia ser:
01 WS-CNPJ.
05 WS-CNPJ-CORPO PIC X(12).
05 WS-CNPJ-DV.
10 WS-CNPJ-DV1 PIC 9.
10 WS-CNPJ-DV2 PIC 9.
01 WS-CONTROLE.
05 WS-I PIC 99 COMP.
05 WS-VALOR PIC 99 COMP.
05 WS-SOMA PIC 9(06) COMP.
05 WS-RESTO PIC 99 COMP.
05 WS-CARACTERE PIC X.
01 WS-PESOS-DV1.
05 FILLER PIC X(12)
VALUE X'050403020908070605040302'.
01 WS-PESOS-DV1-R REDEFINES WS-PESOS-DV1.
05 WS-PESO1 PIC X OCCURS 12 TIMES.
01 WS-PESOS-DV2.
05 FILLER PIC X(13)
VALUE X'06050403020908070605040302'.
01 WS-PESOS-DV2-R REDEFINES WS-PESOS-DV2.
05 WS-PESO2 PIC X OCCURS 13 TIMES.
Em uma implementação corporativa, talvez seja mais legível declarar os pesos como campos numéricos individuais ou carregá-los em uma tabela durante a inicialização.
Por exemplo:
01 WS-TAB-PESO1.
05 WS-PESO1 OCCURS 12 TIMES PIC 9 COMP.
E inicializar:
MOVE 5 TO WS-PESO1(1)
MOVE 4 TO WS-PESO1(2)
MOVE 3 TO WS-PESO1(3)
MOVE 2 TO WS-PESO1(4)
MOVE 9 TO WS-PESO1(5)
MOVE 8 TO WS-PESO1(6)
MOVE 7 TO WS-PESO1(7)
MOVE 6 TO WS-PESO1(8)
MOVE 5 TO WS-PESO1(9)
MOVE 4 TO WS-PESO1(10)
MOVE 3 TO WS-PESO1(11)
MOVE 2 TO WS-PESO1(12)
É mais extenso, porém muito fácil de auditar.
No mundo fiscal, clareza costuma valer mais do que cinco linhas economizadas.
9. Conversão segura do caractere
Uma rotina simples pode utilizar EVALUATE:
CONVERTER-CARACTERE.
EVALUATE WS-CARACTERE
WHEN '0' MOVE 0 TO WS-VALOR
WHEN '1' MOVE 1 TO WS-VALOR
WHEN '2' MOVE 2 TO WS-VALOR
WHEN '3' MOVE 3 TO WS-VALOR
WHEN '4' MOVE 4 TO WS-VALOR
WHEN '5' MOVE 5 TO WS-VALOR
WHEN '6' MOVE 6 TO WS-VALOR
WHEN '7' MOVE 7 TO WS-VALOR
WHEN '8' MOVE 8 TO WS-VALOR
WHEN '9' MOVE 9 TO WS-VALOR
WHEN 'A' MOVE 17 TO WS-VALOR
WHEN 'B' MOVE 18 TO WS-VALOR
WHEN 'C' MOVE 19 TO WS-VALOR
WHEN 'D' MOVE 20 TO WS-VALOR
WHEN 'E' MOVE 21 TO WS-VALOR
WHEN 'F' MOVE 22 TO WS-VALOR
WHEN 'G' MOVE 23 TO WS-VALOR
WHEN 'H' MOVE 24 TO WS-VALOR
WHEN 'I' MOVE 25 TO WS-VALOR
WHEN 'J' MOVE 26 TO WS-VALOR
WHEN 'K' MOVE 27 TO WS-VALOR
WHEN 'L' MOVE 28 TO WS-VALOR
WHEN 'M' MOVE 29 TO WS-VALOR
WHEN 'N' MOVE 30 TO WS-VALOR
WHEN 'O' MOVE 31 TO WS-VALOR
WHEN 'P' MOVE 32 TO WS-VALOR
WHEN 'Q' MOVE 33 TO WS-VALOR
WHEN 'R' MOVE 34 TO WS-VALOR
WHEN 'S' MOVE 35 TO WS-VALOR
WHEN 'T' MOVE 36 TO WS-VALOR
WHEN 'U' MOVE 37 TO WS-VALOR
WHEN 'V' MOVE 38 TO WS-VALOR
WHEN 'W' MOVE 39 TO WS-VALOR
WHEN 'X' MOVE 40 TO WS-VALOR
WHEN 'Y' MOVE 41 TO WS-VALOR
WHEN 'Z' MOVE 42 TO WS-VALOR
WHEN OTHER
MOVE 99 TO WS-VALOR
END-EVALUATE.
Sim, são muitas linhas.
Porém, esta rotina é:
explícita;
independente de ASCII ou EBCDIC;
portável;
auditável;
fácil de testar;
fiel à especificação.
Em ambientes modernos, também seria possível usar uma tabela indexada. Ainda assim, documente claramente por que A = 17.
Sem essa documentação, algum programador bem-intencionado poderá “corrigir” a rotina no futuro, fazendo A = 10, e produzir um belo incidente fiscal.
10. Cálculo COBOL simplificado do primeiro DV
CALCULAR-DV1.
MOVE ZERO TO WS-SOMA
PERFORM VARYING WS-I FROM 1 BY 1
UNTIL WS-I > 12
MOVE WS-CNPJ-CORPO(WS-I:1)
TO WS-CARACTERE
PERFORM CONVERTER-CARACTERE
IF WS-VALOR = 99
MOVE 'S' TO WS-ERRO-CNPJ
EXIT PARAGRAPH
END-IF
COMPUTE WS-SOMA =
WS-SOMA +
(WS-VALOR * WS-PESO1(WS-I))
END-PERFORM
COMPUTE WS-RESTO =
FUNCTION MOD(WS-SOMA, 11)
IF WS-RESTO < 2
MOVE ZERO TO WS-CNPJ-DV1
ELSE
COMPUTE WS-CNPJ-DV1 = 11 - WS-RESTO
END-IF.
Para o segundo DV, processe novamente as doze posições e depois multiplique o primeiro dígito pelo peso final 2.
CALCULAR-DV2.
MOVE ZERO TO WS-SOMA
PERFORM VARYING WS-I FROM 1 BY 1
UNTIL WS-I > 12
MOVE WS-CNPJ-CORPO(WS-I:1)
TO WS-CARACTERE
PERFORM CONVERTER-CARACTERE
COMPUTE WS-SOMA =
WS-SOMA +
(WS-VALOR * WS-PESO2(WS-I))
END-PERFORM
COMPUTE WS-SOMA =
WS-SOMA + (WS-CNPJ-DV1 * 2)
COMPUTE WS-RESTO =
FUNCTION MOD(WS-SOMA, 11)
IF WS-RESTO < 2
MOVE ZERO TO WS-CNPJ-DV2
ELSE
COMPUTE WS-CNPJ-DV2 = 11 - WS-RESTO
END-IF.
Em produção, acrescente tratamento formal de erro, mensagens padronizadas, logging, retorno de condição e testes automatizados.
11. Normalização da entrada
O usuário poderá informar:
AB.123.CD4/0001-55
Ou:
AB123CD4000155
A aplicação deve decidir qual contrato aceita.
Uma boa rotina de normalização pode:
remover
.,/e-;eliminar espaços laterais;
converter letras minúsculas em maiúsculas;
verificar se restaram exatamente 14 caracteres;
validar as primeiras doze posições;
confirmar que as duas últimas são numéricas;
calcular e comparar os dígitos verificadores.
Não aceite silenciosamente qualquer caractere.
Os permitidos nas primeiras posições são apenas:
0-9
A-Z
Portanto, estes devem ser rejeitados:
Á
Ç
@
#
espaço
underscore
letra minúscula sem normalização
A Receita orienta que os sistemas considerem todas as letras de A a Z. O controle de combinações eventualmente proibidas, como formações ofensivas ou confusas, será realizado internamente pela própria Receita; as empresas não precisam reproduzir essa lista.
12. Não use IS NUMERIC para validar o CNPJ inteiro
Antes:
IF WS-CNPJ IS NUMERIC
CONTINUE
ELSE
MOVE 'CNPJ INVALIDO' TO WS-MENSAGEM
END-IF
Depois da mudança, isso rejeitará corretamente todos os novos CNPJs — o que significa que estará funcionalmente errado.
A validação precisa ser segmentada:
Posições 1 a 12:
letras A-Z ou números 0-9
Posições 13 e 14:
somente números
Conjunto completo:
dígito verificador válido
Uma verificação de formato nunca substitui a validação do DV.
Este identificador possui formato válido:
ABCDEFGHIJKL00
Mas não significa que seus dígitos verificadores sejam corretos ou que exista uma entidade registrada com ele.
São três conceitos diferentes:
formato válido
dígito verificador válido
cadastro existente
Um programa maduro não mistura essas responsabilidades.
13. Db2: o problema escondido nas colunas DECIMAL
Imagine esta tabela:
CREATE TABLE CLIENTE
(
CNPJ DECIMAL(14,0) NOT NULL,
NOME VARCHAR(100)
);
Ela não poderá armazenar o novo formato.
A coluna precisará tornar-se:
CNPJ CHAR(14)
ou:
CNPJ VARCHAR(14)
Para identificadores de tamanho fixo, CHAR(14) costuma ser uma escolha natural.
Entretanto, alterar uma coluna primária pode envolver:
índices;
chaves estrangeiras;
views;
triggers;
packages Db2;
programas com SQL estático;
DCLGENs;
rotinas ETL;
replicação;
unloads;
data warehouses;
APIs;
relatórios;
programas que usam host variable numérica.
Uma host variable antiga:
01 HV-CNPJ PIC S9(14) COMP-3.
precisará ser substituída por:
01 HV-CNPJ PIC X(14).
Depois será necessário regenerar o DCLGEN, recompilar, realizar precompile, bind e testes de regressão.
Não trate isso apenas como alteração de tela.
14. Arquivos VSAM e chaves
Considere um KSDS cujo CNPJ esteja na chave:
KEYS(14 0)
O comprimento continua igual. Isso parece ótimo.
Mas se o campo era interpretado como numérico em programas, sorts ou relatórios, o comportamento precisará ser revisto.
Outro cuidado é a ordenação.
Em EBCDIC, a sequência de comparação de caracteres é diferente da sequência ASCII. Um arquivo ordenado no mainframe pode produzir uma ordem diferente de um banco distribuído.
Para identificadores únicos, isso normalmente não invalida a chave. Contudo, pode afetar:
relatórios;
comparações de faixa;
cargas ordenadas;
reconciliações;
merge entre arquivos de plataformas diferentes;
processamento com
STARTeREAD NEXT.
Evite atribuir significado comercial à ordem lexical do CNPJ.
Um CNPJ “maior” não é mais novo, mais importante ou pertencente a determinada região.
15. Letras não representam estado, porte ou natureza jurídica
As letras serão atribuídas pelo sistema de geração e não carregarão inteligência sobre:
Unidade da Federação;
município;
porte;
atividade econômica;
natureza jurídica;
regime tributário;
data de abertura;
órgão de registro.
A Receita esclarece que não haverá conexão semântica entre as letras e atributos cadastrais.
Portanto, nunca escreva uma regra como:
IF WS-CNPJ(1:1) = 'S'
MOVE 'SAO PAULO' TO WS-UF
END-IF
O identificador é opaco.
Ele identifica a entidade, mas não deve ser “decodificado” para inferir informações.
Essa é uma prática moderna importante: identificadores não devem carregar regras de negócio ocultas, a menos que isso faça parte de uma especificação formal.
16. E o famoso sufixo 0001?
Historicamente, muitos sistemas assumiram:
0001 = matriz
qualquer outro valor = filial
A própria Receita informa que 0001 continuará inicialmente associado à matriz quando o número for gerado. Porém, essa não é uma associação permanente: uma filial poderá posteriormente tornar-se o estabelecimento principal, mesmo possuindo outro número de ordem.
Portanto, isto é uma regra frágil:
IF WS-CNPJ(9:4) = '0001'
MOVE 'MATRIZ' TO WS-TIPO
ELSE
MOVE 'FILIAL' TO WS-TIPO
END-IF
A informação de matriz ou filial deve vir de um atributo cadastral confiável, não de uma interpretação eterna do sufixo.
Além disso, o número de ordem poderá conter letras:
000A
00B7
A001
Quem armazenou a ordem da filial em PIC 9(4) também terá trabalho.
17. APIs, JSON e XML
Este JSON antigo já tratava corretamente o CNPJ:
{
"cnpj": "12345678000195"
}
Este, não:
{
"cnpj": 12345678000195
}
O identificador deve ser enviado como string.
Novo exemplo:
{
"cnpj": "AB3C567800D142"
}
Em OpenAPI:
cnpj:
type: string
minLength: 14
maxLength: 14
pattern: '^[A-Z0-9]{12}[0-9]{2}$'
A expressão regular valida apenas a estrutura. O cálculo do DV continuará necessário.
Para o COBOL usando JSON GENERATE, defina o campo como alfanumérico:
05 CNPJ PIC X(14).
Revise também os schemas XML. O ecossistema de documentos fiscais eletrônicos vem publicando notas técnicas e atualizações de XSD para suportar o novo formato, incluindo NF-e, NFC-e e EFD-Reinf. (Nota Fiscal Eletrônica)
18. Estratégia de implantação sem derrubar a produção
Não faça uma alteração Big Bang sem inventário.
Uma estratégia madura pode ser dividida em ondas.
Onda 1 — Descoberta
Procure por:
PIC 9(14)
PIC 9(12)
PIC 9(8)
PIC 9(4)
COMP-3
CNPJ
CGC
CGC-CPF
NUM-CNPJ
CNPJ-NUM
IS NUMERIC
NUMERIC-EDITED
Não pesquise apenas por CNPJ.
Sistemas antigos podem ainda usar o termo CGC, nome histórico anterior do cadastro.
Procure também:
DECIMAL(14,0)
NUMERIC(14)
BIGINT
CHAR(14)
O objetivo é construir um inventário de:
fontes;
copybooks;
tabelas;
arquivos;
interfaces;
relatórios;
rotinas de validação;
consumidores externos.
Onda 2 — Classificação
Classifique os componentes:
A – armazena CNPJ
B – recebe CNPJ
C – envia CNPJ
D – valida CNPJ
E – formata CNPJ
F – usa CNPJ como chave
G – apenas exibe CNPJ
Os itens que usam o identificador como chave ou campo numérico possuem prioridade maior.
Onda 3 — Modelo canônico
Defina um padrão corporativo:
CNPJ interno: X(14), sem máscara, maiúsculo
CNPJ apresentado: XX.XXX.XXX/XXXX-XX
DV: módulo 11 oficial
Codificação: contrato independente de ASCII/EBCDIC
Onda 4 — Compatibilidade dupla
Teste simultaneamente:
CNPJ exclusivamente numérico
CNPJ com uma letra
CNPJ com várias letras
CNPJ com letras na raiz
CNPJ com letras na ordem
CNPJ com zero à esquerda
CNPJ inválido
DV incorreto
letra minúscula
pontuação
espaços
caracteres especiais
Onda 5 — Implantação observável
Crie métricas:
quantidade de CNPJs alfanuméricos recebidos
rejeições por formato
rejeições por DV
erros de integração
truncamentos
conversões indevidas
mensagens enviadas para DLQ
falhas em arquivos fiscais
Modernização sem observabilidade é apenas uma nova forma de torcer para que tudo funcione.
19. Casos de teste essenciais
Uma suíte mínima deveria incluir:
Caso 1 — CNPJ numérico atual
Entrada: CNPJ numérico válido
Resultado: aceito
Caso 2 — Raiz alfanumérica
Entrada: letras entre as posições 1 e 8
Resultado: aceito se o DV estiver correto
Caso 3 — Ordem alfanumérica
Entrada: letras entre as posições 9 e 12
Resultado: aceito se o DV estiver correto
Caso 4 — Identificador totalmente numérico depois da mudança
Ainda poderá ocorrer, pois a geração progressiva poderá produzir combinações exclusivamente numéricas. Não crie uma regra que exija pelo menos uma letra.
Caso 5 — Minúsculas
ab12cd34000199
Defina o comportamento:
normalizar para maiúsculas
ou
rejeitar por contrato
A primeira opção costuma proporcionar melhor experiência, desde que seja documentada.
Caso 6 — Caractere inválido
AB12ÇD34000199
Deve ser rejeitado.
Caso 7 — DV alfabético
AB12CD340001A9
Deve ser rejeitado, pois as duas últimas posições são exclusivamente numéricas.
Caso 8 — Campo com pontuação
AB.12C.D34/0001-99
Valide após a normalização, caso a interface permita máscara.
Caso 9 — Valor vazio
Decida se o campo é obrigatório ou opcional. Não transforme espaços em zeros silenciosamente.
Caso 10 — Integração EBCDIC/ASCII
Envie o mesmo CNPJ entre:
COBOL/zOS
Java/Linux
API REST
MQ
arquivo UTF-8
arquivo EBCDIC
Confirme que o valor não sofreu tradução incorreta.
20. Use o simulador oficial
A Receita Federal disponibilizou um simulador capaz de gerar CNPJs fictícios, numéricos e alfanuméricos, inclusive combinações para matriz e filiais. A ferramenta pode gerar lotes para testes e exportação, auxiliando equipes de desenvolvimento na adaptação. (Receita Federal)
Essa é uma excelente oportunidade para criar:
massa de testes unitários;
arquivos de entrada;
cenários de integração;
registros Db2;
entradas de CICS;
mensagens MQ;
testes de API;
validação de relatórios.
Não invente apenas três exemplos manualmente.
Gere centenas de casos e execute-os automaticamente.
No pipeline:
Build
↓
Análise estática
↓
Teste unitário do DV
↓
Teste com CNPJ numérico
↓
Teste com CNPJ alfanumérico
↓
Teste de integração
↓
Teste de regressão
↓
Deploy controlado
O CNPJ alfanumérico é um excelente caso de uso para ZUnit, COBOL Check, Galasa, DBB, Jenkins e pipelines corporativos.
21. Dicas do Mestre Bellacosa
Nunca converta o CNPJ para número
Não faça:
MOVE FUNCTION NUMVAL(WS-CNPJ) TO WS-CNPJ-NUM
Além de falhar com letras, isso pode eliminar zeros à esquerda.
Não remova letras para “manter compatibilidade”
Esta aberração:
AB12CD34000199 → 1234000199
destrói o identificador e pode criar colisões.
Não use espaços para substituir letras
Um campo com letras não reconhecidas deve causar erro controlado, não limpeza silenciosa.
Centralize a validação
Crie uma rotina comum, serviço ou módulo compartilhado.
Exemplo:
CALL 'VALCNPJ2'
USING CNPJ-ENTRADA
CNPJ-NORMALIZADO
CODIGO-RETORNO
MENSAGEM-RETORNO
Assim, todos os sistemas seguem a mesma regra.
Versione o copybook
Não altere um copybook crítico sem avaliar seus consumidores.
Uma estratégia possível:
CPYCNPJ1 – formato legado
CPYCNPJ2 – formato alfanumérico
Depois, migre os programas progressivamente.
Não confunda máscara com conteúdo
A máscara possui 18 caracteres:
AA.AAA.AAA/AAAA-99
O conteúdo canônico possui 14:
AAAAAAAAAAAA99
Preserve os zeros à esquerda
Como o campo passa a ser textual, a preservação fica mais natural. Ainda assim, evite funções que façam conversão numérica intermediária.
Registre o valor recebido e o normalizado
Em sistemas críticos, pode ser útil registrar:
valor original
valor normalizado
resultado da validação
origem da transação
data e hora
Isso facilita auditoria e investigação.
22. Curiosidades importantes
O número continuará público
O novo formato não é código secreto, token de rastreamento ou identificação criptografada. A Receita afirma que não existe informação escondida na composição.
Não existe inteligência artificial escolhendo o CNPJ
Apesar da palavra “alfanumérico” parecer sofisticada, a Receita esclarece que a geração não utiliza IA para atribuir significado ao número.
A chave Pix poderá usar o novo formato
Empresas com CNPJ alfanumérico poderão utilizá-lo como chave Pix, enquanto as chaves dos CNPJs numéricos existentes continuam válidas.
CNPJs numéricos e alfanuméricos coexistirão por décadas
Como os registros antigos não serão modificados, é perfeitamente possível que sistemas ainda processem CNPJs exclusivamente numéricos muitas décadas depois da implantação.
Portanto, não crie duas lógicas separadas desnecessariamente:
validador antigo
validador novo
Crie uma lógica compatível com ambos.
O algoritmo alfanumérico, quando aplicado a algarismos, preserva o mapeamento de 0 a 9, permitindo tratar o formato numérico dentro da mesma arquitetura.
23. O verdadeiro problema não está no campo
O grande risco do CNPJ alfanumérico não é a largura.
Ela continua sendo 14.
O risco está nas suposições invisíveis acumuladas durante décadas:
CNPJ sempre é numérico.
CNPJ pode ser COMP-3.
Filial sempre é 9(4).
0001 sempre significa matriz.
IS NUMERIC valida o campo.
SORT ZD funciona.
Banco pode usar DECIMAL.
JSON pode enviar um número.
A posição das letras tem significado.
ASCII e EBCDIC produzem o mesmo valor.
Cada uma dessas suposições pode estar escondida em milhares de linhas.
É por isso que bons profissionais de sistemas legados não começam mudando código.
Eles começam construindo um mapa de dependências.
Conclusão: o campo não cresceu, mas o sistema amadureceu
Padawan, o CNPJ alfanumérico é uma daquelas mudanças que ensinam uma poderosa lição de engenharia.
Durante décadas, muitos sistemas confundiram representação com significado.
O CNPJ parecia numérico porque era formado por números. Entretanto, ele nunca foi uma quantidade. Sempre foi uma chave textual de identificação.
Agora, a chegada das letras remove essa ilusão.
O programador COBOL que simplesmente trocar:
PIC 9(14)
por:
PIC X(14)
terá iniciado o trabalho.
O profissional que revisar arquivos, bancos, chaves, interfaces, módulos de validação, ordenação, codificação, APIs, documentos fiscais, observabilidade e testes terá realmente preparado o sistema.
No IBM Z aprendemos há décadas que sistemas críticos não quebram apenas por grandes revoluções.
Eles quebram por pequenas suposições que deixaram de ser verdade.
O novo CNPJ não é apenas uma letra chegando a um campo antigo.
É um lembrete de que contratos de dados também envelhecem, regras aparentemente eternas também mudam e nenhum PIC 9 deve ser considerado imortal.
Prepare seus copybooks.
Revise seus DCLGENs.
Convoque seus testes automatizados.
E nunca se esqueça do Easter egg mais importante desta jornada:
Quando a especificação disser ASCII e seu programa estiver rodando em EBCDIC, não confie no byte. Confie na regra de negócio.
Porque no Bellacosa Mainframe, até uma simples letra A pode valer 17 — e separar um processamento concluído com sucesso de uma longa madrugada examinando dumps no abençoado SDSF.
Sem comentários:
Enviar um comentário