Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Brazilian documents generation and documentation #1495

Merged
merged 27 commits into from
Aug 11, 2019
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
5b6ff9c
Merge pull request #1 from stympy/master
lucasqueiroz Dec 16, 2018
a145af9
Change default parameter format in brazilian_citizen_number
lucasqueiroz Dec 16, 2018
f56d364
Add alias to brazilian_citizen_number
lucasqueiroz Dec 16, 2018
9d6b9d5
Add Brazilian ID generator
lucasqueiroz Dec 16, 2018
981fe10
Change generator for Brazilian ID number
lucasqueiroz Dec 16, 2018
4463195
Add docs for Brazilian Citizen Number (CPF)
lucasqueiroz Dec 16, 2018
a1ba4f9
Add docs for Brazilian ID (RG)
lucasqueiroz Dec 16, 2018
d512276
Merge pull request #2 from stympy/master
lucasqueiroz Dec 22, 2018
d02ca09
Merge branch 'master' into brazilian_documents
lucasqueiroz Dec 22, 2018
1d0a40a
Add tests for brazilian id digit
lucasqueiroz Dec 22, 2018
9318467
Remove if statement from brazilian id digit method
lucasqueiroz Dec 22, 2018
69206ee
Refactor brazilian_document_remainder and rename it to brazilian_docu…
lucasqueiroz Dec 22, 2018
2ab5ea4
Add tests for brazilian_citizen_number_digit
lucasqueiroz Dec 22, 2018
9428748
Add tests for brazilian_document_digit
lucasqueiroz Dec 22, 2018
57f9543
Add tests for brazilian_document_checksum
lucasqueiroz Dec 22, 2018
b5f5b30
Add tests for brazilian_id_checksum_digit
lucasqueiroz Dec 22, 2018
d375cae
Add tests for brazilian_citizen_number_checksum_digit
lucasqueiroz Dec 22, 2018
08e38fc
Simplify brazilian document tests
lucasqueiroz Dec 22, 2018
c3645ab
Merge pull request #3 from stympy/master
lucasqueiroz Jul 18, 2019
0a6db17
Remove old doc file
lucasqueiroz Jul 18, 2019
da6b35c
Add Brazilian ID (RG) to ID Number docs
lucasqueiroz Jul 18, 2019
9607878
Minor changes
vbrazo Aug 10, 2019
e2ee9c3
Remove unused file
vbrazo Aug 10, 2019
afe0102
Merge branch 'master' into brazilian_documents
vbrazo Aug 10, 2019
080e928
Minor fixes
vbrazo Aug 11, 2019
132220b
Readd docs after deleting unreleased docs folder
vbrazo Aug 11, 2019
6bebe20
docs
vbrazo Aug 11, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions doc/v1.9.1/id_number.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,16 @@ Faker::IDNumber.spanish_citizen_number

# Generate a Spanish foreign born citizen identifier (NIE)
Faker::IDNumber.spanish_foreign_citizen_number

# Generate a Brazilian Citizen Number (CPF)
Faker::IDNumber.brazilian_citizen_number #=> "03522455657"
Faker::IDNumber.brazilian_citizen_number(formatted: true) #=> "006.726.029-20"
Faker::IDNumber.brazilian_cpf #=> "03522455657"
Faker::IDNumber.brazilian_cpf(formatted: true) #=> "006.726.029-20"

# Generate a Brazilian ID (RG)
Faker::IDNumber.brazilian_id #=> "924805353"
Faker::IDNumber.brazilian_id(formatted: true) #=> "68.456.954-1"
Faker::IDNumber.brazilian_rg #=> "924805353"
Faker::IDNumber.brazilian_rg(formatted: true) #=> "68.456.954-1"
```
43 changes: 40 additions & 3 deletions lib/faker/default/id_number.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ class IDNumber < Base
].freeze
ZA_RACE_DIGIT = '8'
ZA_CITIZENSHIP_DIGITS = %w[0 1].freeze
BRAZILIAN_ID_FORMAT = /(\d{1,2})(\d{3})(\d{3})([\dX])/
BRAZILIAN_ID_FROM = 10_000_000
BRAZILIAN_ID_TO = 99_999_999

class << self
def valid
Expand Down Expand Up @@ -75,14 +78,25 @@ def invalid_south_african_id_number
[id_number, south_african_id_checksum_digit(id_number)].join
end

def brazilian_citizen_number(formatted: false)
def brazilian_citizen_number(formatted = false)
digits = Faker::Number.leading_zero_number(9) until digits&.match(/(\d)((?!\1)\d)+/)
first_digit = brazilian_citizen_number_checksum_digit(digits)
second_digit = brazilian_citizen_number_checksum_digit(digits + first_digit)
number = [digits, first_digit, second_digit].join
formatted ? format('%s.%s.%s-%s', *number.scan(/\d{2,3}/).flatten) : number
end

alias brazilian_cpf brazilian_citizen_number

def brazilian_id(formatted = false)
digits = Faker::Number.between(BRAZILIAN_ID_FROM, BRAZILIAN_ID_TO).to_s
check_digit = brazilian_id_checksum_digit(digits)
number = [digits, check_digit].join
formatted ? format('%s.%s.%s-%s', *number.scan(BRAZILIAN_ID_FORMAT).flatten) : number
end

alias brazilian_rg brazilian_id

private

def south_african_id_checksum_digit(id_number)
Expand All @@ -104,13 +118,36 @@ def south_african_id_checksum_digit(id_number)
end

def brazilian_citizen_number_checksum_digit(digits)
digit_sum = digits.chars.each_with_index.inject(0) do |acc, (digit, i)|
checksum = brazilian_document_checksum(digits)
brazilian_document_digit(checksum)
end

def brazilian_id_checksum_digit(digits)
checksum = brazilian_document_checksum(digits)
brazilian_document_digit(checksum, id: true)
end

def brazilian_document_checksum(digits)
digits.chars.each_with_index.inject(0) do |acc, (digit, i)|
acc + digit.to_i * (digits.size + 1 - i)
end * 10
remainder = digit_sum % 11
end

def brazilian_document_digit(checksum, id = false)
remainder = checksum % 11
id ? brazilian_id_digit(remainder) : brazilian_citizen_number_digit(remainder)
end

def brazilian_citizen_number_digit(remainder)
remainder == 10 ? '0' : remainder.to_s
end

def brazilian_id_digit(remainder)
subtraction = 11 - remainder.to_i
digits = { 10 => 'X', 11 => '0' }
digits.include?(subtraction) ? digits[subtraction] : subtraction.to_s
end

def _translate(key)
parse("id_number.#{key}")
end
Expand Down
73 changes: 61 additions & 12 deletions test/faker/default/test_faker_id_number.rb
Original file line number Diff line number Diff line change
Expand Up @@ -67,25 +67,74 @@ def test_brazilian_citizen_number
sample = @tester.brazilian_citizen_number
assert_match(/^\d{11}$/, sample)
assert_match(/(\d)((?!\1)\d)+/, sample)
digit_sum = sample[0..8].chars.each_with_index.inject(0) do |acc, (digit, i)|
acc + digit.to_i * (10 - i)
end * 10
remainder = digit_sum % 11
first_digit = remainder == 10 ? '0' : remainder.to_s
assert_equal sample[9], first_digit
digit_sum = sample[0..9].chars.each_with_index.inject(0) do |acc, (digit, i)|
acc + digit.to_i * (11 - i)
end * 10
remainder = digit_sum % 11
second_digit = remainder == 10 ? '0' : remainder.to_s
assert_equal sample[10], second_digit
end

def test_brazilian_citizen_number_formatted
sample = @tester.brazilian_citizen_number(formatted: true)
assert_match(/^\d{3}\.\d{3}\.\d{3}-\d{2}$/, sample)
end

def test_brazilian_id
sample = @tester.brazilian_id
assert_match(/^\d{9}$/, sample)
assert_match(/(\d)((?!\1)\d)+/, sample)
end

def test_brazilian_id_formatted
sample = @tester.brazilian_id(formatted: true)
assert_match(/^\d{1,2}.\d{3}.\d{3}-[\dX]$/, sample)
end

def test_brazilian_citizen_number_checksum_digit
digits = '128991760'
checksum_digit = Faker::IDNumber.send(:brazilian_citizen_number_checksum_digit, digits)
assert_equal checksum_digit, '4'
digits = '1289917604'
checksum_digit = Faker::IDNumber.send(:brazilian_citizen_number_checksum_digit, digits)
assert_equal checksum_digit, '8'
end

def test_brazilian_id_checksum_digit
digits = '41987080'
checksum_digit = Faker::IDNumber.send(:brazilian_id_checksum_digit, digits)
assert_equal checksum_digit, '5'
end

def test_brazilian_document_checksum
digits = '123456789'
checksum = Faker::IDNumber.send(:brazilian_document_checksum, digits)
assert_equal checksum, 2100
end

def test_brazilian_document_digit
citizen_number_digit10 = Faker::IDNumber.send(:brazilian_document_digit, 10)
citizen_number_digit_other = Faker::IDNumber.send(:brazilian_document_digit, 9)
id_digit10 = Faker::IDNumber.send(:brazilian_document_digit, 1, true)
id_digit11 = Faker::IDNumber.send(:brazilian_document_digit, 0, true)
id_digit_other = Faker::IDNumber.send(:brazilian_document_digit, 2, true)
assert_equal citizen_number_digit10, '0'
assert_equal citizen_number_digit_other, '9'
assert_equal id_digit10, 'X'
assert_equal id_digit11, '0'
assert_equal id_digit_other, '9'
end

def test_brazilian_citizen_number_digit
digit10 = Faker::IDNumber.send(:brazilian_citizen_number_digit, 10)
digit_other = Faker::IDNumber.send(:brazilian_citizen_number_digit, 9)
assert_equal digit10, '0'
assert_equal digit_other, '9'
end

def test_brazilian_id_digit
digit10 = Faker::IDNumber.send(:brazilian_id_digit, 1)
digit11 = Faker::IDNumber.send(:brazilian_id_digit, 0)
digit_other = Faker::IDNumber.send(:brazilian_id_digit, 2)
assert_equal digit10, 'X'
assert_equal digit11, '0'
assert_equal digit_other, '9'
end

private

def south_african_id_number_to_date_of_birth_string(sample)
Expand Down