From e94c3f1f468e05a3b80dd6ae8f04f2b79d26bd4b Mon Sep 17 00:00:00 2001 From: Javier Aranda Date: Mon, 10 Aug 2020 22:42:25 +0200 Subject: [PATCH] Improve Faker::Company.spanish_organisation_number --- lib/faker/default/company.rb | 38 ++++++++++++++++++++++-- test/faker/default/test_faker_company.rb | 30 +++++++++++++++++-- 2 files changed, 62 insertions(+), 6 deletions(-) diff --git a/lib/faker/default/company.rb b/lib/faker/default/company.rb index 1b1e486242..00e4381829 100644 --- a/lib/faker/default/company.rb +++ b/lib/faker/default/company.rb @@ -162,10 +162,17 @@ def profession # @faker.version 1.8.5 # # Get a random Spanish organization number. See more here https://es.wikipedia.org/wiki/N%C3%BAmero_de_identificaci%C3%B3n_fiscal - def spanish_organisation_number + def spanish_organisation_number(organization_type: nil) # Valid leading character: A, B, C, D, E, F, G, H, J, N, P, Q, R, S, U, V, W - # 7 digit numbers - [sample(self::ULetters), format('%07d', rand(10**7))].join + # format: 1 digit letter (organization type) + 7 digit numbers + 1 digit control (letter or number based on + # organization type) + letters = %w[A B C D E F G H J N P Q R S U V W] + + organization_type = sample(letters) unless letters.include?(organization_type) + code = format('%07d', rand(10**7)) + control = spanish_cif_control_digit(organization_type, code) + + [organization_type, code, control].join end ## @@ -528,6 +535,31 @@ def inn_checksum(factor, number) end % 11 % 10 ).to_s end + + def spanish_cif_control_digit(organization_type, code) + letters = %w[J A B C D E F G H] + + control = code.split('').each_with_index.inject(0) do |sum, (value, index)| + if (index + 1).even? + sum + value.to_i + else + sum + spanish_b_algorithm(value.to_i) + end + end + + control = control.to_s[-1].to_i + control = control.zero? ? control : 10 - control + + %w[A B C D E F G H J U V].include?(organization_type) ? control : letters[control] + end + + def spanish_b_algorithm(value) + result = value.to_i * 2 + + return result if result < 10 + + result.to_s[0].to_i + result.to_s[1].to_i + end end end end diff --git a/test/faker/default/test_faker_company.rb b/test/faker/default/test_faker_company.rb index 87d97fddd0..e0442942a8 100644 --- a/test/faker/default/test_faker_company.rb +++ b/test/faker/default/test_faker_company.rb @@ -28,9 +28,8 @@ def test_type end def test_spanish_organisation_number - org_no = @tester.spanish_organisation_number - assert org_no.match(/\D\d{7}/) - assert Faker::Base::ULetters.include?(org_no[0].to_s) + cif = @tester.spanish_organisation_number(organization_type: 'A') + assert @tester.send(:spanish_cif_control_digit, 'A', cif[1..7]) == cif[-1].to_i end def test_swedish_organisation_number @@ -211,6 +210,31 @@ def test_sic_code assert @tester.sic_code.match(/\d\d\d\d/) end + def test_spanish_cif_control_digit + assert @tester.send(:spanish_cif_control_digit, 'A', '2217680') == 4 + assert @tester.send(:spanish_cif_control_digit, 'B', '4031315') == 7 + assert @tester.send(:spanish_cif_control_digit, 'C', '7191088') == 9 + assert @tester.send(:spanish_cif_control_digit, 'D', '3178686') == 6 + assert @tester.send(:spanish_cif_control_digit, 'E', '4484441') == 3 + assert @tester.send(:spanish_cif_control_digit, 'F', '4830511') == 4 + assert @tester.send(:spanish_cif_control_digit, 'G', '7676903') == 3 + assert @tester.send(:spanish_cif_control_digit, 'H', '8888075') == 2 + assert @tester.send(:spanish_cif_control_digit, 'J', '6840041') == 5 + assert @tester.send(:spanish_cif_control_digit, 'N', '5350867') == 'G' + assert @tester.send(:spanish_cif_control_digit, 'P', '5669582') == 'H' + assert @tester.send(:spanish_cif_control_digit, 'Q', '5182823') == 'D' + assert @tester.send(:spanish_cif_control_digit, 'R', '1099088') == 'E' + assert @tester.send(:spanish_cif_control_digit, 'S', '2210399') == 'H' + assert @tester.send(:spanish_cif_control_digit, 'U', '3957325') == 8 + assert @tester.send(:spanish_cif_control_digit, 'V', '7536342') == 4 + assert @tester.send(:spanish_cif_control_digit, 'W', '6793772') == 'B' + end + + def test_spanish_b_algorithm + assert @tester.send(:spanish_b_algorithm, 2) == 4 + assert @tester.send(:spanish_b_algorithm, 6) == 3 + end + private def czech_o_n_checksum(org_no)