-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathvalidacpfcnpj.py
151 lines (120 loc) · 4.48 KB
/
validacpfcnpj.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
import re
from typing import Union
class ValidaCpfCnpj:
"""
Valida CPF ou CNPJ realizando cálculos dos dígitos
"""
def __init__(self, cpf_cnpj: str = '') -> None:
"""Recebe o CPF/CNPJ
:param cpf_cnpj: o CPF/CNPJ
:type cpf_cnpj: str
"""
self._validado = False
# O CPF pode ser enviado direto ao instanciar a classe
# ou como property
if cpf_cnpj:
self.cpf_cnpj: str = cpf_cnpj
def valida(self) -> bool:
"""Realiza toda a validação
:return: True se for válido, False caso contrário
:rtype: bool
"""
if not self.cpf_cnpj:
return False
qtd_caractere = len(self.cpf_cnpj)
# CPF
if qtd_caractere == 11:
# Primeiros 9 digitos
novo_cpf_cnpj: str = self._calcula_digitos(self.cpf_cnpj[:9],
multiplicador_inicial=10)
# 9 digitos + primeiro digito verificador
novo_cpf_cnpj: str = self._calcula_digitos(novo_cpf_cnpj,
multiplicador_inicial=11)
if novo_cpf_cnpj == self.cpf_cnpj:
self._validado = True
return True
# CNPJ
elif qtd_caractere == 14:
# Primeiros 12 digitos
novo_cpf_cnpj: str = self._calcula_digitos(self.cpf_cnpj[:12],
multiplicador_inicial=5)
# 12 digitos + primeiro digito verificador
novo_cpf_cnpj: str = self._calcula_digitos(novo_cpf_cnpj,
multiplicador_inicial=6)
if novo_cpf_cnpj == self.cpf_cnpj:
self._validado = True
return True
return False
@property
def formatado(self):
"""Formata o CPF/CNPJ
:raises ValueError: Se o CPF/CNPJ não for enviado ou não for válido
:return: o cpf ou cnpj formatado
:rtype: str
"""
if not self._validado:
if not self.cpf_cnpj or not self.valida():
raise ValueError("Enviar o CPF e validar para "
"obter CPF formatado.")
qtd_caracteres = len(self.cpf_cnpj)
if qtd_caracteres == 11:
cpf = self.cpf_cnpj
return '%s.%s.%s-%s' % (cpf[0:3], cpf[3:6], cpf[6:9], cpf[9:],)
elif qtd_caracteres == 14:
cnpj = self.cpf_cnpj
# 63.080.648/0001-35
return '%s.%s.%s/%s-%s' % \
(cnpj[0:2], cnpj[2:5], cnpj[5:8], cnpj[8:12], cnpj[12:])
@staticmethod
def _calcula_digitos(
fatia_cpf_cnpj: str,
multiplicador_inicial: int
) -> Union[str, bool]:
"""Realiza os cálculos das posições
:param fatia_cpf_cnpj: fatias de 9 ou 10 digitos do CPF
:type fatia_cpf_cnpj: str
:param multiplicador_inicial: o número que inicia os cálculos
:type multiplicador_inicial: int
:return: a fatia do CPF mais um dos digitos gerados
:rtype: Union[str, bool]
"""
if not fatia_cpf_cnpj:
return False
# Evita sequências
sequencia: str = fatia_cpf_cnpj[0] * len(fatia_cpf_cnpj)
if sequencia == fatia_cpf_cnpj:
return False
soma: int = 0
for chave, _ in enumerate(range(len(fatia_cpf_cnpj) + 1, 1, -1)):
soma += int(fatia_cpf_cnpj[chave]) * multiplicador_inicial
if (multiplicador_inicial == 2):
multiplicador_inicial = 9
else:
multiplicador_inicial -= 1
resto: int = 11 - (soma % 11)
resto: int = resto if resto <= 9 else 0
return fatia_cpf_cnpj + str(resto)
@property
def cpf_cnpj(self) -> str:
"""Getter do CPF
:return: o CPF
:rtype: str
"""
self._validado = False
return self._cpf_cnpj
@cpf_cnpj.setter
def cpf_cnpj(self, cpf_cnpj: str):
"""Setter do CPF
:param cpf: o CPF
:type cpf: str
"""
self._cpf_cnpj = self._so_numeros(cpf_cnpj)
@staticmethod
def _so_numeros(cpf_cnpj: str) -> str:
"""Remove todos os digitos não numéricos
:param cpf_cnpj: o cpf ou cnpj
:type cpf_cnpj: str
:return: o cpf/cnpj formatado (só com números)
:rtype: str
"""
return re.sub('[^0-9]', '', cpf_cnpj)