Dicas sobre desenvolvimento de software, gestão e tributações

Rede Social

15 de outubro de 2020

Python: Uma função Pythônica para validar CNPJ



Seguindo a ideia do post anterior, onde mostrei uma solução para a validação de CPF, falarei hoje sobre a validação de CNPJ. Mas como o cálculo é bem parecido, vou destacar apenas as diferenças entre eles.

 

Para a validação do CPF, os pesos aplicados aos seus dígitos vão de 2 a 11. Para o CNPJ, os pesos vão de 2 a 9 e então reiniciamos os pesos (novamente em 2). E, assim como para o CPF, os pesos são aplicados da direita para a esquerda.


Vamos usar o CNPJ (gerado aleatoriamente) 90.306.453/0001-33 como exemplo.

Ao aplicarmos os pesos teremos as seguintes associações:

9
0
3
0
6
4
5
3
0
0
0
1

5

4

3

2

9

8

7

6

5

4

3

2

Sem contar o primeiro DV.

E

9
0
3
0
6
4
5
3
0
0
0
1
3
6
5
4
3
2
9
8
7
6
5
4
3
2

Contando o primeiro DV.


Como a partir da aplicação dos pesos o algoritmo é exatamente o mesmo ao do CPF, vamos direto para o código.

 

from itertools import cycle

LENGTH_CNPJ = 14


def is_cnpj_valido(cnpj: str) -> bool:
if len(cnpj) != LENGTH_CNPJ:
return False

if cnpj in (c * LENGTH_CNPJ for c in "1234567890"):
return False

cnpj_r = cnpj[::-1]
for i in range(2, 0, -1):
cnpj_enum = zip(cycle(range(2, 10)), cnpj_r[i:])
dv = sum(map(lambda x: int(x[1]) * x[0], cnpj_enum)) * 10 % 11
if cnpj_r[i - 1:i] != str(dv % 10):
return False

return True


if __name__ == "__main__":
print("CNPJs inválidos")
print(is_cnpj_valido("0"))
print(is_cnpj_valido("123456789012345"))
print(is_cnpj_valido("5" * LENGTH_CNPJ))
print(is_cnpj_valido("90306453000103"))
print(is_cnpj_valido("90306453000130"))
print("CNPJs válidos")
print(is_cnpj_valido("90306453000133"))
print(is_cnpj_valido("82671952000100"))
print(is_cnpj_valido("31049514000165"))
print(is_cnpj_valido("77437514000133"))
print(is_cnpj_valido("00059549000151"))


Temos apenas 3 diferenças entre os códigos de validação de CNPJ e CPF, que são:

1. A importação da função "cycle" do pacote "intertools"

2. O tamanho da constante que é 14 para CNPJ

3. O método da aplicação dos pesos.


Como são apenas estas as diferenças, e a importação e o tamanho da constante não precisam maiores explicações, vou explicar apenas a parte dos pesos. (Para a explicação do restante do algoritmo, acesse o post do CPF).


Para aplicar os pesos do CPF, nós fazemos uso da função "enumerate", porém não podemos fazer o uso da mesma função para o CNPJ, pois os pesos do CNPJ não são sequenciais, uma vez que a sequência é reiniciada ao atingir o valor 9.

Para atendermos esta particularidade, fazemos uso de 3 funções: "range", "cycle" e "zip". Como todas são funções que merecem posts específicos para explicá-las, vamos apenas resumir como elas agem no algoritmo.

A função range irá nos retornar um iterável que se inicia em 2 e termina em 9 (o 10 não é incluso).

Este iterável é recebido pela função cycle, que por sua vez devolve um objeto "itertools.cycle". Vamos dizer que esse objeto é tipo um "iterável infinito", pois se fizermos um "for" nele, o loop "nunca" será finalizado.

Por fim pegamos este "iterável infinito" e o iterável com os dígitos invertidos do CNPJ e passamos para a função zip. A função irá unir estes 2 iteráveis, limitando o resultado pelo tamanho do menor iterável (neste caso o CNPJ). Com isso teremos todos os dígitos do CNPJ com seus respectivos pesos aplicados, similar ao que a função enumerate faz com o CPF.

A partir daqui segue igual ao que é feito com o CPF.

0 comentários:

Postar um comentário