Skip to content

Commit

Permalink
Merge pull request #18 from luizpericolo/luizpericolo-voting-document
Browse files Browse the repository at this point in the history
luizpericolo Voting Document
  • Loading branch information
alvarofpp authored Oct 30, 2019
2 parents 0fe3394 + c9336e4 commit 66399bb
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 1 deletion.
3 changes: 2 additions & 1 deletion docs/sobre.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ Documentos que estão no pacote:

- CPF: Cadastro de Pessoas Físicas;
- CNPJ: Cadastro Nacional da Pessoa Jurídica;
- CNS: Cartão Nacional de Saúde.
- CNS: Cartão Nacional de Saúde,
- Título Eleitoral: Cadastro que permite cidadãos brasileiros votar.
2 changes: 2 additions & 0 deletions tests/test_all.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import tests.test_cnh
import tests.test_cns
import tests.test_cnpj
import tests.test_titulo_eleitor


def suite():
Expand All @@ -14,6 +15,7 @@ def suite():
test_suite.addTests(loader.loadTestsFromModule(tests.test_cnh))
test_suite.addTests(loader.loadTestsFromModule(tests.test_cns))
test_suite.addTests(loader.loadTestsFromModule(tests.test_cnpj))
test_suite.addTests(loader.loadTestsFromModule(tests.test_titulo_eleitor))

return test_suite

Expand Down
36 changes: 36 additions & 0 deletions tests/test_titulo_eleitor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import unittest
import validate_docbr as docbr


class TestTituloEleitoral(unittest.TestCase):
def setUp(self):
""" Inicia novo objeto em todo os testes """
self.titulo_eleitoral = docbr.TituloEleitoral()

def test_generate(self):
""" Verifica se o método generate """
# generate, generate(mask=True)
titulos = [self.titulo_eleitoral.generate() for i in range(10000)]\
+ [self.titulo_eleitoral.generate(mask=True) for i in range(10000)]
self.assertIsInstance(titulos, list)
self.assertTrue(len(titulos) == 20000)

def test_generate_list(self):
""" Verifica se o método generate_list """
# generate_list
titulo_eleitoral = self.titulo_eleitoral.generate_list(10000)\
+ self.titulo_eleitoral.generate_list(10000, True)\
+ self.titulo_eleitoral.generate_list(10000, True, True)
self.assertIsInstance(titulo_eleitoral, list)
self.assertTrue(len(titulo_eleitoral) == 30000)

def test_validate(self):
""" Verifica se o método validate """
# validate
for titulo in self.titulo_eleitoral.generate_list(10000):
self.assertTrue(self.titulo_eleitoral.validate(titulo))

def test_mask_returns_correctly_formatted_string(self):
masked_titulo = self.titulo_eleitoral.mask('123123123123')

self.assertEquals(masked_titulo, '1231 2312 3123')
82 changes: 82 additions & 0 deletions validate_docbr/TituloEleitoral.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
from .BaseDoc import BaseDoc

from random import sample
from typing import List


class TituloEleitoral(BaseDoc):
"""Classe referente ao Título eleitoral"""
def __init__(self):
self.digits = list(range(10))
self.first_check_digit_weights = list(range(2, 10))
self.second_check_digit_weights = list(range(7, 10))
self.first_check_digit_doc_slice = slice(0, 8)
self.second_check_digit_doc_slice = slice(8, 10)

def __compute_first_check_digit(self, doc_digits: List[int]) -> int:
"""Método que calcula o primeiro dígito verificador."""
doc_digits_to_consider = doc_digits[self.first_check_digit_doc_slice]
terms = [
doc_digit * multiplier
for doc_digit, multiplier in zip(doc_digits_to_consider, self.first_check_digit_weights)
]

total = sum(terms)

if total % 11 == 10:
return 0

return total % 11

def __compute_second_check_digit(self, doc_digits: List[int], first_check_digit: int) -> int:
"""Método que calcula o segundo dígito verificador."""
doc_digits_to_consider = doc_digits[self.second_check_digit_doc_slice] + [first_check_digit]
terms = [
doc_digit * multiplier
for doc_digit, multiplier in zip(doc_digits_to_consider, self.second_check_digit_weights)
]

total = sum(terms)

if total % 11 == 10:
return 0

return total % 11

def validate(self, doc: str = '') -> bool:
"""Método para validar o título eleitoral."""
doc_digits = list(map(int, self._only_digits(doc=doc)))

if len(doc_digits) != 12:
return False

first_check_digit = self.__compute_first_check_digit(doc_digits=doc_digits)
second_check_digit = self.__compute_second_check_digit(doc_digits=doc_digits, first_check_digit=first_check_digit)

return first_check_digit == doc_digits[-2] and second_check_digit == doc_digits[-1]

def __generate_valid_state_identifier(self) -> str:
state_identifier = str(sample(range(1, 19), 1)[0])
return state_identifier.zfill(2)

def generate(self, mask: bool = False) -> str:
"""Método para gerar um título eleitoral válido."""
document_digits = [sample(self.digits, 1)[0] for _ in range(8)]

state_identifier = self.__generate_valid_state_identifier()
document_digits.extend(map(int, state_identifier))

first_check_digit = self.__compute_first_check_digit(doc_digits=document_digits)
second_check_digit = self.__compute_second_check_digit(doc_digits=document_digits, first_check_digit=first_check_digit)

document_digits.extend([first_check_digit, second_check_digit])

document = ''.join(map(str, document_digits))

if mask:
return self.mask(doc=document)
return document

def mask(self, doc: str = '') -> str:
"""Mascara o documento enviado"""
return '{} {} {}'.format(doc[0:4], doc[4:8], doc[8:])
1 change: 1 addition & 0 deletions validate_docbr/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
from .CNPJ import CNPJ
from .CNH import CNH
from .CNS import CNS
from .TituloEleitoral import TituloEleitoral

0 comments on commit 66399bb

Please sign in to comment.