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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 57ef691e689d26ef2b254910aa99a7aee71247ebd5029187404b1fb9ae26d725
4
- data.tar.gz: 81e37c9edc4a97698cdc1e264a9c794679e4f417ce01284f78a62f16b87b3a77
3
+ metadata.gz: 3fb98f7f433b3c6a6755c0caa0835c75ed58408fee17ee0e96a083603fd965d5
4
+ data.tar.gz: 2eb697ac67268456c7cd8ff346144b3cbbfcb2b4bbff8052065ad6b7789b0d15
5
5
  SHA512:
6
- metadata.gz: 04d22d7d57e37bba3cd2de93f5af77883671520143e8cd15b62f3062b388e71a774b49c2c58c90970b4ef72d14d3b80a3ff9c5fb7aa1a0ba9f84561f466f75f7
7
- data.tar.gz: '089d95d8d72de2f7ed52958c194112bedde0bc982b58ec3cc134db13b5eea8b72f44df2bfdffe898e6aa61f962d6976ac53b3fcfa4a3cf3e8f9a1db9da34743d'
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
- # Austria
59
- TinValid::AustriaTin.new(tin: "…").valid? # => true
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
- # Belgium
62
- # Optional birth_date
63
- TinValid::BelgiumTin.new(tin: "…", birth_date: Date.new(…)).valid?
180
+ ### Greece (gr)
64
181
 
65
- # Bulgaria
66
- # Optional birth_date
67
- TinValid::BulgariaTin.new(tin: "…", birth_date: Date.new(…)).valid?
182
+ ```rb
183
+ TinValid::GreeceTin.new(tin: "999999999").valid?
184
+ ```
68
185
 
69
- # Croatia
70
- TinValid::CroatiaTin.new(tin: "…").valid?
186
+ ### Hungary (hu)
71
187
 
72
- # Cyprus
73
- # Optional kind ("individual" or "company")
74
- TinValid::CyprusTin.new(tin: "…", kind: "individual").valid?
188
+ ```rb
189
+ TinValid::HungaryTin.new(tin: "8071592153").valid?
190
+ ```
75
191
 
76
- # Czechia
77
- # Optional birth_date
78
- TinValid::CzechiaTin.new(tin: "…", birth_date: Date.new(…)).valid?
192
+ ### Ireland (ie)
79
193
 
80
- # Denmark
81
- # Optional birth_date
82
- TinValid::DenmarkTin.new(tin: "…", birth_date: Date.new(…)).valid?
194
+ ```rb
195
+ TinValid::IrelandTin.new(tin: "1234567T").valid?
196
+ ```
83
197
 
84
- # Estonia
85
- # Optional birth_date
86
- TinValid::EstoniaTin.new(tin: "…", birth_date: Date.new(…)).valid?
198
+ ### Italy (it)
87
199
 
88
- # Finland
89
- # Optional birth_date
90
- TinValid::FinlandTin.new(tin: "…", birth_date: Date.new(…)).valid?
200
+ `birth_date` is optional
91
201
 
92
- # France
93
- TinValid::FranceTin.new(tin: "…").valid?
202
+ ```rb
203
+ TinValid::ItalyTin.new(
204
+ tin: "DMLPRY77D15H501F",
205
+ birth_date: Date.new(1977, 4, 15),
206
+ ).valid?
207
+ ```
94
208
 
95
- # Germany
96
- TinValid::GermanyTin.new(tin: "…").valid?
209
+ ### Latvia (lv)
97
210
 
98
- # Greece
99
- TinValid::GreeceTin.new(tin: "…").valid?
211
+ `birth_date` is optional
100
212
 
101
- # Hungary
102
- TinValid::HungaryTin.new(tin: "…").valid?
213
+ ```rb
214
+ TinValid::LatviaTin.new(
215
+ tin: "01011012345",
216
+ birth_date: Date.new(1910, 1, 1),
217
+ ).valid?
218
+ ```
103
219
 
104
- # Ireland
105
- TinValid::IrelandTin.new(tin: "…").valid?
220
+ ### Lithuania (lt)
106
221
 
107
- # Italy
108
- # Optional birth_date
109
- TinValid::ItalyTin.new(tin: "…", birth_date: Date.new(…)).valid?
222
+ `birth_date` is optional
110
223
 
111
- # Latvia
112
- # Optional birth_date
113
- TinValid::LatviaTin.new(tin: "", birth_date: Date.new(…)).valid?
224
+ ```rb
225
+ TinValid::LithuaniaTin.new(
226
+ tin: "10101010005",
227
+ birth_date: Date.new(2001, 1, 1),
228
+ ).valid?
229
+ ```
114
230
 
115
- # Lithuania
116
- # Optional birth_date
117
- TinValid::LithuaniaTin.new(tin: "…", birth_date: Date.new(…)).valid?
231
+ ### Luxembourg (lu)
118
232
 
119
- # Luxembourg
120
- # Optional birth_date
121
- TinValid::LuxembourgTin.new(tin: "…", birth_date: Date.new(…)).valid?
233
+ `birth_date` is optional
122
234
 
123
- # Malta
124
- TinValid::MaltaTin.new(tin: "…").valid?
235
+ ```rb
236
+ TinValid::LuxembourgTin.new(
237
+ tin: "1893120105732",
238
+ birth_date: Date.new(1893, 12, 1),
239
+ ).valid?
240
+ ```
125
241
 
126
- # Netherlands
127
- TinValid::NetherlandsTin.new(tin: "…").valid?
242
+ ### Malta (mt)
128
243
 
129
- # Poland
130
- # Optional birth_date
131
- TinValid::PolandTin.new(tin: "…", birth_date: Date.new(…)).valid?
244
+ ```rb
245
+ TinValid::MaltaTin.new(tin: "1234567A").valid?
246
+ ```
132
247
 
133
- # Portugal
134
- TinValid::PortugalTin.new(tin: "…").valid?
248
+ ### Netherlands (nl)
135
249
 
136
- # Romania
137
- # Optional birth_date
138
- TinValid::RomaniaTin.new(tin: "…", birth_date: Date.new(…)).valid?
250
+ ```rb
251
+ TinValid::NetherlandsTin.new(tin: "174559434").valid?
252
+ ```
139
253
 
140
- # Slovakia
141
- # Optional birth_date
142
- TinValid::SlovakiaTin.new(tin: "…", birth_date: Date.new(…)).valid?
254
+ ### Poland (pl)
143
255
 
144
- # Slovenia
145
- TinValid::SloveniaTin.new(tin: "…").valid?
256
+ `birth_date` is optional
146
257
 
147
- # Spain
148
- TinValid::SpainTin.new(tin: "…").valid?
258
+ ```rb
259
+ TinValid::PolandTin.new(
260
+ tin: "02070803628",
261
+ birth_date: Date.new(1902, 7, 8),
262
+ ).valid?
263
+ ```
149
264
 
150
- # Sweden
151
- # Optional birth_date
152
- TinValid::SwedenTin.new(tin: "…", birth_date: Date.new(…)).valid?
265
+ ### Portugal (pt)
153
266
 
154
- # United Kingdom
155
- TinValid::UnitedKingdomTin.new(tin: "").valid?
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
@@ -9,7 +9,23 @@ module TinValid
9
9
 
10
10
  attr_reader :tin
11
11
 
12
- def valid? = valid_v1? || valid_siren?
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 == check
36
+ tin[-3..].to_i == v1_check
21
37
  end
22
38
 
23
- # https://annuaire-entreprises.data.gouv.fr/definitions/numero-siren
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TinValid
4
- VERSION = "1.1.2"
4
+ VERSION = "1.2.0"
5
5
  end
data/lib/tin_valid.rb CHANGED
@@ -3,6 +3,7 @@
3
3
  require "date"
4
4
  require_relative "tin_valid/version"
5
5
  require_relative "tin_valid/helpers"
6
+ require_relative "tin_valid/tin"
6
7
  require_relative "tin_valid/austria_tin"
7
8
  require_relative "tin_valid/belgium_tin"
8
9
  require_relative "tin_valid/bulgaria_tin"
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.1.2
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-06 00:00:00.000000000 Z
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