diff --git a/doc/id_number.md b/doc/id_number.md index bcd2a36105..81f6ed1640 100644 --- a/doc/id_number.md +++ b/doc/id_number.md @@ -20,4 +20,7 @@ Faker::IDNumber.valid_south_african_id_number #=> "8105128870184" # Generate an invalid South African ID Number Faker::IDNumber.invalid_south_african_id_number #=> "1642972065088" + +# Generate a Brazilian citizen number (CPF) +Faker::IDNumber.brazilian_citizen_number #=> "53540542221" ``` diff --git a/lib/faker/id_number.rb b/lib/faker/id_number.rb index 34b5f9f749..df5a14af03 100644 --- a/lib/faker/id_number.rb +++ b/lib/faker/id_number.rb @@ -75,6 +75,13 @@ def invalid_south_african_id_number [id_number, south_african_id_checksum_digit(id_number)].join end + def brazilian_citizen_number + 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) + [digits, first_digit, second_digit].join + end + private def south_african_id_checksum_digit(id_number) @@ -95,6 +102,14 @@ def south_african_id_checksum_digit(id_number) ((10 - (total_sum % 10)) % 10).to_s end + def brazilian_citizen_number_checksum_digit(digits) + digit_sum = 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 + remainder == 10 ? '0' : remainder.to_s + end + def _translate(key) parse("id_number.#{key}") end diff --git a/test/test_faker_id_number.rb b/test/test_faker_id_number.rb index 1f50c6476b..c24dbed60e 100644 --- a/test/test_faker_id_number.rb +++ b/test/test_faker_id_number.rb @@ -63,6 +63,24 @@ def test_invalid_south_african_id_number end end + 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 + private def south_african_id_number_to_date_of_birth_string(sample)