codice-fiscale 0.0.4 → 0.0.5
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.
- data/README.md +3 -2
- data/lib/codice_fiscale.rb +20 -9
- data/lib/codice_fiscale/alphabet.rb +3 -3
- data/lib/codice_fiscale/codes.rb +22 -12
- data/lib/codice_fiscale/version.rb +1 -1
- data/spec/lib/codice_fiscale_spec.rb +36 -4
- metadata +1 -1
data/README.md
CHANGED
@@ -11,7 +11,7 @@ gender, birthdate and the birthplace. Read more on [wikipedia](http://en.wikiped
|
|
11
11
|
```ruby
|
12
12
|
require 'codice_fiscale'
|
13
13
|
|
14
|
-
CodiceFiscale.calculate '
|
14
|
+
CodiceFiscale.calculate :name => 'Mario', :surname => 'Rossi', :gender => :male, :birthdate => Date.new(1987, 1, 1), :province_code => 'LC', :city_name => 'Abbadia Lariana'
|
15
15
|
|
16
16
|
# RSSMRA87A01A005V
|
17
17
|
```
|
@@ -22,8 +22,9 @@ If a person was born outside Italy, only the italian name of the county is requi
|
|
22
22
|
For example, an italian citizen born in France:
|
23
23
|
|
24
24
|
```ruby
|
25
|
-
CodiceFiscale.calculate '
|
25
|
+
CodiceFiscale.calculate :name => 'Mario', :surname => 'Rossi', :gender => :male, :birthdate => Date.new(1987, 1, 1), :country_name => 'Francia'
|
26
26
|
```
|
27
|
+
|
27
28
|
If a person was born in Italy you have to specify the *code* of the province and the *name* of the city. These informations are actually contained in an XLS
|
28
29
|
document downloaded from [agenziaterritorio.it](http://www.agenziaterritorio.it/?id=721), converted to CSV and shipped with this gem.
|
29
30
|
|
data/lib/codice_fiscale.rb
CHANGED
@@ -9,20 +9,31 @@ require 'codice_fiscale/configuration'
|
|
9
9
|
module CodiceFiscale
|
10
10
|
extend self
|
11
11
|
|
12
|
-
def calculate
|
13
|
-
|
14
|
-
|
15
|
-
|
12
|
+
def calculate params
|
13
|
+
validate_calculate_params params
|
14
|
+
code = birthplace_part (params[:country_name] || Codes::ITALY), params[:city_name], params[:province_code]
|
15
|
+
raise "Missing city/country code. Mispelled?" unless code
|
16
|
+
code = surname_part(params[:surname]) + name_part(params[:name]) + birthdate_part(params[:birthdate], params[:gender]) + code
|
16
17
|
code + check_character(code)
|
17
18
|
end
|
18
19
|
|
20
|
+
def validate_calculate_params params
|
21
|
+
[:name, :surname, :gender, :birthdate].each do |param_name|
|
22
|
+
raise "Missing #{param_name} parameter" unless params[param_name]
|
23
|
+
end
|
24
|
+
raise "Invalid birthdate: #{params[:birthdate]}" unless params[:birthdate].respond_to? :year
|
25
|
+
unless Codes::GENDERS.include? params[:gender]
|
26
|
+
raise "Invalid gender. Possible values are #{Codes::GENDERS}"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
19
30
|
|
20
31
|
# Methods to generate each part of the code
|
21
32
|
|
22
33
|
def surname_part surname
|
23
34
|
surname.upcase!
|
24
35
|
code = first_three_consonants surname
|
25
|
-
code <<
|
36
|
+
code << first_three_vowels(surname)
|
26
37
|
truncate_and_right_pad_with_three_x code
|
27
38
|
end
|
28
39
|
|
@@ -31,7 +42,7 @@ module CodiceFiscale
|
|
31
42
|
consonants_of_name = consonants name
|
32
43
|
return consonants_of_name[0]+consonants_of_name[2..3] if consonants_of_name.size >= 4
|
33
44
|
code = first_three_consonants name
|
34
|
-
code <<
|
45
|
+
code << first_three_vowels(name)
|
35
46
|
truncate_and_right_pad_with_three_x code
|
36
47
|
end
|
37
48
|
|
@@ -53,7 +64,7 @@ module CodiceFiscale
|
|
53
64
|
end
|
54
65
|
|
55
66
|
def birthplace_part country_name, city_name = nil, province_code = nil
|
56
|
-
if
|
67
|
+
if Codes.italy? country_name
|
57
68
|
city_code city_name, province_code
|
58
69
|
else
|
59
70
|
country_code country_name
|
@@ -87,8 +98,8 @@ module CodiceFiscale
|
|
87
98
|
intersects(string, Alphabet.consonants)[0..2]
|
88
99
|
end
|
89
100
|
|
90
|
-
def
|
91
|
-
intersects(string, Alphabet.
|
101
|
+
def first_three_vowels string
|
102
|
+
intersects(string, Alphabet.vowels)[0..2]
|
92
103
|
end
|
93
104
|
|
94
105
|
def truncate_and_right_pad_with_three_x string
|
@@ -2,16 +2,16 @@ module CodiceFiscale
|
|
2
2
|
module Alphabet
|
3
3
|
extend self
|
4
4
|
|
5
|
-
def
|
5
|
+
def vowels
|
6
6
|
%w[A E I O U]
|
7
7
|
end
|
8
8
|
|
9
9
|
def consonants
|
10
|
-
letters -
|
10
|
+
letters - vowels
|
11
11
|
end
|
12
12
|
|
13
13
|
def letters
|
14
|
-
|
14
|
+
('A'..'Z').to_a
|
15
15
|
end
|
16
16
|
end
|
17
17
|
end
|
data/lib/codice_fiscale/codes.rb
CHANGED
@@ -2,13 +2,26 @@ module CodiceFiscale
|
|
2
2
|
module Codes
|
3
3
|
extend self
|
4
4
|
|
5
|
+
ITALY = 'Italia'
|
6
|
+
|
7
|
+
MONTH_CODES = %w[A B C D E H L M P R S T]
|
8
|
+
|
9
|
+
ODD_CODES = {'0' => 1, '1' => 0, '2' => 5, '3' => 7, '4' => 9, '5' => 13, '6' => 15, '7' => 17, '8' => 19, '9' => 21, 'A' => 1, 'B' => 0,
|
10
|
+
'C' => 5, 'D' => 7, 'E' => 9, 'F' => 13, 'G' => 15, 'H' => 17, 'I' => 19, 'J' => 21, 'K' => 2, 'L' => 4, 'M' => 18, 'N' => 20,
|
11
|
+
'O' => 11, 'P' => 3, 'Q' => 6, 'R' => 8, 'S' => 12, 'T' => 14, 'U' => 16, 'V' => 10, 'W' => 22, 'X' => 25, 'Y' => 24, 'Z' => 23}
|
12
|
+
|
13
|
+
EVEN_CODES = {'0' => 0, '1' => 1, '2' => 2, '3' => 3, '4' => 4, '5' => 5, '6' => 6, '7' => 7, '8' => 8, '9' => 9, 'A' => 0, 'B' => 1,
|
14
|
+
'C' => 2, 'D' => 3, 'E' => 4, 'F' => 5, 'G' => 6, 'H' => 7, 'I' => 8, 'J' => 9, 'K' => 10, 'L' => 11, 'M' => 12, 'N' => 13,
|
15
|
+
'O' => 14, 'P' => 15, 'Q' => 16, 'R' => 17, 'S' => 18, 'T' => 19, 'U' => 20, 'V' => 21, 'W' => 22, 'X' => 23, 'Y' => 24, 'Z' => 25}
|
16
|
+
|
17
|
+
GENDERS = [:male, :female]
|
18
|
+
|
5
19
|
def config
|
6
20
|
CodiceFiscale.config
|
7
21
|
end
|
8
22
|
|
9
23
|
def month_letter month_number
|
10
|
-
|
11
|
-
month_number <= 0 ? nil : decode[month_number-1]
|
24
|
+
month_number <= 0 ? nil : MONTH_CODES[month_number-1]
|
12
25
|
end
|
13
26
|
|
14
27
|
def city city_name, province_code
|
@@ -28,22 +41,19 @@ module CodiceFiscale
|
|
28
41
|
end
|
29
42
|
|
30
43
|
def odd_character character
|
31
|
-
|
32
|
-
'C' => 5, 'D' => 7, 'E' => 9, 'F' => 13, 'G' => 15, 'H' => 17, 'I' => 19, 'J' => 21, 'K' => 2, 'L' => 4, 'M' => 18, 'N' => 20,
|
33
|
-
'O' => 11, 'P' => 3, 'Q' => 6, 'R' => 8, 'S' => 12, 'T' => 14, 'U' => 16, 'V' => 10, 'W' => 22, 'X' => 25, 'Y' => 24, 'Z' => 23}
|
34
|
-
decode[character.upcase]
|
44
|
+
ODD_CODES[character.upcase]
|
35
45
|
end
|
36
46
|
|
37
47
|
def even_character character
|
38
|
-
|
39
|
-
'C' => 2, 'D' => 3, 'E' => 4, 'F' => 5, 'G' => 6, 'H' => 7, 'I' => 8, 'J' => 9, 'K' => 10, 'L' => 11, 'M' => 12, 'N' => 13,
|
40
|
-
'O' => 14, 'P' => 15, 'Q' => 16, 'R' => 17, 'S' => 18, 'T' => 19, 'U' => 20, 'V' => 21, 'W' => 22, 'X' => 23, 'Y' => 24, 'Z' => 25}
|
41
|
-
decode[character.upcase]
|
48
|
+
EVEN_CODES[character.upcase]
|
42
49
|
end
|
43
50
|
|
44
51
|
def check_character number
|
45
|
-
|
46
|
-
|
52
|
+
Alphabet.letters[number]
|
53
|
+
end
|
54
|
+
|
55
|
+
def italy? country_name
|
56
|
+
ITALY.casecmp(country_name.strip) == 0
|
47
57
|
end
|
48
58
|
end
|
49
59
|
end
|
@@ -168,15 +168,47 @@ describe CodiceFiscale do
|
|
168
168
|
describe '#calculate' do
|
169
169
|
context 'italian citizen' do
|
170
170
|
it 'return the expected code' do
|
171
|
-
params =
|
172
|
-
|
171
|
+
params = {:name => 'mario', :surname => 'rossi', :gender => :male, :birthdate => Date.new(1987, 1, 1),
|
172
|
+
:province_code => 'lc', :city_name => 'Abbadia Lariana'}
|
173
|
+
subject.calculate(params).should == 'RSSMRA87A01A005V'
|
173
174
|
end
|
174
175
|
end
|
175
176
|
|
176
177
|
context 'return the expected code' do
|
177
178
|
it 'work' do
|
178
|
-
params =
|
179
|
-
subject.calculate(
|
179
|
+
params = {:name => 'mario', :surname => 'rossi', :gender => :male, :birthdate => Date.new(1987, 1, 1), :country_name => 'Albania'}
|
180
|
+
subject.calculate(params).should == 'RSSMRA87A01Z100H'
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
describe '#validate_calculate_params' do
|
186
|
+
let(:mandatory_params) { {:name => 'mario', :surname => 'rossi', :gender => :male, :birthdate => Date.new(1987, 1, 1)} }
|
187
|
+
|
188
|
+
context 'All mandatory params are correct' do
|
189
|
+
it 'do not raise any arror' do
|
190
|
+
lambda { subject.validate_calculate_params(mandatory_params) }.should_not raise_error
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
context 'A mandatory parameter is missing' do
|
195
|
+
it 'raise an error' do
|
196
|
+
without_name = mandatory_params.reject {|p| p == :name }
|
197
|
+
lambda { subject.validate_calculate_params(without_name) }.should raise_error
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
context 'Gender is invalid' do
|
202
|
+
it 'raise an error' do
|
203
|
+
params = mandatory_params.merge :gender => :lol
|
204
|
+
lambda { subject.validate_calculate_params(params) }.should raise_error
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
context 'Birthdate is invalid' do
|
209
|
+
it 'raise an error' do
|
210
|
+
params = mandatory_params.merge :birthdate => '2000/01/01'
|
211
|
+
lambda { subject.validate_calculate_params(params) }.should raise_error
|
180
212
|
end
|
181
213
|
end
|
182
214
|
end
|