rfc_facil 0.1.1 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2e4beff53f9889d87b462d70ef89626a465c47fd
4
- data.tar.gz: 2c3a42b7c21b0799d0d88581917476c86a054cc9
3
+ metadata.gz: 13be1b95f84eeda13a0db0fef85d61561db1f8cd
4
+ data.tar.gz: a0927464ec27e36164f7a2f81b168dc6da322690
5
5
  SHA512:
6
- metadata.gz: ef619a13b09e212df01f75df492fc5d616de7c546d647fc7fbc01f752a1f656baa624c6e304f94c904e22c74f7b1a2bc7c4769d6b21901fd6865716cb010bc91
7
- data.tar.gz: 21b4428b04a98f0f5acf266a8984ea0201f85e62b53ed4f80e43601b3b9167efda69b7ab3be5f95cfbbcdc66416ef9da5eb2c34fddc4c04dc500d8304bc46f07
6
+ metadata.gz: 8f8e93171358b4cc72b4082235fbf2d562595caf7b7c4781319e1b43edc42b62182a4b6de36d124dc69f3de6d7d1685792ecc962b72a987bd5f23dbfaf694170
7
+ data.tar.gz: bd7f631ffce63eafde81dac49bb1c1c4b214c8cb33b3ea1121a638de7e762f168146576f9da55e33e4f7cb6270b785ddbf92addd6d8e34910cabce2b7be22b3f
data/README.md CHANGED
@@ -1,4 +1,7 @@
1
1
  # Rfc Fácil
2
+ [![Code Climate](https://codeclimate.com/github/Munett/rfc_facil/badges/gpa.svg)](https://codeclimate.com/github/Munett/rfc_facil)
3
+ [![Test Coverage](https://codeclimate.com/github/Munett/rfc_facil/badges/coverage.svg)](https://codeclimate.com/github/Munett/rfc_facil/coverage)
4
+
2
5
  ![](https://github.com/acrogenesis/rfc_facil/raw/master/logo.png)
3
6
 
4
7
  Libreria para calcular el Registro Federal de Contribuyentes en México (RFC) en Ruby.
@@ -12,7 +15,7 @@ gem 'rfc_facil'
12
15
  ```
13
16
  Calcular el rfc de una persona física es muy sencillo:
14
17
  ```ruby
15
- rfc = Rfc.new(name: 'Adrián Marcelo', first_last_name: 'Rangel', second_last_name: 'Araujo', day: 27, month: 11, year: 1992)
18
+ rfc = RfcFacil::Rfc.new(name: 'Adrián Marcelo', first_last_name: 'Rangel', second_last_name: 'Araujo', day: 27, month: 11, year: 1992)
16
19
  rfc.to_s # => 'RAAA921127RI6'
17
20
  ```
18
21
 
@@ -1,8 +1,10 @@
1
1
  require 'rfc_facil/version'
2
2
  require 'rfc_facil/homoclave_calculator'
3
- require 'rfc_facil/person'
3
+ require 'rfc_facil/natural_person'
4
+ require 'rfc_facil/juristic_person'
4
5
  require 'rfc_facil/rfc'
5
- require 'rfc_facil/ten_digits_code_calculator'
6
+ require 'rfc_facil/natural_ten_digits_code_calculator'
7
+ require 'rfc_facil/juristic_ten_digits_code_calculator'
6
8
  require 'rfc_facil/verification_digit_calculator'
7
9
  require 'i18n'
8
10
  require 'unicode_utils/upcase'
@@ -1,72 +1,74 @@
1
- class HomoclaveCalculator
2
- HOMOCLAVE_DIGITS = '123456789ABCDEFGHIJKLMNPQRSTUVWXYZ'
3
- FULL_NAME_MAPPING = {
4
- ' ' => '00', '0' => '00', '1' => '01', '2' => '02', '3' => '03', '4' => '04',
5
- '5' => '05', '6' => '06', '7' => '07', '8' => '08', '9' => '09', '&' => '10',
6
- 'A' => '11', 'B' => '12', 'C' => '13', 'D' => '14', 'E' => '15', 'F' => '16',
7
- 'G' => '17', 'H' => '18', 'I' => '19', 'J' => '21', 'K' => '22', 'L' => '23',
8
- 'M' => '24', 'N' => '25', 'O' => '26', 'P' => '27', 'Q' => '28', 'R' => '29',
9
- 'S' => '32', 'T' => '33', 'U' => '34', 'V' => '35', 'W' => '36', 'X' => '37',
10
- 'Y' => '38', 'Z' => '39', 'Ñ' => '40'
11
- }
12
- attr_accessor :person, :full_name, :mapped_full_name, :pairs_of_digits_sum, :homoclave
1
+ module RfcFacil
2
+ class HomoclaveCalculator
3
+ HOMOCLAVE_DIGITS = '123456789ABCDEFGHIJKLMNPQRSTUVWXYZ'.freeze
4
+ FULL_NAME_MAPPING = {
5
+ ' ' => '00', '0' => '00', '1' => '01', '2' => '02', '3' => '03', '4' => '04',
6
+ '5' => '05', '6' => '06', '7' => '07', '8' => '08', '9' => '09', '&' => '10',
7
+ 'A' => '11', 'B' => '12', 'C' => '13', 'D' => '14', 'E' => '15', 'F' => '16',
8
+ 'G' => '17', 'H' => '18', 'I' => '19', 'J' => '21', 'K' => '22', 'L' => '23',
9
+ 'M' => '24', 'N' => '25', 'O' => '26', 'P' => '27', 'Q' => '28', 'R' => '29',
10
+ 'S' => '32', 'T' => '33', 'U' => '34', 'V' => '35', 'W' => '36', 'X' => '37',
11
+ 'Y' => '38', 'Z' => '39', 'Ñ' => '40'
12
+ }.freeze
13
+ attr_accessor :person, :full_name, :mapped_full_name, :pairs_of_digits_sum, :homoclave
13
14
 
14
- def initialize(person)
15
- @person = person
16
- end
15
+ def initialize(person)
16
+ @person = person
17
+ end
17
18
 
18
- def calculate
19
- normalize_full_name
20
- map_full_name_to_digits_code
21
- sum_pairs_of_digits
22
- build_homoclave
19
+ def calculate
20
+ normalize_full_name
21
+ map_full_name_to_digits_code
22
+ sum_pairs_of_digits
23
+ build_homoclave
23
24
 
24
- @homoclave
25
- end
25
+ @homoclave
26
+ end
26
27
 
27
- private
28
+ private
28
29
 
29
- def build_homoclave
30
- last_three_digits = (@pairs_of_digits_sum % 1000)
31
- quo = (last_three_digits / 34)
32
- reminder = (last_three_digits % 34)
33
- @homoclave = "#{HOMOCLAVE_DIGITS[quo]}#{HOMOCLAVE_DIGITS[reminder]}"
34
- end
30
+ def build_homoclave
31
+ last_three_digits = (@pairs_of_digits_sum % 1000)
32
+ quo = (last_three_digits / 34)
33
+ reminder = (last_three_digits % 34)
34
+ @homoclave = "#{HOMOCLAVE_DIGITS[quo]}#{HOMOCLAVE_DIGITS[reminder]}"
35
+ end
35
36
 
36
- def sum_pairs_of_digits
37
- @pairs_of_digits_sum = 0
38
- (0..@mapped_full_name.length - 2).each do |i|
39
- num1 = @mapped_full_name[i..i + 1].to_i
40
- num2 = @mapped_full_name[i + 1..i + 1].to_i
37
+ def sum_pairs_of_digits
38
+ @pairs_of_digits_sum = 0
39
+ (0..@mapped_full_name.length - 2).each do |i|
40
+ num1 = @mapped_full_name[i..i + 1].to_i
41
+ num2 = @mapped_full_name[i + 1..i + 1].to_i
41
42
 
42
- @pairs_of_digits_sum += num1 * num2
43
+ @pairs_of_digits_sum += num1 * num2
44
+ end
43
45
  end
44
- end
45
46
 
46
- def map_full_name_to_digits_code
47
- @mapped_full_name = '0'
48
- @full_name.each_char do |c|
49
- @mapped_full_name << map_character_to_two_digit_code(c)
47
+ def map_full_name_to_digits_code
48
+ @mapped_full_name = '0'
49
+ @full_name.each_char do |c|
50
+ @mapped_full_name << map_character_to_two_digit_code(c)
51
+ end
50
52
  end
51
- end
52
53
 
53
- def map_character_to_two_digit_code(c)
54
- return FULL_NAME_MAPPING[c] if FULL_NAME_MAPPING.key?(c)
55
- fail ArgumentError, "No two-digit-code mapping for char: #{c}"
56
- end
54
+ def map_character_to_two_digit_code(c)
55
+ return FULL_NAME_MAPPING[c] if FULL_NAME_MAPPING.key?(c)
56
+ raise ArgumentError, "No two-digit-code mapping for char: #{c}"
57
+ end
57
58
 
58
- def normalize_full_name
59
- raw_full_name = UnicodeUtils.upcase("#{@person}")
60
- @full_name = I18n.transliterate(raw_full_name)
61
- @full_name.gsub!(/[-.']/, '') # remove .'-
62
- add_missing_char_to_full_name(raw_full_name, 'Ñ')
63
- end
59
+ def normalize_full_name
60
+ raw_full_name = UnicodeUtils.upcase(@person.to_s)
61
+ @full_name = I18n.transliterate(raw_full_name)
62
+ @full_name.gsub!(/[-.']/, '') # remove .'-
63
+ add_missing_char_to_full_name(raw_full_name, 'Ñ')
64
+ end
64
65
 
65
- def add_missing_char_to_full_name(raw_full_name, missing_char)
66
- index = raw_full_name.index(missing_char)
67
- until index.nil?
68
- @full_name[index] = missing_char
69
- index = raw_full_name.index(missing_char, index + 1)
66
+ def add_missing_char_to_full_name(raw_full_name, missing_char)
67
+ index = raw_full_name.index(missing_char)
68
+ until index.nil?
69
+ @full_name[index] = missing_char
70
+ index = raw_full_name.index(missing_char, index + 1)
71
+ end
70
72
  end
71
73
  end
72
74
  end
@@ -0,0 +1,12 @@
1
+ module RfcFacil
2
+ class JuristicPerson
3
+ attr_accessor :legal_name, :day, :month, :year
4
+
5
+ def initialize(legal_name, day, month, year)
6
+ @legal_name = legal_name
7
+ @day = day
8
+ @month = month
9
+ @year = year
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,26 @@
1
+ module RfcFacil
2
+ class JuristicTenDigitsCodeCalculator
3
+ attr_accessor :person
4
+
5
+ def initialize(person)
6
+ @person = person
7
+ end
8
+
9
+ def calculate
10
+ words = person.legal_name.split('\\s')
11
+ "#{words[0][0]}#{words[1][0]}#{words[2][0]}-#{birthday_code}"
12
+ end
13
+
14
+ def birthday_code
15
+ "#{last_two_digits_of(person.year)}#{formatted_in_two_digits(person.month)}#{formatted_in_two_digits(person.day)}"
16
+ end
17
+
18
+ def formatted_in_two_digits(number)
19
+ format('%02d', number)
20
+ end
21
+
22
+ def last_two_digits_of(number)
23
+ formatted_in_two_digits(number % 100)
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,18 @@
1
+ module RfcFacil
2
+ class NaturalPerson
3
+ attr_accessor :name, :first_last_name, :second_last_name, :day, :month, :year
4
+
5
+ def initialize(name, first_last_name, second_last_name, day, month, year)
6
+ @name = name
7
+ @first_last_name = first_last_name
8
+ @second_last_name = second_last_name
9
+ @day = day
10
+ @month = month
11
+ @year = year
12
+ end
13
+
14
+ def to_s
15
+ "#{@first_last_name} #{@second_last_name} #{@name}"
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,124 @@
1
+ module RfcFacil
2
+ class NaturalTenDigitsCodeCalculator
3
+ VOWEL_PATTERN = /[AEIOU]+/
4
+ attr_accessor :person
5
+ SPECIAL_PARTICLES = %w(DE LA LAS MC VON DEL LOS Y MAC VAN MI).freeze
6
+ FORBIDDEN_WORDS = %w(
7
+ BUEI BUEY CACA CACO CAGA KOGE KAKA MAME KOJO KULO
8
+ CAGO COGE COJE COJO FETO JOTO KACO KAGO MAMO MEAR MEON
9
+ MION MOCO MULA PEDA PEDO PENE PUTA PUTO QULO RATA RUIN
10
+ ).freeze
11
+
12
+ def initialize(person)
13
+ @person = person
14
+ end
15
+
16
+ def calculate
17
+ "#{obfuscate_forbidden_words(name_code)}#{birthday_code}"
18
+ end
19
+
20
+ def obfuscate_forbidden_words(name_code)
21
+ FORBIDDEN_WORDS.each do |forbidden|
22
+ return "#{name_code[0..2]}X" if forbidden == name_code
23
+ end
24
+ name_code
25
+ end
26
+
27
+ def name_code
28
+ return first_last_name_empty_form if first_last_name_empty?
29
+ return second_last_name_empty_form if second_last_name_empty?
30
+ return first_last_name_too_short_form if first_last_name_is_too_short?
31
+ normal_form
32
+ end
33
+
34
+ def second_last_name_empty_form
35
+ first_two_letters_of(@person.first_last_name) <<
36
+ first_two_letters_of(filter_name(@person.name))
37
+ end
38
+
39
+ def birthday_code
40
+ "#{@person.year.to_s[-2, 2]}#{format('%02d', @person.month)}#{format('%02d', @person.day)}"
41
+ end
42
+
43
+ def second_last_name_empty?
44
+ normalize(@person.second_last_name).nil? || normalize(@person.second_last_name).empty?
45
+ end
46
+
47
+ def first_last_name_empty_form
48
+ first_two_letters_of(@person.second_last_name) <<
49
+ first_two_letters_of(filter_name(@person.name))
50
+ end
51
+
52
+ def first_last_name_empty?
53
+ normalize(@person.first_last_name).nil? || normalize(@person.first_last_name).empty?
54
+ end
55
+
56
+ def first_last_name_too_short_form
57
+ first_letter_of(@person.first_last_name) <<
58
+ first_letter_of(@person.second_last_name) <<
59
+ first_two_letters_of(filter_name(@person.name))
60
+ end
61
+
62
+ def first_two_letters_of(word)
63
+ normalized_word = normalize(word)
64
+ normalized_word[0..1]
65
+ end
66
+
67
+ def first_last_name_is_too_short?
68
+ normalize(@person.first_last_name).length <= 2
69
+ end
70
+
71
+ def normal_form
72
+ first_letter_of(@person.first_last_name) <<
73
+ first_vowel_excluding_first_character_of(@person.first_last_name) <<
74
+ first_letter_of(@person.second_last_name) <<
75
+ first_letter_of(filter_name(@person.name))
76
+ end
77
+
78
+ def filter_name(name)
79
+ raw_name = normalize(name).strip
80
+ if raw_name.include?(' ') && (raw_name.start_with?('MARIA', 'JOSE'))
81
+ return raw_name.split(' ')[1]
82
+ end
83
+ name
84
+ end
85
+
86
+ def formatted_in_two_digits(number)
87
+ format('%02d', number)
88
+ end
89
+
90
+ def last_two_digits_of(number)
91
+ formatted_in_two_digits(number % 100)
92
+ end
93
+
94
+ def first_letter_of(word)
95
+ normalized_word = normalize(word)
96
+ normalized_word[0]
97
+ end
98
+
99
+ def normalize(word)
100
+ return word if word.nil? || word.empty?
101
+ normalized_word = UnicodeUtils.upcase(I18n.transliterate(word))
102
+ remove_special_particles(normalized_word, SPECIAL_PARTICLES)
103
+ end
104
+
105
+ def remove_special_particles(word, special_particles)
106
+ new_word = word
107
+ special_particles.each do |particle|
108
+ pp = "#{particle} "
109
+ while new_word.include?(pp)
110
+ i = new_word.to_s.index(pp).to_i
111
+ new_word.slice!(i..i + pp.length - 1)
112
+ end
113
+ end
114
+ new_word.to_s
115
+ end
116
+
117
+ def first_vowel_excluding_first_character_of(word)
118
+ normalized_word = normalize(word)[1..-1]
119
+ m = VOWEL_PATTERN.match(normalized_word)
120
+ raise ArgumentError, "Word doesn't contain a vowel: #{normalized_word}" if m.nil?
121
+ normalized_word[m.to_s[0]]
122
+ end
123
+ end
124
+ end
@@ -1,22 +1,36 @@
1
- class Rfc
2
- attr_accessor :name, :first_last_name, :second_last_name, :day, :month, :year,
3
- :ten_digits_code, :homoclave, :verification_digit
1
+ module RfcFacil
2
+ class Rfc
3
+ attr_accessor :name, :first_last_name, :second_last_name, :day, :month, :year,
4
+ :ten_digits_code, :homoclave, :verification_digit, :legal_name
4
5
 
5
- def initialize(args)
6
- @name = args[:name]
7
- @first_last_name = args[:first_last_name]
8
- @second_last_name = args[:second_last_name]
9
- @day = args[:day]
10
- @month = args[:month]
11
- @year = args[:year]
6
+ def initialize(args)
7
+ @name = args[:name]
8
+ @first_last_name = args[:first_last_name]
9
+ @second_last_name = args[:second_last_name]
10
+ @day = args[:day]
11
+ @month = args[:month]
12
+ @year = args[:year]
13
+ @legal_name = args[:legal_name]
14
+ if @legal_name.nil?
15
+ build_natural_person
16
+ else
17
+ build_juristic_person
18
+ end
19
+ end
12
20
 
13
- @person = Person.new(@name, @first_last_name, @second_last_name, @day, @month, @year)
14
- @ten_digits_code = TenDigitsCodeCalculator.new(@person).calculate
15
- @homoclave = HomoclaveCalculator.new(@person).calculate
16
- @verification_digit = VerificationDigitCalculator.new("#{@ten_digits_code}#{@homoclave}").calculate
17
- end
21
+ def build_juristic_person
22
+
23
+ end
24
+
25
+ def build_natural_person
26
+ @person = NaturalPerson.new(@name, @first_last_name, @second_last_name, @day, @month, @year)
27
+ @ten_digits_code = NaturalTenDigitsCodeCalculator.new(@person).calculate
28
+ @homoclave = HomoclaveCalculator.new(@person).calculate
29
+ @verification_digit = VerificationDigitCalculator.new("#{@ten_digits_code}#{@homoclave}").calculate
30
+ end
18
31
 
19
- def to_s
20
- "#{@ten_digits_code}#{@homoclave}#{@verification_digit}"
32
+ def to_s
33
+ "#{@ten_digits_code}#{@homoclave}#{@verification_digit}"
34
+ end
21
35
  end
22
36
  end
@@ -1,32 +1,34 @@
1
- class VerificationDigitCalculator
2
- attr_accessor :rfc12_digits
3
- MAPPING = {
4
- '0' => 0, '1' => 1, '2' => 2, '3' => 3, '4' => 4, '5' => 5, '6' => 6,
5
- '7' => 7, '8' => 8, '9' => 9, 'A' => 10, 'B' => 11, 'C' => 12, 'D' => 13,
6
- 'E' => 14, 'F' => 15, 'G' => 16, 'H' => 17, 'I' => 18, 'J' => 19, 'K' => 20,
7
- 'L' => 21, 'M' => 22, 'N' => 23, '&' => 24, 'O' => 25, 'P' => 26, 'Q' => 27,
8
- 'R' => 28, 'S' => 29, 'T' => 30, 'U' => 31, 'V' => 32, 'W' => 33, 'X' => 34,
9
- 'Y' => 35, 'Z' => 36, ' ' => 37, 'Ñ' => 38
10
- }
1
+ module RfcFacil
2
+ class VerificationDigitCalculator
3
+ attr_accessor :rfc12_digits
4
+ MAPPING = {
5
+ '0' => 0, '1' => 1, '2' => 2, '3' => 3, '4' => 4, '5' => 5, '6' => 6,
6
+ '7' => 7, '8' => 8, '9' => 9, 'A' => 10, 'B' => 11, 'C' => 12, 'D' => 13,
7
+ 'E' => 14, 'F' => 15, 'G' => 16, 'H' => 17, 'I' => 18, 'J' => 19, 'K' => 20,
8
+ 'L' => 21, 'M' => 22, 'N' => 23, '&' => 24, 'O' => 25, 'P' => 26, 'Q' => 27,
9
+ 'R' => 28, 'S' => 29, 'T' => 30, 'U' => 31, 'V' => 32, 'W' => 33, 'X' => 34,
10
+ 'Y' => 35, 'Z' => 36, ' ' => 37, 'Ñ' => 38
11
+ }.freeze
11
12
 
12
- def initialize(rfc12_digits)
13
- @rfc12_digits = rfc12_digits
14
- end
15
-
16
- def calculate
17
- sum = 0
18
- (0..11).each do |i|
19
- sum += map_digit(@rfc12_digits[i]) * (13 - i)
13
+ def initialize(rfc12_digits)
14
+ @rfc12_digits = rfc12_digits
20
15
  end
21
- reminder = sum % 11
22
16
 
23
- return '0' if (reminder == 0)
24
- return 'A' if (reminder == 10)
25
- (11 - reminder).to_s
26
- end
17
+ def calculate
18
+ sum = 0
19
+ (0..11).each do |i|
20
+ sum += map_digit(@rfc12_digits[i]) * (13 - i)
21
+ end
22
+ reminder = sum % 11
27
23
 
28
- def map_digit(c)
29
- return MAPPING[c] if MAPPING.key?(c)
30
- 0
24
+ return '0' if reminder == 0
25
+ return 'A' if reminder == 10
26
+ (11 - reminder).to_s
27
+ end
28
+
29
+ def map_digit(c)
30
+ return MAPPING[c] if MAPPING.key?(c)
31
+ 0
32
+ end
31
33
  end
32
34
  end
@@ -1,3 +1,3 @@
1
1
  module RfcFacil
2
- VERSION = '0.1.1'
2
+ VERSION = '1.0.0'
3
3
  end
@@ -8,6 +8,7 @@ Gem::Specification.new do |spec|
8
8
  spec.version = RfcFacil::VERSION
9
9
  spec.authors = ['Adrian Rangel']
10
10
  spec.email = ['adrian.rangel@gmail.com']
11
+ spec.licenses = ['MIT']
11
12
 
12
13
  spec.summary = 'Libreria para calcular el Registro Federal de Contribuyentes en México (RFC).'
13
14
  spec.homepage = 'https://acrogenesis.com/rfc_facil/'
@@ -23,4 +24,5 @@ Gem::Specification.new do |spec|
23
24
  spec.add_development_dependency 'bundler', '~> 1.10'
24
25
  spec.add_development_dependency 'rake', '~> 10.0'
25
26
  spec.add_development_dependency 'minitest', '~> 5.8'
27
+ spec.add_development_dependency 'codeclimate-test-reporter', '~> 0.4'
26
28
  end
@@ -50,12 +50,12 @@ class TestHomoclaveCalculator < Minitest::Test
50
50
 
51
51
  def test_calculate_same_homoclave_for_different_birthdays
52
52
  assert_equal(
53
- HomoclaveCalculator.new(Person.new('Juan', 'Perez', 'Garcia', 5, 8, 1987)).calculate,
54
- HomoclaveCalculator.new(Person.new('Juan', 'Perez', 'Garcia', 1, 1, 1901)).calculate
53
+ RfcFacil::HomoclaveCalculator.new(RfcFacil::NaturalPerson.new('Juan', 'Perez', 'Garcia', 5, 8, 1987)).calculate,
54
+ RfcFacil::HomoclaveCalculator.new(RfcFacil::NaturalPerson.new('Juan', 'Perez', 'Garcia', 1, 1, 1901)).calculate
55
55
  )
56
56
  end
57
57
 
58
58
  def homoclave(name, firstLastName, secondLastName)
59
- HomoclaveCalculator.new(Person.new(name, firstLastName, secondLastName, 1, 1, 1901)).calculate
59
+ RfcFacil::HomoclaveCalculator.new(RfcFacil::NaturalPerson.new(name, firstLastName, secondLastName, 1, 1, 1901)).calculate
60
60
  end
61
61
  end
@@ -0,0 +1,17 @@
1
+ class TestJurisitcTenDigitsCodeCalculator < Minitest::Test
2
+ def should_take_first_letters_from_the_first_three_words_from_legal_name
3
+ assert_equal('MNE', ten_digits_code('Mu Networks S.A.P.I. de C.V.', 10, 07, 2014)[0, 3])
4
+ end
5
+
6
+ def should_take_creation_date_in_format_yy_mm_dd
7
+ assert_equal('MNE1407107', ten_digits_code('Mu Networks S.A.P.I. de C.V.', 10, 07, 2014))
8
+ end
9
+
10
+ private
11
+
12
+ def ten_digits_code(legal_name, day, month, year)
13
+ RfcFacil::JuristicTenDigitsCodeCalculator.new(
14
+ RfcFacil::JuristicPerson.new(legal_name, day, month, year)
15
+ ).calculate
16
+ end
17
+ end
@@ -1,4 +1,4 @@
1
- class TestTenDigitsCodeCalculator < Minitest::Test
1
+ class TestNaturalTenDigitsCodeCalculator < Minitest::Test
2
2
  def test_calculate_ten_digits_code_for_simple_test_case
3
3
  assert_equal('BAFJ701213', ten_digits_code('Juan', 'Barrios', 'Fernandez', 13, 12, 1970))
4
4
  end
@@ -72,8 +72,8 @@ class TestTenDigitsCodeCalculator < Minitest::Test
72
72
  private
73
73
 
74
74
  def ten_digits_code(name, first_last_name, second_last_name, day, month, year)
75
- TenDigitsCodeCalculator.new(
76
- Person.new(name, first_last_name, second_last_name, day, month, year)
75
+ RfcFacil::NaturalTenDigitsCodeCalculator.new(
76
+ RfcFacil::NaturalPerson.new(name, first_last_name, second_last_name, day, month, year)
77
77
  ).calculate
78
78
  end
79
79
  end
@@ -1,6 +1,6 @@
1
1
  class TestRfc < Minitest::Test
2
- def test_rfc
3
- rfc = Rfc.new(name: 'Adrian Marcelo', first_last_name: 'Rangel',
2
+ def test_rfc_for_a_natural_person
3
+ rfc = RfcFacil::Rfc.new(name: 'Adrian Marcelo', first_last_name: 'Rangel',
4
4
  second_last_name: 'Araujo', day: 27, month: 11, year: 1992)
5
5
 
6
6
  assert_equal('RAAA921127', rfc.ten_digits_code)
@@ -8,4 +8,13 @@ class TestRfc < Minitest::Test
8
8
  assert_equal('6', rfc.verification_digit)
9
9
  assert_equal('RAAA921127RI6', rfc.to_s)
10
10
  end
11
+
12
+ def test_rfc_for_a_juristic_person
13
+ _rfc = RfcFacil::Rfc.new(legal_name: 'Mu Networks S.A.P.I de C.V.', day: 10, month: 07, year: 2014)
14
+
15
+ # assertThat(rfc.tenDigitsCode, equalTo("SIA-821129"));
16
+ # assertThat(rfc.homoclave, equalTo("CK"));
17
+ # assertThat(rfc.verificationDigit, equalTo("6"));
18
+ # assertThat(rfc.toString(), equalTo("ZATJ870805CK6"));
19
+ end
11
20
  end
@@ -4,6 +4,6 @@ class VerificationDigitCalculatorTest < Minitest::Test
4
4
  end
5
5
 
6
6
  def verification_digit(rfc12Digit)
7
- VerificationDigitCalculator.new(rfc12Digit).calculate
7
+ RfcFacil::VerificationDigitCalculator.new(rfc12Digit).calculate
8
8
  end
9
9
  end
@@ -1,6 +1,9 @@
1
+ require "codeclimate-test-reporter"
2
+ CodeClimate::TestReporter.start
1
3
  require 'minitest/autorun'
2
4
  require_relative '../lib/rfc_facil'
3
5
  require 'rfc_facil/test_homoclave_calculator'
4
6
  require 'rfc_facil/test_rfc'
5
- require 'rfc_facil/test_ten_digits_code_calculator'
7
+ require 'rfc_facil/test_natural_ten_digits_code_calculator'
8
+ require 'rfc_facil/test_juristic_ten_digits_code_calculator'
6
9
  require 'rfc_facil/test_verification_digit_calculator'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rfc_facil
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adrian Rangel
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2015-10-12 00:00:00.000000000 Z
11
+ date: 2016-03-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: i18n
@@ -80,6 +80,20 @@ dependencies:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
82
  version: '5.8'
83
+ - !ruby/object:Gem::Dependency
84
+ name: codeclimate-test-reporter
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '0.4'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '0.4'
83
97
  description:
84
98
  email:
85
99
  - adrian.rangel@gmail.com
@@ -96,20 +110,24 @@ files:
96
110
  - bin/setup
97
111
  - lib/rfc_facil.rb
98
112
  - lib/rfc_facil/homoclave_calculator.rb
99
- - lib/rfc_facil/person.rb
113
+ - lib/rfc_facil/juristic_person.rb
114
+ - lib/rfc_facil/juristic_ten_digits_code_calculator.rb
115
+ - lib/rfc_facil/natural_person.rb
116
+ - lib/rfc_facil/natural_ten_digits_code_calculator.rb
100
117
  - lib/rfc_facil/rfc.rb
101
- - lib/rfc_facil/ten_digits_code_calculator.rb
102
118
  - lib/rfc_facil/verification_digit_calculator.rb
103
119
  - lib/rfc_facil/version.rb
104
120
  - logo.png
105
121
  - rfc_facil.gemspec
106
122
  - tests/rfc_facil/test_homoclave_calculator.rb
123
+ - tests/rfc_facil/test_juristic_ten_digits_code_calculator.rb
124
+ - tests/rfc_facil/test_natural_ten_digits_code_calculator.rb
107
125
  - tests/rfc_facil/test_rfc.rb
108
- - tests/rfc_facil/test_ten_digits_code_calculator.rb
109
126
  - tests/rfc_facil/test_verification_digit_calculator.rb
110
127
  - tests/tests_helper.rb
111
128
  homepage: https://acrogenesis.com/rfc_facil/
112
- licenses: []
129
+ licenses:
130
+ - MIT
113
131
  metadata: {}
114
132
  post_install_message:
115
133
  rdoc_options: []
@@ -127,7 +145,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
127
145
  version: '0'
128
146
  requirements: []
129
147
  rubyforge_project:
130
- rubygems_version: 2.4.8
148
+ rubygems_version: 2.5.1
131
149
  signing_key:
132
150
  specification_version: 4
133
151
  summary: Libreria para calcular el Registro Federal de Contribuyentes en México (RFC).
@@ -1,16 +0,0 @@
1
- class Person
2
- attr_accessor :name, :first_last_name, :second_last_name, :day, :month, :year
3
-
4
- def initialize(name, first_last_name, second_last_name, day, month, year)
5
- @name = name
6
- @first_last_name = first_last_name
7
- @second_last_name = second_last_name
8
- @day = day
9
- @month = month
10
- @year = year
11
- end
12
-
13
- def to_s
14
- "#{@first_last_name} #{@second_last_name} #{@name}"
15
- end
16
- end
@@ -1,122 +0,0 @@
1
- class TenDigitsCodeCalculator
2
- VOWEL_PATTERN = /[AEIOU]+/
3
- attr_accessor :person
4
- SPECIAL_PARTICLES = %w(DE LA LAS MC VON DEL LOS Y MAC VAN MI)
5
- FORBIDDEN_WORDS = %w(
6
- BUEI BUEY CACA CACO CAGA KOGE KAKA MAME KOJO KULO
7
- CAGO COGE COJE COJO FETO JOTO KACO KAGO MAMO MEAR MEON
8
- MION MOCO MULA PEDA PEDO PENE PUTA PUTO QULO RATA RUIN
9
- )
10
-
11
- def initialize(person)
12
- @person = person
13
- end
14
-
15
- def calculate
16
- "#{obfuscate_forbidden_words(name_code)}#{birthday_code}"
17
- end
18
-
19
- def obfuscate_forbidden_words(name_code)
20
- FORBIDDEN_WORDS.each do |forbidden|
21
- return "#{name_code[0..2]}X" if forbidden == name_code
22
- end
23
- name_code
24
- end
25
-
26
- def name_code
27
- return first_last_name_empty_form if first_last_name_empty?
28
- return second_last_name_empty_form if second_last_name_empty?
29
- return first_last_name_too_short_form if first_last_name_is_too_short?
30
- normal_form
31
- end
32
-
33
- def second_last_name_empty_form
34
- first_two_letters_of(@person.first_last_name) <<
35
- first_two_letters_of(filter_name(@person.name))
36
- end
37
-
38
- def birthday_code
39
- "#{@person.year.to_s[-2, 2]}#{format('%02d', @person.month)}#{format('%02d', @person.day)}"
40
- end
41
-
42
- def second_last_name_empty?
43
- normalize(@person.second_last_name).nil? || normalize(@person.second_last_name).empty?
44
- end
45
-
46
- def first_last_name_empty_form
47
- first_two_letters_of(@person.second_last_name) <<
48
- first_two_letters_of(filter_name(@person.name))
49
- end
50
-
51
- def first_last_name_empty?
52
- normalize(@person.first_last_name).nil? || normalize(@person.first_last_name).empty?
53
- end
54
-
55
- def first_last_name_too_short_form
56
- first_letter_of(@person.first_last_name) <<
57
- first_letter_of(@person.second_last_name) <<
58
- first_two_letters_of(filter_name(@person.name))
59
- end
60
-
61
- def first_two_letters_of(word)
62
- normalized_word = normalize(word)
63
- normalized_word[0..1]
64
- end
65
-
66
- def first_last_name_is_too_short?
67
- normalize(@person.first_last_name).length <= 2
68
- end
69
-
70
- def normal_form
71
- first_letter_of(@person.first_last_name) <<
72
- first_vowel_excluding_first_character_of(@person.first_last_name) <<
73
- first_letter_of(@person.second_last_name) <<
74
- first_letter_of(filter_name(@person.name))
75
- end
76
-
77
- def filter_name(name)
78
- raw_name = normalize(name).strip
79
- if raw_name.include?(' ') && (raw_name.start_with?('MARIA') || raw_name.start_with?('JOSE'))
80
- return raw_name.split(' ')[1]
81
- end
82
- name
83
- end
84
-
85
- def formatted_in_two_digits(number)
86
- format('%02d', number)
87
- end
88
-
89
- def last_two_digits_of(number)
90
- formatted_in_two_digits(number % 100)
91
- end
92
-
93
- def first_letter_of(word)
94
- normalized_word = normalize(word)
95
- normalized_word[0]
96
- end
97
-
98
- def normalize(word)
99
- return word if word.nil? || word.empty?
100
- normalized_word = UnicodeUtils.upcase(I18n.transliterate(word))
101
- remove_special_particles(normalized_word, SPECIAL_PARTICLES)
102
- end
103
-
104
- def remove_special_particles(word, special_particles)
105
- new_word = word
106
- special_particles.each do |particle|
107
- pp = "#{particle} "
108
- while new_word.include?(pp)
109
- i = new_word.to_s.index(pp).to_i
110
- new_word.slice!(i..i + pp.length - 1)
111
- end
112
- end
113
- new_word.to_s
114
- end
115
-
116
- def first_vowel_excluding_first_character_of(word)
117
- normalized_word = normalize(word)[1..-1]
118
- m = VOWEL_PATTERN.match(normalized_word)
119
- fail ArgumentError, "Word doesn't contain a vowel: #{normalized_word}" if m.nil?
120
- normalized_word[m.to_s[0]]
121
- end
122
- end