valvat 1.1.4 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dc72697b0c9176fc5204b1434efb9acb303e70f37ba894518a92ef964e22111b
4
- data.tar.gz: 879918277a1fdee158ae2d45d5ba12c06ed9ce2f3a61143f8ae737cb079f4f8a
3
+ metadata.gz: d8adbca62e2ebbf198c817bfed2cf8dc2d375a24cb146dff52ce42a6dd59750d
4
+ data.tar.gz: 84949112505cff60333ff382583b54f4b4c20cb86e59bf5cbb1c16616c1c3ce7
5
5
  SHA512:
6
- metadata.gz: fd117658d26b50836714888ddc58b0a1155b380d874887af56b299226120164a7730b44cf76599f281bc51ab87dc4ce535dada233dbf2a99b62f84502b418fe0
7
- data.tar.gz: 7c452101dc8994424f4e3af668834f16e7fe1297b71f634f42e0ea4f25fe2678cafb33b154ca9d3ffa9de9b578cb20869fcb251464393f67aec98ac24543273c
6
+ metadata.gz: d2c2cb07112932730644124d140dc29a8e1ffc2e0b590d67ef1ff9f24dfb9c327fc72c189a8ebccdb983c04271c5cabebfa210bc20a61d8b9788c489135d58f9
7
+ data.tar.gz: 543a2f012caac4dfb874d9c5cca697b3cde38bbb16ca646ff87e66020d913f58094890ceed95d0ffa39637d4c538253358fe0f6ae4ea0a045fe6de4fd9f8585b
checksums.yaml.gz.sig CHANGED
Binary file
@@ -2,12 +2,12 @@ name: Specs
2
2
 
3
3
  on:
4
4
  push:
5
- branches: [ master ]
6
5
  paths-ignore:
7
6
  - 'README.md'
8
7
  - 'CHANGES.md'
9
8
  pull_request:
10
- branches: [ master ]
9
+ schedule:
10
+ - cron: '52 8 * * *'
11
11
 
12
12
  jobs:
13
13
  test:
@@ -17,7 +17,7 @@ jobs:
17
17
  BUNDLE_GEMFILE: gemfiles/${{ matrix.gemfile }}
18
18
  strategy:
19
19
  matrix:
20
- ruby-version: ['2.6', '2.7', '3.0', '3.1', 'truffleruby-head', 'jruby-9.3.2.0']
20
+ ruby-version: ['2.6', '2.7', '3.0', '3.1', 'jruby-9.3.2.0']
21
21
  gemfile: [ 'standalone', 'activemodel-5', 'activemodel-6', 'activemodel-7' ]
22
22
  exclude:
23
23
  - ruby-version: '3.0'
data/.rubocop.yml CHANGED
@@ -9,7 +9,16 @@ Metrics/BlockLength:
9
9
  - spec/**/*_spec.rb
10
10
 
11
11
  Style/Documentation:
12
- Enabled: false
12
+ Enabled: false
13
13
 
14
14
  RSpec/MultipleExpectations:
15
- Enabled: false
15
+ Enabled: false
16
+
17
+ Style/StringChars:
18
+ Enabled: false
19
+
20
+ RSpec/NestedGroups:
21
+ Max: 4
22
+
23
+ RSpec/ExampleLength:
24
+ Enabled: false
data/CHANGES.md CHANGED
@@ -1,7 +1,24 @@
1
1
 
2
2
  ### dev
3
3
 
4
- [full changelog](http://github.com/yolk/valvat/compare/v1.1.4...master)
4
+ [full changelog](http://github.com/yolk/valvat/compare/v1.2.0...master)
5
+
6
+ ### 1.2.0 / 2022-09-30
7
+
8
+ [full changelog](http://github.com/yolk/valvat/compare/v1.1.5...v1.2.0)
9
+
10
+ * Implemented lookup of VAT numbers from the UK (via HMRC api and only with :uk option set to true) (by [Adrien Rey-Jarthon](https://github.com/jarthod))
11
+ * Remimplemented VIES lookup using only nethttp (removes dependency on savon)
12
+ * Deprecate require 'valvat/local'. Please require 'valvat' directly.
13
+ * Apply more rules to spanish VAT numbers on checksum validation #115 (by [Thomas Scalise](https://github.com/KirtashW17))
14
+
15
+ ### 1.1.5 / 2022-09-14
16
+
17
+ [full changelog](http://github.com/yolk/valvat/compare/v1.1.4...v1.1.5)
18
+
19
+ * Fixed natural person VAT checksum validation for ES #114 (by [Thomas Scalise](https://github.com/KirtashW17))
20
+ * Better (ruby) code blocks in README #113
21
+ * Minor internal syntax changes / refactorings
5
22
 
6
23
  ### 1.1.4 / 2022-05-05
7
24
 
@@ -14,7 +31,7 @@
14
31
 
15
32
  [full changelog](http://github.com/yolk/valvat/compare/v1.1.2...v1.1.3)
16
33
 
17
- * Handle Savon::HTTPError and Savon::UnknownOperationError as ViesError and throw Valvat::HTTPError and Valvat::OperationUnknown instead.
34
+ * Handle Savon::HTTPError and Savon::UnknownOperationError as LookupError and throw Valvat::HTTPError and Valvat::OperationUnknown instead.
18
35
 
19
36
  ### 1.1.2 / 2021-10-29
20
37
 
data/MIT-LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2011 Yolk Sebastian Munz & Julia Soergel GbR
1
+ Copyright (c) 2011-2022 mite GmbH
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -7,7 +7,7 @@ Validates european vat numbers. Standalone or as a ActiveModel validator.
7
7
 
8
8
  ## A note on Brexit
9
9
 
10
- Valvat supports validating VAT-IDs from the UK by syntax & checksum for now. Validation against the VIES web service will probably stop working (and return `false`) in 2021.
10
+ Valvat supports validating VAT-IDs from the UK by syntax, checksum and using the HMRC API (for backwards compatibility only with the `:uk` option set to true). Validation against the VIES web service stopped working early 2021.
11
11
 
12
12
  Northern Ireland received its own VAT number prefix - XI which is supported by VIES web service so any XI-prefixed VAT numbers should be validated as any EU VAT number.
13
13
 
@@ -15,24 +15,24 @@ Northern Ireland received its own VAT number prefix - XI which is supported by V
15
15
 
16
16
  * Simple syntax verification
17
17
  * Lookup via the VIES web service
18
+ * (Optional) lookup via the HMRC web service (for UK VAT numbers)
18
19
  * ActiveModel/Rails integration
19
20
  * Works standalone without ActiveModel
21
+ * No runtime dependencies
20
22
  * I18n locales for language specific error messages in English, German, French, Spanish, Italian, Portuguese, Polish, Swedish, Dutch, Danish, Czech, Slovakian, Hungarian, Bulgarian, Romanian, Latvian, Catalan, Norwegian, and Finnish.
21
23
  * *Experimental* checksum verification
22
24
 
23
- valvat is tested and works with ruby MRI 2.6/2.7/3.0/3.1, jruby, truffleruby-head and ActiveModel 5/6/7. If you need support for ruby down to 1.9.3 and ActiveModel 3 and 4 use [v1.0.1](https://github.com/yolk/valvat/tree/v1.0.1).
25
+ valvat is tested and works with ruby MRI 2.6/2.7/3.0/3.1, jruby and ActiveModel 5/6/7. If you need support for ruby down to 1.9.3 and ActiveModel 3 and 4 use [v1.0.1](https://github.com/yolk/valvat/tree/v1.0.1).
24
26
 
25
27
  ## Installation
26
28
 
27
29
  Add it to your Gemfile:
28
30
 
29
- gem 'valvat'
31
+ ```ruby
32
+ gem 'valvat'
33
+ ```
30
34
 
31
- To use less memory (~0.5 mb vs. ~3.5 mb) and load only the local verification functionality – and not the remote lookup with VIES – add it like this instead:
32
-
33
- gem 'valvat', require: 'valvat/local'
34
-
35
- In any case run:
35
+ And run:
36
36
 
37
37
  $ bundle
38
38
 
@@ -44,66 +44,96 @@ Or install it yourself as:
44
44
 
45
45
  To verify the syntax of a vat number:
46
46
 
47
- Valvat.new("DE345789003").valid?
48
- => true or false
47
+ ```ruby
48
+ Valvat.new("DE345789003").valid?
49
+ # => true or false
50
+ ```
49
51
 
50
52
  It is also possible to bypass initializing a Valvat instance and check the syntax of a vat number string directly with:
51
53
 
52
- Valvat::Syntax.validate("DE345789003")
53
- => true or false
54
+ ```ruby
55
+ Valvat::Syntax.validate("DE345789003")
56
+ # => true or false
57
+ ```
58
+
59
+ ## Validate against the VIES / HMRC web service
54
60
 
55
- ## Validate agains the VIES web service
61
+ To check if the given vat number exists via the VIES or HMRC web service:
56
62
 
57
- To check if the given vat number exists via the VIES web service:
63
+ ```ruby
64
+ Valvat.new("DE345789003").exists?
65
+ # => true or false or nil
66
+ ```
58
67
 
59
- Valvat.new("DE345789003").exists?
60
- => true or false or nil
68
+ Or to lookup a vat number string directly:
61
69
 
62
- Or to lookup a vat number string directly via VIES web service:
70
+ ```ruby
71
+ Valvat::Lookup.validate("DE345789003")
72
+ # => true or false or nil
73
+ ```
63
74
 
64
- Valvat::Lookup.validate("DE345789003")
65
- => true or false or nil
75
+ To keep backwards compatibility lookups of UK VAT numbers against the HMRC API are only performed with the option `:uk` set to true.
66
76
 
67
- *IMPORTANT* Keep in mind that the VIES web service might be offline at some time for all or some member states. If this happens `exists?` or `Valvat::Lookup.validate` will return `nil`. See *Handling of VIES maintenance errors* for further details.
77
+ ```ruby
78
+ Valvat::Lookup.validate("GB553557881", uk: true)
79
+ # => true or false or nil
80
+ ```
81
+
82
+ Without this option the lookup of UK VAT number always returns `false`.
83
+
84
+ *IMPORTANT* Keep in mind that the web service might be offline at some time for all or some member states. If this happens `exists?` or `Valvat::Lookup.validate` will return `nil`. See *Handling of maintenance errors* for further details.
68
85
 
69
86
  ### Details & request identifier
70
87
 
71
88
  If you need all details and not only if the VAT is valid, pass {detail: true} as second parameter to the lookup call.
72
89
 
73
- Valvat.new("IE6388047V").exists?(detail: true)
74
- => {
75
- :country_code=>"IE", :vat_number => "6388047V", :valid => true,
76
- :request_date => Date.today, :name=>"GOOGLE IRELAND LIMITED",
77
- :address=>"1ST & 2ND FLOOR ,GORDON HOUSE ,BARROW STREET ,DUBLIN 4"
78
- } or false or nil
90
+ ```ruby
91
+ Valvat.new("IE6388047V").exists?(detail: true)
92
+ => {
93
+ :country_code=> "IE", :vat_number => "6388047V", :valid => true,
94
+ :request_date => Date.today, :name=> "GOOGLE IRELAND LIMITED",
95
+ :address=> "1ST & 2ND FLOOR ,GORDON HOUSE ,BARROW STREET ,DUBLIN 4"
96
+ } or false or nil
97
+ ```
79
98
 
80
- According to EU law, or at least as Austria sees it, it's mandatory to verify the VAT number of every new customer, but also to check the VAT number periodicaly. To prove that you have checked the VAT number, the VIES Web service can return a `request_identifier`.
99
+ According to EU law, or at least as Austria sees it, it's mandatory to verify the VAT number of every new customer, but also to check the VAT number periodicaly. To prove that you have checked the VAT number, the web service can return a `request_identifier`.
81
100
 
82
101
  To receive a `request_identifier` you need to pass your own VAT number in the options hash. In this example, Google (VAT IE6388047V) is checking the validity of eBays VAT number (LU21416127)
83
102
 
84
- Valvat.new("LU21416127").exists?(requester: "IE6388047V")
85
- => {
86
- :country_code=>"LU", :vat_number => "21416127", :valid => true,
87
- :request_date => Date.today, :name=>"EBAY EUROPE S.A R.L.",
88
- :address => "22, BOULEVARD ROYAL\nL-2449 LUXEMBOURG",
89
- :company_type => nil, :request_identifier => "some_uniq_string"
90
- } or false or nil
103
+ ```ruby
104
+ Valvat.new("LU21416127").exists?(requester: "IE6388047V")
105
+ => {
106
+ :country_code=>"LU", :vat_number => "21416127", :valid => true,
107
+ :request_date => Date.today, :name=>"EBAY EUROPE S.A R.L.",
108
+ :address => "22, BOULEVARD ROYAL\nL-2449 LUXEMBOURG",
109
+ :company_type => nil, :request_identifier => "some_uniq_string"
110
+ } or false or nil
111
+ ```
91
112
 
92
113
  If the given `requester` is invalid, a `Valvat::InvalidRequester` error is thrown.
93
114
 
94
- ### Handling of VIES maintenance errors
115
+ When requesting a `request_identifier` for a GB VAT number, the requester must be your own GB number; a EU VAT number won't work.
116
+
117
+ Note that when validating UK VAT numbers using the HMRC service, the detail output is modified to match the one from VIES more closely with slight differences remaining:
118
+
119
+ 1. The `request_date` will actually be a (more precise) `Time` instead of a `Date`
120
+ 2. The `address` string will join lines using `\n` instead of `,` so it's more acurate and can be displayed nicely.
121
+
122
+ ### Handling of maintenance errors
95
123
 
96
124
  From time to time the VIES web service for one or all member states is down for maintenance. To handle this kind of temporary errors, `Valvat::Lookup#validate` returns `nil` by default to indicate that there is no way at the moment to say if the given VAT is valid or not. You should revalidate the VAT later. If you prefer an error, use the `raise_error` option:
97
125
 
98
- Valvat.new("IE6388047V").exists?(raise_error: true)
126
+ ```ruby
127
+ Valvat.new("IE6388047V").exists?(raise_error: true)
128
+ ```
99
129
 
100
130
  This raises `Valvat::ServiceUnavailable` or `Valvat::MemberStateUnavailable` instead of returning `nil`.
101
131
 
102
132
  Visit [http://ec.europa.eu/taxation_customs/vies/viesspec.do](http://ec.europa.eu/taxation_customs/vies/viesspec.do) for more accurate information at what time the service for a specific member state will be down.
103
133
 
104
- ### Handling of other VIES errors
134
+ ### Handling of other errors
105
135
 
106
- All other errors accuring while validating against the VIES web service are raised and must be handled by you. These include:
136
+ All other errors accuring while validating against the web service are raised and must be handled by you. These include:
107
137
 
108
138
  * `Valvat::InvalidRequester`
109
139
  * `Valvat::BlockedError`
@@ -113,39 +143,45 @@ All other errors accuring while validating against the VIES web service are rais
113
143
 
114
144
  If you want to suppress all known error cases. Pass in the `raise_error` option set to `false`:
115
145
 
116
- Valvat.new("IE6388047V").exists?(raise_error: false)
146
+ ```ruby
147
+ Valvat.new("IE6388047V").exists?(raise_error: false)
148
+ ```
117
149
 
118
150
  This will return `nil` instead of raising a known error.
119
151
 
120
- ### Set options for the savon client
121
-
122
- Use the `:savon` key to set options for the used savon SOAP client. For example to log all requests:
152
+ ### Set options for the Net::HTTP client
123
153
 
124
- Valvat.new("IE6388047V").exists?(savon: {log: true})
154
+ Use the `:http` key to set options for the http client. These options are directly passed to `Net::HTTP.start`.
125
155
 
126
- Or to use higher timeouts for the requests:
156
+ For example to set timeouts:
127
157
 
128
- Valvat.new("IE6388047V").exists?(savon: {open_timeout: 10, read_timeout: 10})
158
+ ```ruby
159
+ Valvat.new("IE6388047V").exists?(http: { open_timeout: 10, read_timeout: 10 })
160
+ ```
129
161
 
130
162
  ### Skip local validation before lookup
131
163
 
132
- To prevent unnecessary requests, valvat performs a local syntax check before making the request to the VIES web service. If you want to skip this step (for any reason), set the `:skip_local_validation` option to `true`.
164
+ To prevent unnecessary requests, valvat performs a local syntax check before making the request to the web service. If you want to skip this step (for any reason), set the `:skip_local_validation` option to `true`.
133
165
 
134
166
  ## Experimental checksum verification
135
167
 
136
168
  valvat allows to check vat numbers from AT, BE, BG, DE, DK, ES, FR, FI, GR, IE, IT, LU, NL, PL, PT, SE and SI against a checksum calculation. All other member states will fall back to a basic syntax check:
137
169
 
138
- Valvat.new("DE345789003").valid_checksum?
139
- => true or false
170
+ ```ruby
171
+ Valvat.new("DE345789003").valid_checksum?
172
+ # => true or false
173
+ ```
140
174
 
141
- These results are more valuable than a simple syntax check, but keep in mind: they can not replace a lookup via VIES.
175
+ These results are more valuable than a simple syntax check, but keep in mind: they can not replace a lookup via VIES or HMRC.
142
176
 
143
177
  *IMPORTANT* This feature was tested against all vat numbers I could get my hand on, but it is still marked as *experimental* because these calculations are not documented and may return wrong results.
144
178
 
145
179
  To bypass initializing a Valvat instance:
146
180
 
147
- Valvat::Checksum.validate("DE345789003")
148
- => true or false
181
+ ```ruby
182
+ Valvat::Checksum.validate("DE345789003")
183
+ # => true or false
184
+ ```
149
185
 
150
186
  ## Usage with ActiveModel / Rails
151
187
 
@@ -153,7 +189,9 @@ To bypass initializing a Valvat instance:
153
189
 
154
190
  When the valvat gem is required and ActiveModel is already loaded, everything will work fine out of the box. If your load order differs just add
155
191
 
156
- require 'active_model/validations/valvat_validator'
192
+ ```ruby
193
+ require 'active_model/validations/valvat_validator'
194
+ ```
157
195
 
158
196
  after ActiveModel has been loaded.
159
197
 
@@ -161,35 +199,53 @@ after ActiveModel has been loaded.
161
199
 
162
200
  To validate the attribute `vat_number` add this to your model:
163
201
 
164
- class MyModel < ActiveRecord::Base
165
- validates :vat_number, valvat: true
166
- end
202
+ ```ruby
203
+ class MyModel < ActiveRecord::Base
204
+ validates :vat_number, valvat: true
205
+ end
206
+ ```
167
207
 
168
208
  ### Additional lookup validation
169
209
 
170
- To additionally perform a lookup via VIES:
210
+ To additionally perform an lookup via VIES:
211
+
212
+ ```ruby
213
+ validates :vat_number, valvat: { lookup: true }
214
+ ```
215
+
216
+ To also perform an lookup via HMRC for UK VAT numbers:
171
217
 
172
- validates :vat_number, valvat: {lookup: true}
218
+ ```ruby
219
+ validates :vat_number, valvat: { lookup: { uk: true } }
220
+ ```
173
221
 
174
- By default this will validate to true if the VIES web service is down. To fail in this case simply add the `:fail_if_down` option:
222
+ By default this will validate to true if the web service is down. To fail in this case simply add the `:fail_if_down` option:
175
223
 
176
- validates :vat_number, valvat: {lookup: {fail_if_down: true}}
224
+ ```ruby
225
+ validates :vat_number, valvat: { lookup: { fail_if_down: true } }
226
+ ```
177
227
 
178
228
  You can pass in any options accepted by `Valvat::Lookup#validate`:
179
229
 
180
- validates :vat_number, valvat: {lookup: {raise_error: true, savon: {log: true}}}
230
+ ```ruby
231
+ validates :vat_number, valvat: { lookup: { raise_error: true, http: { read_timeout: 12 } } }
232
+ ```
181
233
 
182
234
  ### Additional (and experimental) checksum validation
183
235
 
184
236
  To additionally perform a checksum validation:
185
237
 
186
- validates :vat_number, valvat: {checksum: true}
238
+ ```ruby
239
+ validates :vat_number, valvat: { checksum: true }
240
+ ```
187
241
 
188
242
  ### Additional ISO country code validation
189
243
 
190
244
  If you want the vat number’s (ISO) country to match another country attribute, use the _match_country_ option:
191
245
 
192
- validates :vat_number, valvat: {match_country: :country}
246
+ ```ruby
247
+ validates :vat_number, valvat: { match_country: :country }
248
+ ```
193
249
 
194
250
  where it is supposed that your model has a method named _country_ which returns the country ISO code you want to match.
195
251
 
@@ -197,48 +253,62 @@ where it is supposed that your model has a method named _country_ which returns
197
253
 
198
254
  By default blank vat numbers validate to false. To change this add the `:allow_blank` option:
199
255
 
200
- validates :vat_number, valvat: {allow_blank: true}
256
+ ```ruby
257
+ validates :vat_number, valvat: { allow_blank: true }
258
+ ```
201
259
 
202
260
  ### Allow vat numbers outside of europe
203
261
 
204
262
  To allow vat numbers from outside of europe, add something like this to your model (country_code should return a upcase ISO country code):
205
263
 
206
- class MyModel < ActiveRecord::Base
207
- validates :vat_number, valvat: true, if: :eu?
264
+ ```ruby
265
+ class MyModel < ActiveRecord::Base
266
+ validates :vat_number, valvat: true, if: :eu?
208
267
 
209
- def eu?
210
- Valvat::Utils::EU_MEMBER_STATES.include?(country_code)
211
- end
212
- end
268
+ def eu?
269
+ Valvat::Utils::EU_MEMBER_STATES.include?(country_code)
270
+ end
271
+ end
272
+ ```
213
273
 
214
274
  ## Utilities
215
275
 
216
276
  To split a vat number into the country code and the remaining chars:
217
277
 
218
- Valvat::Utils.split("ATU345789003")
219
- => ["AT", "U345789003"]
278
+ ```ruby
279
+ Valvat::Utils.split("ATU345789003")
280
+ # => ["AT", "U345789003"]
281
+ ```
220
282
 
221
283
  or
222
284
 
223
- Valvat.new("ATU345789003").to_a
224
- => ["AT", "U345789003"]
285
+ ```ruby
286
+ Valvat.new("ATU345789003").to_a
287
+ # => ["AT", "U345789003"]
288
+ ```
225
289
 
226
290
  Both methods always return an array. If it can not detect the country or the given country is located outside of europe it returns `[nil, nil]`. Please note that this does not strictly return the ISO country code: for greek vat numbers this returns the ISO language code 'EL' instead of the ISO country code 'GR'.
227
291
 
228
292
  To extract the ISO country code of a given vat number:
229
293
 
230
- Valvat.new("EL7345789003").iso_country_code
231
- => "GR"
294
+ ```ruby
295
+ Valvat.new("EL7345789003").iso_country_code
296
+ # => "GR"
297
+ ```
232
298
 
233
299
  To extract the vat country code (first two chars in every european vat number):
234
300
 
235
- Valvat.new("EL7345789003").vat_country_code
236
- => "EL"
301
+ ```ruby
302
+ Valvat.new("EL7345789003").vat_country_code
303
+ # => "EL"
304
+ ```
237
305
 
238
306
  To normalize a vat number:
239
307
 
240
- Valvat::Utils.normalize("atu345789003")
241
- => "ATU345789003"
308
+ ```ruby
309
+ Valvat::Utils.normalize("atu345789003")
310
+ # => "ATU345789003"
311
+ ```
242
312
 
243
313
  This basically just removes trailing spaces and ensures all chars are uppercase.
244
314
 
@@ -249,6 +319,7 @@ There seems to be a problem when using the VIES service over IPv6. Sadly this is
249
319
  ## Links
250
320
 
251
321
  * [VIES web service](http://ec.europa.eu/taxation_customs/vies)
322
+ * [HMRC web service](https://developer.service.hmrc.gov.uk/api-documentation/docs/api/service/vat-registered-companies-api/1.0)
252
323
  * [European vat number formats (german)](http://bzst.de/DE/Steuern_International/USt_Identifikationsnummer/Merkblaetter/Aufbau_USt_IdNr.html)
253
324
  * [European vat number formats on Wikipedia](http://en.wikipedia.org/wiki/European_Union_Value_Added_Tax)
254
325
 
@@ -258,7 +329,7 @@ https://github.com/yolk/valvat/graphs/contributors
258
329
 
259
330
  ## BlaBla
260
331
 
261
- Copyright (c) 2011-2022 Yolk Sebastian Munz & Julia Soergel GbR
332
+ Copyright (c) 2011-2022 mite GmbH
262
333
 
263
334
  Beyond that, the implementation is licensed under the MIT License.
264
335
 
@@ -3,5 +3,8 @@ source "https://rubygems.org"
3
3
  gem "activemodel", "~> 6.0"
4
4
 
5
5
  gem 'rack'
6
+ gem 'net-smtp', require: false
7
+ gem 'net-imap', require: false
8
+ gem 'net-pop', require: false
6
9
 
7
10
  gemspec path: "../"
@@ -3,5 +3,8 @@ source "https://rubygems.org"
3
3
  gem "activemodel", "~> 7.0"
4
4
 
5
5
  gem 'rack'
6
+ gem 'net-smtp', require: false
7
+ gem 'net-imap', require: false
8
+ gem 'net-pop', require: false
6
9
 
7
10
  gemspec path: "../"
data/gemfiles/standalone CHANGED
@@ -1,5 +1,8 @@
1
1
  source "https://rubygems.org"
2
2
 
3
3
  gem 'rack', '< 2'
4
+ gem 'net-smtp', require: false
5
+ gem 'net-imap', require: false
6
+ gem 'net-pop', require: false
4
7
 
5
8
  gemspec path: "../"
@@ -74,7 +74,7 @@ module ActiveModel
74
74
  message: options[:message],
75
75
  country_adjective: I18n.translate(
76
76
  :"valvat.country_adjectives.#{iso_country_code.downcase}",
77
- default: [:"valvat.country_adjectives.eu", 'european']
77
+ default: [:'valvat.country_adjectives.eu', 'european']
78
78
  ))
79
79
  end
80
80
 
@@ -4,32 +4,53 @@ class Valvat
4
4
  module Checksum
5
5
  class ES < Base
6
6
  NATURAL_PERSON_CHARS = %w[T R W A G M Y F P D X B N J Z S Q V H L C K E].freeze
7
- NATURAL_PERSON_EXP = /\A(\d{8}[ABCDEFGHJKLMNPQRSTVWXYZ]|[KLMXYZ]\d{7}[ABCDEFGHJKLMNPQRSTVWXYZ])\Z/.freeze
7
+ NATURAL_PERSON_EXP = /\A[KLMXYZ\d]/.freeze
8
8
  LEGAL_PERSON_CHARS = [false] + %w[A B C D E F G H I J]
9
- LEGAL_PERSON_EXP = /\A[NPQRSW]\d{7}[ABCDEFGHIJ]\Z/.freeze
10
9
  NIE_DIGIT_BY_LETTER = %w[X Y Z].freeze
10
+ GIVEN_CD_IS_A_LETTER_EXP = /[A-Z]\Z/.freeze
11
+ LEGAL_PERSON_EXP = /\A[ABCDEFGHJUVNPQRSW]/.freeze
12
+ CIF_MUST_BE_A_LETTER_EXP = /\A[NPQRSW]/.freeze
13
+ CIF_MUST_BE_A_NUMBER_EXP = /\A[HJUV]/.freeze
14
+ SPECIAL_NIF_EXP = /\A[KLM]/.freeze
11
15
 
12
- def check_digit
13
- natural_person? ? check_digit_natural_person : check_digit_legal_person
16
+ def validate
17
+ passes_special_validations? && possible_check_digits.include?(given_check_digit)
14
18
  end
15
19
 
16
- def check_digit_natural_person
20
+ private
21
+
22
+ def passes_special_validations?
23
+ !(
24
+ # [KLM]: CD first two numerical digits must be between 01 and 56 (both inclusive)
25
+ (vat.to_s_wo_country =~ SPECIAL_NIF_EXP &&
26
+ vat.to_s_wo_country[1..2].to_i > 56) or vat.to_s_wo_country[1..2].to_i < 0o1 ||
27
+ # Exceptions: X0000000T, 00000001R, 00000000T, 99999999R are invalid.
28
+ %w[X0000000T 00000001R 00000000T 99999999R].include?(vat.to_s_wo_country)
29
+ )
30
+ end
31
+
32
+ def given_check_digit
33
+ given_cd_is_a_letter? ? str_wo_country[-1] : super
34
+ end
35
+
36
+ def possible_check_digits
37
+ natural_person? ? possible_cd_natural_person : possible_cds_legal_person
38
+ end
39
+
40
+ def possible_cd_natural_person
17
41
  letter = vat.to_s_wo_country[0]
18
42
  nie_digit = NIE_DIGIT_BY_LETTER.index(letter)
19
- NATURAL_PERSON_CHARS["#{nie_digit}#{figures_str}".to_i.modulo(23)]
43
+ [NATURAL_PERSON_CHARS["#{nie_digit}#{figures_str}".to_i.modulo(23)]]
20
44
  end
21
45
 
22
- def check_digit_legal_person
46
+ def possible_cds_legal_person
23
47
  chk = 10 - sum_of_figures_for_at_es_it_se(reverse_ints: true).modulo(10)
24
- if legal_foreign_person?
25
- LEGAL_PERSON_CHARS[chk]
26
- else
27
- (chk == 10 ? 0 : chk)
48
+ possible_check_digits = []
49
+ possible_check_digits << LEGAL_PERSON_CHARS[chk] if cd_can_be_a_letter?
50
+ if cd_can_be_a_num?
51
+ possible_check_digits << (chk == 10 ? 0 : chk)
28
52
  end
29
- end
30
-
31
- def given_check_digit
32
- person? ? str_wo_country[-1] : super
53
+ possible_check_digits
33
54
  end
34
55
 
35
56
  def str_wo_country
@@ -46,7 +67,19 @@ class Valvat
46
67
  end
47
68
 
48
69
  def legal_foreign_person?
49
- !!(vat.to_s_wo_country =~ LEGAL_PERSON_EXP)
70
+ !!(vat.to_s_wo_country =~ FOREIGN_LEGAL_PERSON_EXP)
71
+ end
72
+
73
+ def cd_can_be_a_letter?
74
+ vat.to_s_wo_country !~ CIF_MUST_BE_A_NUMBER_EXP
75
+ end
76
+
77
+ def cd_can_be_a_num?
78
+ vat.to_s_wo_country !~ CIF_MUST_BE_A_LETTER_EXP
79
+ end
80
+
81
+ def given_cd_is_a_letter?
82
+ !!(vat.to_s_wo_country =~ GIVEN_CD_IS_A_LETTER_EXP)
50
83
  end
51
84
  end
52
85
  end
@@ -5,7 +5,7 @@ class Valvat
5
5
  class FR < Base
6
6
  def check_digit
7
7
  siren = str_wo_country[2..-1].to_i
8
- (12 + (3 * siren) % 97) % 97
8
+ (12 + ((3 * siren) % 97)) % 97
9
9
  end
10
10
 
11
11
  def given_check_digit
@@ -13,7 +13,7 @@ class Valvat
13
13
  product = (2 * sum) % 11
14
14
  end
15
15
 
16
- (10 - (product - 1) % 10) % 10
16
+ (10 - ((product - 1) % 10)) % 10
17
17
  end
18
18
  end
19
19
  end
@@ -10,7 +10,7 @@ class Valvat
10
10
  digit * multipliers[index]
11
11
  end
12
12
 
13
- (10 - sum % 10) % 10
13
+ (10 - (sum % 10)) % 10
14
14
  end
15
15
  end
16
16
  end