tin_valid 1.1.2 → 1.2.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/.rubocop.yml +8 -0
- data/CHANGELOG.md +9 -0
- data/README.md +235 -71
- data/lib/tin_valid/france_tin.rb +28 -10
- data/lib/tin_valid/tin.rb +55 -0
- data/lib/tin_valid/version.rb +1 -1
- data/lib/tin_valid.rb +1 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3fb98f7f433b3c6a6755c0caa0835c75ed58408fee17ee0e96a083603fd965d5
|
4
|
+
data.tar.gz: 2eb697ac67268456c7cd8ff346144b3cbbfcb2b4bbff8052065ad6b7789b0d15
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ea7cd37992f808250a153fa5be6728489438136701318e8397d1822512efaddfd8ed395534cdc0e62f8523f9ec225cb151f37409ea741accdcd8c233e7858e5f
|
7
|
+
data.tar.gz: 91eefad78dd3d3219cb7e4add5b5022cd72f62e09a7d6fa5b8b9279e60e165a7620ca2ab25fe4ccb94da5b629f6251e814aeeff0007399830b275be3b99e5ce7
|
data/.rubocop.yml
CHANGED
@@ -12,6 +12,7 @@ Layout/LineLength:
|
|
12
12
|
Max: 80
|
13
13
|
Exclude:
|
14
14
|
- bin/rspec
|
15
|
+
- bin/rake
|
15
16
|
|
16
17
|
Layout/MultilineMethodCallIndentation:
|
17
18
|
# On multiline calls, indent starting from the receiver.
|
@@ -33,6 +34,13 @@ Metrics/BlockLength:
|
|
33
34
|
Exclude:
|
34
35
|
- spec/**/*
|
35
36
|
|
37
|
+
# Security
|
38
|
+
|
39
|
+
Security/Eval:
|
40
|
+
# Allow the use of `eval` in specs.
|
41
|
+
Exclude:
|
42
|
+
- spec/**/*
|
43
|
+
|
36
44
|
# Style
|
37
45
|
|
38
46
|
Style/Documentation:
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,14 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [1.2.0] - 2025-05-14
|
4
|
+
|
5
|
+
Features:
|
6
|
+
- Add generic `TinValid::Tin.new(country_code: "…", tin: "…").valid?`
|
7
|
+
- Add `#siren?` and `#siret?` on `TinValid::FranceTin`
|
8
|
+
|
9
|
+
Fixes:
|
10
|
+
- Accept SIRET for France
|
11
|
+
|
3
12
|
## [1.1.2] - 2025-05-06
|
4
13
|
|
5
14
|
Fixes:
|
data/README.md
CHANGED
@@ -54,105 +54,269 @@ gem install tin_valid
|
|
54
54
|
|
55
55
|
## Usage
|
56
56
|
|
57
|
+
Check a TIN by providing the country code as a lowercase string.
|
58
|
+
|
59
|
+
Also accepts the following optional arguments:
|
60
|
+
|
61
|
+
- `birth_date`: Date
|
62
|
+
- `kind`: `"individual"` or `"company"`
|
63
|
+
|
64
|
+
```rb
|
65
|
+
TinValid::Tin.new(country_code: "fr", tin: "3023217600053").valid?
|
66
|
+
```
|
67
|
+
|
68
|
+
You can also call countries individually:
|
69
|
+
|
70
|
+
### Austria (at)
|
71
|
+
|
72
|
+
```rb
|
73
|
+
TinValid::AustriaTin.new(
|
74
|
+
tin: "931736581",
|
75
|
+
).valid?
|
76
|
+
```
|
77
|
+
|
78
|
+
### Belgium (be)
|
79
|
+
|
80
|
+
`birth_date` is optional
|
81
|
+
|
82
|
+
```rb
|
83
|
+
TinValid::BelgiumTin.new(
|
84
|
+
tin: "00012511119",
|
85
|
+
birth_date: Date.new(1900, 1, 25),
|
86
|
+
).valid?
|
87
|
+
```
|
88
|
+
|
89
|
+
### Bulgaria (bg)
|
90
|
+
|
91
|
+
`birth_date` is optional
|
92
|
+
|
93
|
+
```rb
|
94
|
+
TinValid::BulgariaTin.new(
|
95
|
+
tin: "7501010010",
|
96
|
+
birth_date: Date.new(1975, 1, 1),
|
97
|
+
).valid?
|
98
|
+
```
|
99
|
+
|
100
|
+
### Croatia (hr)
|
101
|
+
|
102
|
+
```rb
|
103
|
+
TinValid::CroatiaTin.new(
|
104
|
+
tin: "94577403194",
|
105
|
+
).valid?
|
106
|
+
```
|
107
|
+
|
108
|
+
### Cyprus (cy)
|
109
|
+
|
110
|
+
`kind` is optional and can be `"individual"` or `"company"`
|
111
|
+
|
112
|
+
```rb
|
113
|
+
TinValid::CyprusTin.new(tin: "00123123T", kind: "individual").valid?
|
114
|
+
```
|
115
|
+
|
116
|
+
### Czechia (cz)
|
117
|
+
|
118
|
+
`birth_date` is optional
|
119
|
+
|
120
|
+
```rb
|
121
|
+
TinValid::CzechiaTin.new(
|
122
|
+
tin: "420901999",
|
123
|
+
birth_date: Date.new(1942, 9, 1),
|
124
|
+
).valid?
|
125
|
+
```
|
126
|
+
|
127
|
+
### Denmark (dk)
|
128
|
+
|
129
|
+
`birth_date` is optional
|
130
|
+
|
131
|
+
```rb
|
132
|
+
TinValid::DenmarkTin.new(
|
133
|
+
tin: "0101111113",
|
134
|
+
birth_date: Date.new(1911, 1, 1),
|
135
|
+
).valid?
|
136
|
+
```
|
137
|
+
|
138
|
+
### Estonia (ee)
|
139
|
+
|
140
|
+
`birth_date` is optional
|
141
|
+
|
142
|
+
```rb
|
143
|
+
TinValid::EstoniaTin.new(
|
144
|
+
tin: "37102250382",
|
145
|
+
birth_date: Date.new(1971, 2, 25),
|
146
|
+
).valid?
|
147
|
+
```
|
148
|
+
|
149
|
+
### Finland (fi)
|
150
|
+
|
151
|
+
`birth_date` is optional
|
152
|
+
|
153
|
+
```rb
|
154
|
+
TinValid::FinlandTin.new(
|
155
|
+
tin: "131052-308T",
|
156
|
+
birth_date: Date.new(1952, 10, 13),
|
157
|
+
).valid?
|
158
|
+
```
|
159
|
+
|
160
|
+
### France (fr)
|
161
|
+
|
162
|
+
```rb
|
163
|
+
TinValid::FranceTin.new(tin: "3023217600053").valid?
|
164
|
+
```
|
165
|
+
|
166
|
+
```rb
|
167
|
+
TinValid::FranceTin.new(tin: "732829320").siren?
|
168
|
+
```
|
169
|
+
|
57
170
|
```rb
|
58
|
-
|
59
|
-
|
171
|
+
TinValid::FranceTin.new(tin: "73282932000074").siret?
|
172
|
+
```
|
173
|
+
|
174
|
+
### Germany (de)
|
175
|
+
|
176
|
+
```rb
|
177
|
+
TinValid::GermanyTin.new(tin: "5133081508159").valid?
|
178
|
+
```
|
60
179
|
|
61
|
-
|
62
|
-
# Optional birth_date
|
63
|
-
TinValid::BelgiumTin.new(tin: "…", birth_date: Date.new(…)).valid?
|
180
|
+
### Greece (gr)
|
64
181
|
|
65
|
-
|
66
|
-
|
67
|
-
|
182
|
+
```rb
|
183
|
+
TinValid::GreeceTin.new(tin: "999999999").valid?
|
184
|
+
```
|
68
185
|
|
69
|
-
|
70
|
-
TinValid::CroatiaTin.new(tin: "…").valid?
|
186
|
+
### Hungary (hu)
|
71
187
|
|
72
|
-
|
73
|
-
|
74
|
-
|
188
|
+
```rb
|
189
|
+
TinValid::HungaryTin.new(tin: "8071592153").valid?
|
190
|
+
```
|
75
191
|
|
76
|
-
|
77
|
-
# Optional birth_date
|
78
|
-
TinValid::CzechiaTin.new(tin: "…", birth_date: Date.new(…)).valid?
|
192
|
+
### Ireland (ie)
|
79
193
|
|
80
|
-
|
81
|
-
|
82
|
-
|
194
|
+
```rb
|
195
|
+
TinValid::IrelandTin.new(tin: "1234567T").valid?
|
196
|
+
```
|
83
197
|
|
84
|
-
|
85
|
-
# Optional birth_date
|
86
|
-
TinValid::EstoniaTin.new(tin: "…", birth_date: Date.new(…)).valid?
|
198
|
+
### Italy (it)
|
87
199
|
|
88
|
-
|
89
|
-
# Optional birth_date
|
90
|
-
TinValid::FinlandTin.new(tin: "…", birth_date: Date.new(…)).valid?
|
200
|
+
`birth_date` is optional
|
91
201
|
|
92
|
-
|
93
|
-
TinValid::
|
202
|
+
```rb
|
203
|
+
TinValid::ItalyTin.new(
|
204
|
+
tin: "DMLPRY77D15H501F",
|
205
|
+
birth_date: Date.new(1977, 4, 15),
|
206
|
+
).valid?
|
207
|
+
```
|
94
208
|
|
95
|
-
|
96
|
-
TinValid::GermanyTin.new(tin: "…").valid?
|
209
|
+
### Latvia (lv)
|
97
210
|
|
98
|
-
|
99
|
-
TinValid::GreeceTin.new(tin: "…").valid?
|
211
|
+
`birth_date` is optional
|
100
212
|
|
101
|
-
|
102
|
-
TinValid::
|
213
|
+
```rb
|
214
|
+
TinValid::LatviaTin.new(
|
215
|
+
tin: "01011012345",
|
216
|
+
birth_date: Date.new(1910, 1, 1),
|
217
|
+
).valid?
|
218
|
+
```
|
103
219
|
|
104
|
-
|
105
|
-
TinValid::IrelandTin.new(tin: "…").valid?
|
220
|
+
### Lithuania (lt)
|
106
221
|
|
107
|
-
|
108
|
-
# Optional birth_date
|
109
|
-
TinValid::ItalyTin.new(tin: "…", birth_date: Date.new(…)).valid?
|
222
|
+
`birth_date` is optional
|
110
223
|
|
111
|
-
|
112
|
-
|
113
|
-
|
224
|
+
```rb
|
225
|
+
TinValid::LithuaniaTin.new(
|
226
|
+
tin: "10101010005",
|
227
|
+
birth_date: Date.new(2001, 1, 1),
|
228
|
+
).valid?
|
229
|
+
```
|
114
230
|
|
115
|
-
|
116
|
-
# Optional birth_date
|
117
|
-
TinValid::LithuaniaTin.new(tin: "…", birth_date: Date.new(…)).valid?
|
231
|
+
### Luxembourg (lu)
|
118
232
|
|
119
|
-
|
120
|
-
# Optional birth_date
|
121
|
-
TinValid::LuxembourgTin.new(tin: "…", birth_date: Date.new(…)).valid?
|
233
|
+
`birth_date` is optional
|
122
234
|
|
123
|
-
|
124
|
-
TinValid::
|
235
|
+
```rb
|
236
|
+
TinValid::LuxembourgTin.new(
|
237
|
+
tin: "1893120105732",
|
238
|
+
birth_date: Date.new(1893, 12, 1),
|
239
|
+
).valid?
|
240
|
+
```
|
125
241
|
|
126
|
-
|
127
|
-
TinValid::NetherlandsTin.new(tin: "…").valid?
|
242
|
+
### Malta (mt)
|
128
243
|
|
129
|
-
|
130
|
-
|
131
|
-
|
244
|
+
```rb
|
245
|
+
TinValid::MaltaTin.new(tin: "1234567A").valid?
|
246
|
+
```
|
132
247
|
|
133
|
-
|
134
|
-
TinValid::PortugalTin.new(tin: "…").valid?
|
248
|
+
### Netherlands (nl)
|
135
249
|
|
136
|
-
|
137
|
-
|
138
|
-
|
250
|
+
```rb
|
251
|
+
TinValid::NetherlandsTin.new(tin: "174559434").valid?
|
252
|
+
```
|
139
253
|
|
140
|
-
|
141
|
-
# Optional birth_date
|
142
|
-
TinValid::SlovakiaTin.new(tin: "…", birth_date: Date.new(…)).valid?
|
254
|
+
### Poland (pl)
|
143
255
|
|
144
|
-
|
145
|
-
TinValid::SloveniaTin.new(tin: "…").valid?
|
256
|
+
`birth_date` is optional
|
146
257
|
|
147
|
-
|
148
|
-
TinValid::
|
258
|
+
```rb
|
259
|
+
TinValid::PolandTin.new(
|
260
|
+
tin: "02070803628",
|
261
|
+
birth_date: Date.new(1902, 7, 8),
|
262
|
+
).valid?
|
263
|
+
```
|
149
264
|
|
150
|
-
|
151
|
-
# Optional birth_date
|
152
|
-
TinValid::SwedenTin.new(tin: "…", birth_date: Date.new(…)).valid?
|
265
|
+
### Portugal (pt)
|
153
266
|
|
154
|
-
|
155
|
-
TinValid::
|
267
|
+
```rb
|
268
|
+
TinValid::PortugalTin.new(tin: "299999998").valid?
|
269
|
+
```
|
270
|
+
|
271
|
+
### Romania (ro)
|
272
|
+
|
273
|
+
`birth_date` is optional
|
274
|
+
|
275
|
+
```rb
|
276
|
+
TinValid::RomaniaTin.new(
|
277
|
+
tin: "8001011234567",
|
278
|
+
birth_date: Date.new(2000, 10, 11),
|
279
|
+
).valid?
|
280
|
+
```
|
281
|
+
|
282
|
+
### Slovakia (sk)
|
283
|
+
|
284
|
+
`birth_date` is optional
|
285
|
+
|
286
|
+
```rb
|
287
|
+
TinValid::SlovakiaTin.new(
|
288
|
+
tin: "7711167420",
|
289
|
+
birth_date: Date.new(1977, 11, 16),
|
290
|
+
).valid?
|
291
|
+
```
|
292
|
+
|
293
|
+
### Slovenia (si)
|
294
|
+
|
295
|
+
```rb
|
296
|
+
TinValid::SloveniaTin.new(tin: "15012557").valid?
|
297
|
+
```
|
298
|
+
|
299
|
+
### Spain (es)
|
300
|
+
|
301
|
+
```rb
|
302
|
+
TinValid::SpainTin.new(tin: "54237A").valid?
|
303
|
+
```
|
304
|
+
|
305
|
+
### Sweden (se)
|
306
|
+
|
307
|
+
`birth_date` is optional
|
308
|
+
|
309
|
+
```rb
|
310
|
+
TinValid::SwedenTin.new(
|
311
|
+
tin: "640823-3234",
|
312
|
+
birth_date: Date.new(1964, 8, 23),
|
313
|
+
).valid?
|
314
|
+
```
|
315
|
+
|
316
|
+
### United Kingdom (gb)
|
317
|
+
|
318
|
+
```rb
|
319
|
+
TinValid::UnitedKingdomTin.new(tin: "9234567890").valid?
|
156
320
|
```
|
157
321
|
|
158
322
|
## Development
|
data/lib/tin_valid/france_tin.rb
CHANGED
@@ -9,7 +9,23 @@ module TinValid
|
|
9
9
|
|
10
10
|
attr_reader :tin
|
11
11
|
|
12
|
-
def valid? = valid_v1? ||
|
12
|
+
def valid? = valid_v1? || siren? || siret?
|
13
|
+
|
14
|
+
# https://fr.wikipedia.org/wiki/Syst%C3%A8me_d%27identification_du_r%C3%A9pertoire_des_entreprises
|
15
|
+
def siren?
|
16
|
+
return false unless /\A[1-9][0-9]{8}\z/.match?(tin)
|
17
|
+
return false if tin == "123456789"
|
18
|
+
|
19
|
+
luhn_valid?
|
20
|
+
end
|
21
|
+
|
22
|
+
# https://fr.wikipedia.org/wiki/Syst%C3%A8me_d%27identification_du_r%C3%A9pertoire_des_%C3%A9tablissements
|
23
|
+
def siret?
|
24
|
+
return false unless /\A\d{14}\z/.match?(tin)
|
25
|
+
return false if tin == "00000000000000"
|
26
|
+
|
27
|
+
luhn_valid?
|
28
|
+
end
|
13
29
|
|
14
30
|
private
|
15
31
|
|
@@ -17,22 +33,24 @@ module TinValid
|
|
17
33
|
return false unless /\A[0-3][0-9]{12}\z/.match?(tin)
|
18
34
|
return false if tin == "0000000000000"
|
19
35
|
|
20
|
-
tin[-3..].to_i ==
|
36
|
+
tin[-3..].to_i == v1_check
|
21
37
|
end
|
22
38
|
|
23
|
-
|
24
|
-
def valid_siren?
|
25
|
-
return false if tin == "123456789"
|
26
|
-
|
27
|
-
/\A[1-9][0-9]{8}\z/.match?(tin)
|
28
|
-
end
|
29
|
-
|
30
|
-
def check
|
39
|
+
def v1_check
|
31
40
|
# 1. Concatenate C1, C2, C3, C4, C5, C6, C7, C8, C9, C10;
|
32
41
|
# 2. Get modulo 511 of the result of the previous result;
|
33
42
|
# 3. Check digit = remainder if remainder < 100, C11 = 0
|
34
43
|
# (if remainder < 10, C11 = 0 and C12 = 0).
|
35
44
|
tin[..-4].to_i % 511
|
36
45
|
end
|
46
|
+
|
47
|
+
# https://en.wikipedia.org/wiki/Luhn_algorithm
|
48
|
+
def luhn_valid?
|
49
|
+
check = tin.chars.reverse.each_slice(2).sum do |a, b|
|
50
|
+
a.to_i + (b.to_i * 2).to_s.chars.sum(&:to_i)
|
51
|
+
end
|
52
|
+
|
53
|
+
check % 10 == 0
|
54
|
+
end
|
37
55
|
end
|
38
56
|
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TinValid
|
4
|
+
class Tin
|
5
|
+
def initialize(country_code:, tin:, birth_date: nil, kind: nil)
|
6
|
+
@country_code = country_code
|
7
|
+
@tin = tin
|
8
|
+
@birth_date = birth_date
|
9
|
+
@kind = kind
|
10
|
+
end
|
11
|
+
|
12
|
+
attr_reader :country_code, :tin, :birth_date, :kind
|
13
|
+
|
14
|
+
# rubocop:disable Metrics/AbcSize
|
15
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
16
|
+
# rubocop:disable Metrics/PerceivedComplexity
|
17
|
+
# rubocop:disable Metrics/MethodLength
|
18
|
+
def valid?
|
19
|
+
case country_code
|
20
|
+
in "at" then AustriaTin.new(tin:).valid?
|
21
|
+
in "be" then BelgiumTin.new(tin:, birth_date:).valid?
|
22
|
+
in "bg" then BulgariaTin.new(tin:, birth_date:).valid?
|
23
|
+
in "cy" then CyprusTin.new(tin:, kind:).valid?
|
24
|
+
in "cz" then CzechiaTin.new(tin:, birth_date:).valid?
|
25
|
+
in "de" then GermanyTin.new(tin:).valid?
|
26
|
+
in "dk" then DenmarkTin.new(tin:, birth_date:).valid?
|
27
|
+
in "ee" then EstoniaTin.new(tin:, birth_date:).valid?
|
28
|
+
in "es" then SpainTin.new(tin:).valid?
|
29
|
+
in "fi" then FinlandTin.new(tin:).valid?
|
30
|
+
in "fr" then FranceTin.new(tin:).valid?
|
31
|
+
in "gb" then UnitedKingdomTin.new(tin:).valid?
|
32
|
+
in "gr" then GreeceTin.new(tin:).valid?
|
33
|
+
in "hr" then CroatiaTin.new(tin:).valid?
|
34
|
+
in "hu" then HungaryTin.new(tin:).valid?
|
35
|
+
in "ie" then IrelandTin.new(tin:).valid?
|
36
|
+
in "it" then ItalyTin.new(tin:, birth_date:).valid?
|
37
|
+
in "lt" then LithuaniaTin.new(tin:, birth_date:).valid?
|
38
|
+
in "lu" then LuxembourgTin.new(tin:, birth_date:).valid?
|
39
|
+
in "lv" then LatviaTin.new(tin:, birth_date:).valid?
|
40
|
+
in "mt" then MaltaTin.new(tin:).valid?
|
41
|
+
in "nl" then NetherlandsTin.new(tin:).valid?
|
42
|
+
in "pl" then PolandTin.new(tin:, birth_date:).valid?
|
43
|
+
in "pt" then PortugalTin.new(tin:).valid?
|
44
|
+
in "ro" then RomaniaTin.new(tin:, birth_date:).valid?
|
45
|
+
in "se" then SwedenTin.new(tin:, birth_date:).valid?
|
46
|
+
in "si" then SloveniaTin.new(tin:).valid?
|
47
|
+
in "sk" then SlovakiaTin.new(tin:).valid?
|
48
|
+
end
|
49
|
+
end
|
50
|
+
# rubocop:enable Metrics/AbcSize
|
51
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
52
|
+
# rubocop:enable Metrics/PerceivedComplexity
|
53
|
+
# rubocop:enable Metrics/MethodLength
|
54
|
+
end
|
55
|
+
end
|
data/lib/tin_valid/version.rb
CHANGED
data/lib/tin_valid.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tin_valid
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sunny Ripert
|
8
8
|
bindir: exe
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-05-
|
10
|
+
date: 2025-05-14 00:00:00.000000000 Z
|
11
11
|
dependencies: []
|
12
12
|
email:
|
13
13
|
- sunny@sunfox.org
|
@@ -51,6 +51,7 @@ files:
|
|
51
51
|
- lib/tin_valid/slovenia_tin.rb
|
52
52
|
- lib/tin_valid/spain_tin.rb
|
53
53
|
- lib/tin_valid/sweden_tin.rb
|
54
|
+
- lib/tin_valid/tin.rb
|
54
55
|
- lib/tin_valid/united_kingdom_tin.rb
|
55
56
|
- lib/tin_valid/version.rb
|
56
57
|
- sig/tin_valid.rbs
|