diff --git a/CHANGELOG.md b/CHANGELOG.md index eea15cc8b0..85cf017418 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### Latest update: 2018-06-09 ### Feature Request +- [PR #877](https://github.com/stympy/faker/pull/877) Add Canada SIN generator in Faker::Code [@gkunwar](https://github.com/gkunwar) - [PR #1268](https://github.com/stympy/faker/pull/1268) Add Faker::Nation.national_sport [@gkunwar](https://github.com/gkunwar) - [PR #1273](https://github.com/stympy/faker/pull/1273) Add Faker::Device [@vbrazo](https://github.com/vbrazo) - [PR #1272](https://github.com/stympy/faker/pull/1272) Add Faker::DrWho.actor [@timcustard](https://github.com/timcustard) diff --git a/doc/code.md b/doc/code.md index 97df668432..e6da5eeea4 100644 --- a/doc/code.md +++ b/doc/code.md @@ -16,4 +16,6 @@ Faker::Code.nric(27, 34) #=> S8505970Z Faker::Code.imei #= "546327785982623" Faker::Code.asin #=> "B00000IGGJ" + +Fake::Code:sin #=> "159160274" ``` diff --git a/lib/faker/code.rb b/lib/faker/code.rb index b99c4de354..e20ebe2938 100644 --- a/lib/faker/code.rb +++ b/lib/faker/code.rb @@ -48,6 +48,25 @@ def asin fetch('code.asin') end + # Generates Social Insurance Number issued in Canada + # https://en.wikipedia.org/wiki/Social_Insurance_Number + def sin + # 1 - province or temporary resident + # 2-8 - random numbers + # 9 - checksum + + # 1st digit. 8,0 are not used + registry = Faker::Base.sample([1, 2, 3, 4, 5, 6, 7, 9]).to_s + + # generate 2nd to 8th + partial = Array.new(7) { Faker::Config.random.rand(0..9) }.join + + # Generate 9th digit + check_digit = generate_sin_check_digit(registry + partial + '0').to_s + + registry + partial + check_digit + end + private # Reporting body identifier @@ -138,6 +157,30 @@ def generate_nric_check_alphabet(values, prefix) total += 4 if prefix == 'T' %w[A B C D E F G H I Z J][10 - total % 11] end + + def generate_sin_check_digit(digits) + # Fast Luhn checksum code from luhn.js: + # https://gist.github.com/ShirtlessKirk/2134376 + + len = 9 + mul = 0 + + luhn_arr = [ + [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], + [0, 2, 4, 6, 8, 1, 3, 5, 7, 9] + ] + sum = 0 + + while len > 0 + len -= 1 + num = digits[len].to_i + sum += luhn_arr[mul][num] + mul ^= 1 + end + + checksum = sum % 10 + checksum.zero? ? checksum : (10 - checksum) + end end end end diff --git a/test/test_faker_code.rb b/test/test_faker_code.rb index 057c06a2cc..4839820bfd 100644 --- a/test/test_faker_code.rb +++ b/test/test_faker_code.rb @@ -53,6 +53,12 @@ def test_imei_luhn_value assert luhn_checksum_valid(@tester.imei) end + def test_sin + assert @tester.sin.match(/\d{9}/) + assert @tester.sin.length == 9 + assert luhn_checksum_valid(@tester.sin) + end + def luhn_checksum_valid(numbers) sum = 0 i = 0