tin_valid 0.1.1 → 1.1.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 +4 -4
- data/.rspec +0 -1
- data/.rubocop.yml +5 -0
- data/CHANGELOG.md +27 -1
- data/README.md +81 -2
- data/lib/tin_valid/austria_tin.rb +1 -0
- data/lib/tin_valid/belgium_tin.rb +11 -15
- data/lib/tin_valid/bulgaria_tin.rb +10 -16
- data/lib/tin_valid/croatia_tin.rb +7 -1
- data/lib/tin_valid/cyprus_tin.rb +5 -2
- data/lib/tin_valid/czechia_tin.rb +24 -23
- data/lib/tin_valid/denmark_tin.rb +10 -8
- data/lib/tin_valid/estonia_tin.rb +7 -8
- data/lib/tin_valid/finland_tin.rb +71 -0
- data/lib/tin_valid/france_tin.rb +28 -0
- data/lib/tin_valid/germany_tin.rb +16 -5
- data/lib/tin_valid/greece_tin.rb +10 -2
- data/lib/tin_valid/helpers.rb +14 -0
- data/lib/tin_valid/hungary_tin.rb +7 -3
- data/lib/tin_valid/ireland_tin.rb +7 -1
- data/lib/tin_valid/italy_tin.rb +161 -0
- data/lib/tin_valid/latvia_tin.rb +63 -0
- data/lib/tin_valid/lithuania_tin.rb +75 -0
- data/lib/tin_valid/luxembourg_tin.rb +106 -0
- data/lib/tin_valid/malta_tin.rb +51 -0
- data/lib/tin_valid/netherlands_tin.rb +36 -0
- data/lib/tin_valid/poland_tin.rb +79 -0
- data/lib/tin_valid/portugal_tin.rb +46 -0
- data/lib/tin_valid/romania_tin.rb +83 -0
- data/lib/tin_valid/slovakia_tin.rb +67 -0
- data/lib/tin_valid/slovenia_tin.rb +38 -0
- data/lib/tin_valid/spain_tin.rb +51 -0
- data/lib/tin_valid/sweden_tin.rb +7 -9
- data/lib/tin_valid/united_kingdom_tin.rb +32 -0
- data/lib/tin_valid/version.rb +1 -1
- data/lib/tin_valid.rb +16 -0
- metadata +18 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2a4dc099cefbd5653c35bb0a8d78061e7e9239a917f2f872e7036651c429c014
|
4
|
+
data.tar.gz: c540ebe0de3b7f4c69c65c2d05b0d2d67b1beca905e4ee2e99416b361d4991c9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d34baae639710a1f82adc36eedce1bb6b961e7fbe3f2128d091b5c61f6956276dc047207d62ac46325577028e5db562a955a4603056d0096469ce48e7698adbf
|
7
|
+
data.tar.gz: 97e1d3b264372400e0575a30d15087d53bb3220c49e2126a5aa24417407b806e8018e4bf26cef7e7ff8a1d749e74c907801a8b3e2ae52ddae85008394682ba28
|
data/.rspec
CHANGED
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,32 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [1.1.0] - 2025-04-18
|
4
|
+
|
5
|
+
Features:
|
6
|
+
- Add Finland 🇫🇮
|
7
|
+
- Add France 🇫🇷
|
8
|
+
|
9
|
+
Fixes:
|
10
|
+
- Test against clearly invalid codes 00000… and 123456…
|
11
|
+
- Check that all dates are in the past
|
12
|
+
|
13
|
+
## [1.0.0] - 2025-04-17
|
14
|
+
|
15
|
+
Features:
|
16
|
+
- Add Italy 🇮🇹
|
17
|
+
- Add Latvia 🇱🇻
|
18
|
+
- Add Luxembourg 🇱🇺
|
19
|
+
- Add Lithuania 🇱🇹
|
20
|
+
- Add Malta 🇲🇹
|
21
|
+
- Add Netherlands 🇳🇱
|
22
|
+
- Add Poland 🇵🇱
|
23
|
+
- Add Portugal 🇵🇹
|
24
|
+
- Add Romania 🇷🇴
|
25
|
+
- Add Slovakia 🇸🇰
|
26
|
+
- Add Slovenia 🇸🇮
|
27
|
+
- Add Spain 🇪🇸
|
28
|
+
- Add United Kingdom 🇬🇧
|
29
|
+
|
3
30
|
## [0.1.1] - 2025-04-15
|
4
31
|
|
5
32
|
Features:
|
@@ -7,7 +34,6 @@ Features:
|
|
7
34
|
- Add Greece 🇬🇷
|
8
35
|
- Add Hungary 🇭🇺
|
9
36
|
- Add Ireland 🇮🇪
|
10
|
-
- Add #normalized to Austria 🇦🇹
|
11
37
|
|
12
38
|
## [0.1.0] - 2025-04-14
|
13
39
|
|
data/README.md
CHANGED
@@ -10,11 +10,26 @@ Validate Tax Identification Numbers (TINs) for the following European countries:
|
|
10
10
|
- Czechia 🇨🇿
|
11
11
|
- Denmark 🇩🇰
|
12
12
|
- Estonia 🇪🇪
|
13
|
+
- Finland 🇫🇮
|
14
|
+
- France 🇫🇷
|
13
15
|
- Germany 🇩🇪
|
14
16
|
- Greece 🇬🇷
|
15
17
|
- Hungary 🇭🇺
|
16
18
|
- Ireland 🇮🇪
|
19
|
+
- Italy 🇮🇹
|
20
|
+
- Latvia 🇱🇻
|
21
|
+
- Lithuania 🇱🇹
|
22
|
+
- Luxembourg 🇱🇺
|
23
|
+
- Malta 🇲🇹
|
24
|
+
- Netherlands 🇳🇱
|
25
|
+
- Poland 🇵🇱
|
26
|
+
- Portugal 🇵🇹
|
27
|
+
- Romania 🇷🇴
|
28
|
+
- Slovakia 🇸🇰
|
29
|
+
- Slovenia 🇸🇮
|
30
|
+
- Spain 🇪🇸
|
17
31
|
- Sweden 🇸🇪
|
32
|
+
- United Kingdom 🇬🇧
|
18
33
|
|
19
34
|
See also the [descriptions of the structure provided by the European
|
20
35
|
Union](https://taxation-customs.ec.europa.eu/online-services/online-services-and-databases-taxation/taxpayer-identification-number-tin_en).
|
@@ -38,8 +53,7 @@ gem install tin_valid
|
|
38
53
|
|
39
54
|
```rb
|
40
55
|
# Austria
|
41
|
-
TinValid::AustriaTin.new(tin: "
|
42
|
-
TinValid::AustriaTin.new(tin: "93-173/6581").normalized # => "931736581"
|
56
|
+
TinValid::AustriaTin.new(tin: "…").valid? # => true
|
43
57
|
|
44
58
|
# Belgium
|
45
59
|
# Optional birth_date
|
@@ -68,9 +82,74 @@ TinValid::DenmarkTin.new(tin: "…", birth_date: Date.new(…)).valid?
|
|
68
82
|
# Optional birth_date
|
69
83
|
TinValid::EstoniaTin.new(tin: "…", birth_date: Date.new(…)).valid?
|
70
84
|
|
85
|
+
# Finland
|
86
|
+
# Optional birth_date
|
87
|
+
TinValid::FinlandTin.new(tin: "…", birth_date: Date.new(…)).valid?
|
88
|
+
|
89
|
+
# France
|
90
|
+
TinValid::FranceTin.new(tin: "…").valid?
|
91
|
+
|
92
|
+
# Germany
|
93
|
+
TinValid::GermanyTin.new(tin: "…").valid?
|
94
|
+
|
95
|
+
# Greece
|
96
|
+
TinValid::GreeceTin.new(tin: "…").valid?
|
97
|
+
|
98
|
+
# Hungary
|
99
|
+
TinValid::HungaryTin.new(tin: "…").valid?
|
100
|
+
|
101
|
+
# Ireland
|
102
|
+
TinValid::IrelandTin.new(tin: "…").valid?
|
103
|
+
|
104
|
+
# Italy
|
105
|
+
# Optional birth_date
|
106
|
+
TinValid::ItalyTin.new(tin: "…", birth_date: Date.new(…)).valid?
|
107
|
+
|
108
|
+
# Latvia
|
109
|
+
# Optional birth_date
|
110
|
+
TinValid::LatviaTin.new(tin: "…", birth_date: Date.new(…)).valid?
|
111
|
+
|
112
|
+
# Lithuania
|
113
|
+
# Optional birth_date
|
114
|
+
TinValid::LithuaniaTin.new(tin: "…", birth_date: Date.new(…)).valid?
|
115
|
+
|
116
|
+
# Luxembourg
|
117
|
+
# Optional birth_date
|
118
|
+
TinValid::LuxembourgTin.new(tin: "…", birth_date: Date.new(…)).valid?
|
119
|
+
|
120
|
+
# Malta
|
121
|
+
TinValid::MaltaTin.new(tin: "…").valid?
|
122
|
+
|
123
|
+
# Netherlands
|
124
|
+
TinValid::NetherlandsTin.new(tin: "…").valid?
|
125
|
+
|
126
|
+
# Poland
|
127
|
+
# Optional birth_date
|
128
|
+
TinValid::PolandTin.new(tin: "…", birth_date: Date.new(…)).valid?
|
129
|
+
|
130
|
+
# Portugal
|
131
|
+
TinValid::PortugalTin.new(tin: "…").valid?
|
132
|
+
|
133
|
+
# Romania
|
134
|
+
# Optional birth_date
|
135
|
+
TinValid::RomaniaTin.new(tin: "…", birth_date: Date.new(…)).valid?
|
136
|
+
|
137
|
+
# Slovakia
|
138
|
+
# Optional birth_date
|
139
|
+
TinValid::SlovakiaTin.new(tin: "…", birth_date: Date.new(…)).valid?
|
140
|
+
|
141
|
+
# Slovenia
|
142
|
+
TinValid::SloveniaTin.new(tin: "…").valid?
|
143
|
+
|
144
|
+
# Spain
|
145
|
+
TinValid::SpainTin.new(tin: "…").valid?
|
146
|
+
|
71
147
|
# Sweden
|
72
148
|
# Optional birth_date
|
73
149
|
TinValid::SwedenTin.new(tin: "…", birth_date: Date.new(…)).valid?
|
150
|
+
|
151
|
+
# United Kingdom
|
152
|
+
TinValid::UnitedKingdomTin.new(tin: "…").valid?
|
74
153
|
```
|
75
154
|
|
76
155
|
## Development
|
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
module TinValid
|
4
4
|
class BelgiumTin
|
5
|
+
include TinValid::Helpers
|
6
|
+
|
5
7
|
def initialize(tin:, birth_date: nil)
|
6
8
|
@tin = tin
|
7
9
|
@birth_date = birth_date
|
@@ -37,6 +39,15 @@ module TinValid
|
|
37
39
|
def check = match[:check].to_i
|
38
40
|
|
39
41
|
def valid_check?(year, month, day, number)
|
42
|
+
# A month (in the range 00...12, 00 is acceptable for person not born in
|
43
|
+
# Belgium and with an uncertain date of birth).
|
44
|
+
month = 1 if month == "00"
|
45
|
+
|
46
|
+
# A day of month (in the range 00...31 depending on month and year, 00 is
|
47
|
+
# acceptable for person not born in Belgium and with an uncertain date of
|
48
|
+
# birth).
|
49
|
+
day = 1 if day == "00"
|
50
|
+
|
40
51
|
tin_date = date(year, month, day)
|
41
52
|
return false if tin_date.nil?
|
42
53
|
return false if birth_date && birth_date != tin_date
|
@@ -54,20 +65,5 @@ module TinValid
|
|
54
65
|
#
|
55
66
|
# 2. 97 - remainder of the previous division is the check number
|
56
67
|
def digit_check(number) = 97 - (number.to_i % 97)
|
57
|
-
|
58
|
-
def date(year, month, day)
|
59
|
-
# A month (in the range 00...12, 00 is acceptable for person not born in
|
60
|
-
# Belgium and with an uncertain date of birth).
|
61
|
-
month = 1 if month == "00"
|
62
|
-
|
63
|
-
# A day of month (in the range 00...31 depending on month and year, 00 is
|
64
|
-
# acceptable for person not born in Belgium and with an uncertain date of
|
65
|
-
# birth).
|
66
|
-
day = 1 if day == "00"
|
67
|
-
|
68
|
-
Date.new(year.to_i, month.to_i, day.to_i)
|
69
|
-
rescue Date::Error
|
70
|
-
nil
|
71
|
-
end
|
72
68
|
end
|
73
69
|
end
|
@@ -1,11 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module TinValid
|
4
|
-
class BulgariaTin
|
4
|
+
class BulgariaTin
|
5
|
+
include TinValid::Helpers
|
6
|
+
|
5
7
|
def initialize(tin:, birth_date: nil)
|
6
|
-
|
8
|
+
@tin = tin
|
9
|
+
@birth_date = birth_date
|
7
10
|
end
|
8
11
|
|
12
|
+
attr_reader :tin, :birth_date
|
13
|
+
|
9
14
|
def valid?
|
10
15
|
match = MATCHER.match(tin)
|
11
16
|
return false unless match
|
@@ -37,9 +42,9 @@ module TinValid
|
|
37
42
|
day = day.to_i
|
38
43
|
|
39
44
|
if birth_date.nil?
|
40
|
-
|
41
|
-
|
42
|
-
|
45
|
+
date("18#{year}", month - 20, day) ||
|
46
|
+
date("19#{year}", month, day) ||
|
47
|
+
date("20#{year}", month - 40, day)
|
43
48
|
elsif birth_year < 1900
|
44
49
|
birth_date == date("18#{year}", month - 20, day)
|
45
50
|
elsif birth_year < 2000
|
@@ -53,17 +58,6 @@ module TinValid
|
|
53
58
|
|
54
59
|
def birth_year = birth_date.year
|
55
60
|
|
56
|
-
def past_date?(year, month, day)
|
57
|
-
found_date = date(year, month, day)
|
58
|
-
found_date && found_date < Date.today
|
59
|
-
end
|
60
|
-
|
61
|
-
def date(year, month, day)
|
62
|
-
Date.new(year.to_i, month.to_i, day.to_i)
|
63
|
-
rescue Date::Error
|
64
|
-
nil
|
65
|
-
end
|
66
|
-
|
67
61
|
def check
|
68
62
|
weights = [2, 4, 8, 5, 10, 9, 7, 3, 6]
|
69
63
|
|
data/lib/tin_valid/cyprus_tin.rb
CHANGED
@@ -1,11 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module TinValid
|
4
|
-
class CyprusTin
|
4
|
+
class CyprusTin
|
5
5
|
def initialize(tin:, kind: nil)
|
6
|
-
|
6
|
+
@tin = tin
|
7
|
+
@kind = kind
|
7
8
|
end
|
8
9
|
|
10
|
+
attr_reader :tin, :kind
|
11
|
+
|
9
12
|
def valid?
|
10
13
|
matcher.match?(tin) && check == tin[-1]
|
11
14
|
end
|
@@ -1,11 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module TinValid
|
4
|
-
class CzechiaTin
|
4
|
+
class CzechiaTin
|
5
|
+
include TinValid::Helpers
|
6
|
+
|
5
7
|
def initialize(tin:, birth_date: nil)
|
6
|
-
|
8
|
+
@tin = tin
|
9
|
+
@birth_date = birth_date
|
7
10
|
end
|
8
11
|
|
12
|
+
attr_reader :tin, :birth_date
|
13
|
+
|
9
14
|
def valid? = valid_v1? || valid_v2?
|
10
15
|
|
11
16
|
private
|
@@ -33,6 +38,7 @@ module TinValid
|
|
33
38
|
def valid_v1?
|
34
39
|
match = MATCHER_V1.match(tin)
|
35
40
|
return false unless match
|
41
|
+
return false if tin == "000000000"
|
36
42
|
return true if birth_date.nil?
|
37
43
|
return false if year_of_birth >= 1954
|
38
44
|
|
@@ -46,11 +52,10 @@ module TinValid
|
|
46
52
|
birth_date == date(year, month, match[:day])
|
47
53
|
end
|
48
54
|
|
49
|
-
# rubocop:disable Metrics/AbcSize
|
50
|
-
# rubocop:disable Metrics/MethodLength
|
51
55
|
def valid_v2?
|
52
56
|
match = MATCHER_V2.match(tin)
|
53
57
|
return false unless match
|
58
|
+
return false if tin == "0000000000"
|
54
59
|
return true if birth_date.nil?
|
55
60
|
return false if year_of_birth < 1954
|
56
61
|
|
@@ -59,30 +64,26 @@ module TinValid
|
|
59
64
|
# 54 - 99 for people born between 1954 and 1999.
|
60
65
|
year = "#{birth_century}#{match[:year]}"
|
61
66
|
|
62
|
-
|
63
|
-
# 21…32 only for men) or month + 50 (in the range 51...62 only for women)
|
64
|
-
# or month + 70 (in the range 71…82 only for women).
|
65
|
-
month = match[:month].to_i
|
66
|
-
if month > 70
|
67
|
-
month -= 70
|
68
|
-
elsif month > 50
|
69
|
-
month -= 50
|
70
|
-
elsif month > 20
|
71
|
-
month -= 20
|
72
|
-
end
|
73
|
-
|
74
|
-
birth_date == date(year, month, match[:day])
|
67
|
+
birth_date == date(year, month_integer(match[:month]), match[:day])
|
75
68
|
end
|
76
|
-
# rubocop:enable Metrics/AbcSize
|
77
|
-
# rubocop:enable Metrics/MethodLength
|
78
69
|
|
79
70
|
def year_of_birth = birth_date&.year
|
80
71
|
def birth_century = birth_date.strftime("%Y")[..1]
|
81
72
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
73
|
+
# Month (in the range 1...12 only for men) or month + 20 (in the range
|
74
|
+
# 21…32 only for men) or month + 50 (in the range 51...62 only for women)
|
75
|
+
# or month + 70 (in the range 71…82 only for women).
|
76
|
+
def month_integer(number)
|
77
|
+
number = number.to_i
|
78
|
+
if number > 70
|
79
|
+
number - 70
|
80
|
+
elsif number > 50
|
81
|
+
number - 50
|
82
|
+
elsif number > 20
|
83
|
+
number - 20
|
84
|
+
else
|
85
|
+
number
|
86
|
+
end
|
86
87
|
end
|
87
88
|
end
|
88
89
|
end
|
@@ -1,14 +1,21 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module TinValid
|
4
|
-
class DenmarkTin
|
4
|
+
class DenmarkTin
|
5
|
+
include TinValid::Helpers
|
6
|
+
|
5
7
|
def initialize(tin:, birth_date: nil)
|
6
|
-
|
8
|
+
@tin = tin
|
9
|
+
@birth_date = birth_date
|
7
10
|
end
|
8
11
|
|
12
|
+
attr_reader :tin, :birth_date
|
13
|
+
|
14
|
+
# rubocop:disable Metrics/AbcSize
|
9
15
|
def valid?
|
10
16
|
match = MATCHER.match(tin)
|
11
17
|
return false unless match
|
18
|
+
return false if tin == "0000000000"
|
12
19
|
|
13
20
|
if birth_date
|
14
21
|
year = "#{birth_century}#{match[:year]}"
|
@@ -19,6 +26,7 @@ module TinValid
|
|
19
26
|
|
20
27
|
match[:check].to_i == checksum
|
21
28
|
end
|
29
|
+
# rubocop:enable Metrics/AbcSize
|
22
30
|
|
23
31
|
private
|
24
32
|
|
@@ -38,12 +46,6 @@ module TinValid
|
|
38
46
|
def birth_century = birth_date.strftime("%Y")[..1]
|
39
47
|
def birth_year = birth_date.year
|
40
48
|
|
41
|
-
def date(year, month, day)
|
42
|
-
Date.new(year.to_i, month.to_i, day.to_i)
|
43
|
-
rescue Date::Error
|
44
|
-
nil
|
45
|
-
end
|
46
|
-
|
47
49
|
def checksum
|
48
50
|
# 1. Multiply the values of each position by the corresponding weight:
|
49
51
|
weights =
|
@@ -1,11 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module TinValid
|
4
|
-
class EstoniaTin
|
4
|
+
class EstoniaTin
|
5
|
+
include TinValid::Helpers
|
6
|
+
|
5
7
|
def initialize(tin:, birth_date: nil)
|
6
|
-
|
8
|
+
@tin = tin
|
9
|
+
@birth_date = birth_date
|
7
10
|
end
|
8
11
|
|
12
|
+
attr_reader :tin, :birth_date
|
13
|
+
|
9
14
|
def valid?
|
10
15
|
match = MATCHER.match(tin)
|
11
16
|
return false unless match
|
@@ -36,12 +41,6 @@ module TinValid
|
|
36
41
|
def birth_century = birth_date.strftime("%Y")[..1]
|
37
42
|
def birth_year = birth_date.year
|
38
43
|
|
39
|
-
def date(year, month, day)
|
40
|
-
Date.new(year.to_i, month.to_i, day.to_i)
|
41
|
-
rescue Date::Error
|
42
|
-
nil
|
43
|
-
end
|
44
|
-
|
45
44
|
def checksum
|
46
45
|
# 1. Multiply the values of each position by the corresponding weight:
|
47
46
|
# 2. Add up the results of the above multiplications;
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TinValid
|
4
|
+
class FinlandTin
|
5
|
+
include TinValid::Helpers
|
6
|
+
|
7
|
+
def initialize(tin:, birth_date: nil)
|
8
|
+
@tin = tin
|
9
|
+
@birth_date = birth_date
|
10
|
+
end
|
11
|
+
|
12
|
+
attr_reader :tin, :birth_date
|
13
|
+
|
14
|
+
def valid?
|
15
|
+
match = MATCHER.match(tin)
|
16
|
+
return false unless match
|
17
|
+
|
18
|
+
tin_date = date(
|
19
|
+
"#{tin_century(match[:century])}#{match[:year]}",
|
20
|
+
match[:month],
|
21
|
+
match[:day],
|
22
|
+
)
|
23
|
+
return false unless tin_date
|
24
|
+
return false if birth_date && birth_date != tin_date
|
25
|
+
|
26
|
+
tin[-1] == check
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
MATCHER = %r{
|
32
|
+
\A
|
33
|
+
(?<day>[0-3][0-9])
|
34
|
+
(?<month>[0-1][0-9])
|
35
|
+
(?<year>[0-9][0-9])
|
36
|
+
(?<century>[-+A-FU-Y])
|
37
|
+
[0-9]{3}
|
38
|
+
[0-9A-Z]
|
39
|
+
\z
|
40
|
+
}x
|
41
|
+
private_constant :MATCHER
|
42
|
+
|
43
|
+
def tin_century(character)
|
44
|
+
case character
|
45
|
+
when "+" then 18
|
46
|
+
when "-", "U", "V", "W", "X", "Y" then 19
|
47
|
+
else 20
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def check
|
52
|
+
# 1. Concatenate C1, C2, C3, C4, C5, C6, C8, C9, C10
|
53
|
+
# (warning: C7 is not part of the check digit);
|
54
|
+
number = "#{tin[0..5]}#{tin[7..9]}".to_i
|
55
|
+
|
56
|
+
# 2. Calculate the modulo 31 of the abovementioned number;
|
57
|
+
remainder = number % 31
|
58
|
+
|
59
|
+
# 4. The result of calculating modulo 31 will give as a result a number,
|
60
|
+
# which will provide the check mark through the following table:
|
61
|
+
case remainder
|
62
|
+
when ..9 then remainder.to_s
|
63
|
+
when ..15 then (remainder + 55).chr
|
64
|
+
when 16 then "H"
|
65
|
+
when ..21 then (remainder + 57).chr
|
66
|
+
when 21 then "P"
|
67
|
+
else (remainder + 59).chr
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TinValid
|
4
|
+
class FranceTin
|
5
|
+
def initialize(tin:)
|
6
|
+
@tin = tin
|
7
|
+
end
|
8
|
+
|
9
|
+
attr_reader :tin
|
10
|
+
|
11
|
+
def valid?
|
12
|
+
return false unless /\A[0-3][0-9]{12}\z/.match?(tin)
|
13
|
+
return false if tin == "0000000000000"
|
14
|
+
|
15
|
+
tin[-3..].to_i == check
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def check
|
21
|
+
# 1. Concatenate C1, C2, C3, C4, C5, C6, C7, C8, C9, C10;
|
22
|
+
# 2. Get modulo 511 of the result of the previous result;
|
23
|
+
# 3. Check digit = remainder if remainder < 100, C11 = 0
|
24
|
+
# (if remainder < 10, C11 = 0 and C12 = 0).
|
25
|
+
tin[..-4].to_i % 511
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -1,7 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module TinValid
|
4
|
-
class GermanyTin
|
4
|
+
class GermanyTin
|
5
|
+
def initialize(tin:)
|
6
|
+
@tin = tin
|
7
|
+
end
|
8
|
+
|
9
|
+
attr_reader :tin
|
10
|
+
|
5
11
|
def valid?
|
6
12
|
valid_v1? || valid_v2?
|
7
13
|
end
|
@@ -12,7 +18,9 @@ module TinValid
|
|
12
18
|
# 1. 13 characters
|
13
19
|
# 2. Only digits
|
14
20
|
# 3. C5 is a 0
|
15
|
-
/\A[0-9]{4}0[0-9]{8}\z/.match?(tin)
|
21
|
+
return false unless /\A[0-9]{4}0[0-9]{8}\z/.match?(tin)
|
22
|
+
|
23
|
+
tin.to_i != 0
|
16
24
|
end
|
17
25
|
|
18
26
|
# rubocop:disable Metrics/AbcSize
|
@@ -48,13 +56,16 @@ module TinValid
|
|
48
56
|
# 3. Multiply the result by 2;
|
49
57
|
result *= 2
|
50
58
|
|
51
|
-
# 4. Take modulo 11 of the result. Update the value of variable X with
|
59
|
+
# 4. Take modulo 11 of the result. Update the value of variable X with
|
60
|
+
# the result of this operation;
|
52
61
|
x = result % 11
|
53
62
|
|
54
63
|
# 5. Take C2 + X modulo 10. If result is 0, result is 10;
|
55
64
|
# 6. Multiply the result by 2;
|
56
|
-
# 7. Take modulo 11 of the result. Update the value of variable X with
|
57
|
-
#
|
65
|
+
# 7. Take modulo 11 of the result. Update the value of variable X with
|
66
|
+
# the result of this operation;
|
67
|
+
# 8. Apply steps 5, 6 and 7 in an analogue way for digits C3 to C10.
|
68
|
+
# Consider that last value called Y;
|
58
69
|
x
|
59
70
|
end
|
60
71
|
|
data/lib/tin_valid/greece_tin.rb
CHANGED
@@ -1,9 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module TinValid
|
4
|
-
class GreeceTin
|
4
|
+
class GreeceTin
|
5
|
+
def initialize(tin:)
|
6
|
+
@tin = tin
|
7
|
+
end
|
8
|
+
|
9
|
+
attr_reader :tin
|
10
|
+
|
5
11
|
def valid?
|
6
|
-
/\A[0-9]{9}\z/.match?(tin)
|
12
|
+
return false unless /\A[0-9]{9}\z/.match?(tin)
|
13
|
+
|
14
|
+
tin != "000000000" && tin != "123456789"
|
7
15
|
end
|
8
16
|
end
|
9
17
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TinValid
|
4
|
+
module Helpers
|
5
|
+
private
|
6
|
+
|
7
|
+
def date(year, month, day)
|
8
|
+
found_date = Date.new(year.to_i, month.to_i, day.to_i)
|
9
|
+
found_date if found_date < Date.today
|
10
|
+
rescue Date::Error
|
11
|
+
nil
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -1,7 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module TinValid
|
4
|
-
class HungaryTin
|
4
|
+
class HungaryTin
|
5
|
+
def initialize(tin:)
|
6
|
+
@tin = tin
|
7
|
+
end
|
8
|
+
|
9
|
+
attr_reader :tin
|
10
|
+
|
5
11
|
def valid?
|
6
12
|
return false unless /\A8[0-9]{9}\z/.match?(tin)
|
7
13
|
|
@@ -11,8 +17,6 @@ module TinValid
|
|
11
17
|
private
|
12
18
|
|
13
19
|
def check
|
14
|
-
tin[..-2].chars
|
15
|
-
|
16
20
|
# 1. Multiply the values of each position by the corresponding weight:
|
17
21
|
# 2. Add up the results of the above multiplications;
|
18
22
|
result = (1..9).each_with_index.sum { |num, i| num * tin[i].to_i }
|