codice-fiscale 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- 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
|