valvat 1.4.1 → 1.4.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/lib/valvat/version.rb +1 -1
  4. data.tar.gz.sig +0 -0
  5. metadata +34 -82
  6. metadata.gz.sig +0 -0
  7. data/.editorconfig +0 -15
  8. data/.github/workflows/rubocop.yml +0 -17
  9. data/.github/workflows/specs.yml +0 -47
  10. data/.gitignore +0 -9
  11. data/.rubocop.yml +0 -24
  12. data/CHANGES.md +0 -419
  13. data/Gemfile +0 -14
  14. data/Guardfile +0 -7
  15. data/MIT-LICENSE +0 -20
  16. data/README.md +0 -350
  17. data/Rakefile +0 -10
  18. data/certs/mite.pem +0 -26
  19. data/gemfiles/activemodel-5 +0 -8
  20. data/gemfiles/activemodel-6 +0 -8
  21. data/gemfiles/activemodel-7 +0 -8
  22. data/gemfiles/standalone +0 -7
  23. data/spec/active_model/validations/valvat_validator_spec.rb +0 -274
  24. data/spec/spec_helper.rb +0 -37
  25. data/spec/valvat/checksum/at_spec.rb +0 -17
  26. data/spec/valvat/checksum/be_spec.rb +0 -17
  27. data/spec/valvat/checksum/bg_spec.rb +0 -18
  28. data/spec/valvat/checksum/cy_spec.rb +0 -17
  29. data/spec/valvat/checksum/de_spec.rb +0 -17
  30. data/spec/valvat/checksum/dk_spec.rb +0 -17
  31. data/spec/valvat/checksum/ee_spec.rb +0 -17
  32. data/spec/valvat/checksum/es_spec.rb +0 -65
  33. data/spec/valvat/checksum/fi_spec.rb +0 -17
  34. data/spec/valvat/checksum/fr_spec.rb +0 -17
  35. data/spec/valvat/checksum/gb_spec.rb +0 -34
  36. data/spec/valvat/checksum/gr_spec.rb +0 -17
  37. data/spec/valvat/checksum/hr_spec.rb +0 -17
  38. data/spec/valvat/checksum/hu_spec.rb +0 -17
  39. data/spec/valvat/checksum/ie_spec.rb +0 -24
  40. data/spec/valvat/checksum/it_spec.rb +0 -25
  41. data/spec/valvat/checksum/lt_spec.rb +0 -17
  42. data/spec/valvat/checksum/lu_spec.rb +0 -17
  43. data/spec/valvat/checksum/mt_spec.rb +0 -17
  44. data/spec/valvat/checksum/nl_spec.rb +0 -17
  45. data/spec/valvat/checksum/pl_spec.rb +0 -21
  46. data/spec/valvat/checksum/pt_spec.rb +0 -30
  47. data/spec/valvat/checksum/ro_spec.rb +0 -17
  48. data/spec/valvat/checksum/se_spec.rb +0 -21
  49. data/spec/valvat/checksum/si_spec.rb +0 -25
  50. data/spec/valvat/checksum_spec.rb +0 -40
  51. data/spec/valvat/lookup/hmrc_spec.rb +0 -58
  52. data/spec/valvat/lookup/vies_spec.rb +0 -25
  53. data/spec/valvat/lookup_spec.rb +0 -493
  54. data/spec/valvat/options_spec.rb +0 -23
  55. data/spec/valvat/syntax_spec.rb +0 -68
  56. data/spec/valvat/utils_spec.rb +0 -125
  57. data/spec/valvat_spec.rb +0 -276
  58. data/valvat.gemspec +0 -24
data/README.md DELETED
@@ -1,350 +0,0 @@
1
- valvat
2
- ===========
3
-
4
- [![rubygems](https://badgen.net/rubygems/v/valvat)](https://rubygems.org/gems/valvat) [![Specs](https://github.com/yolk/valvat/workflows/Specs/badge.svg)](https://github.com/yolk/valvat/actions?query=workflow%3ASpecs)
5
-
6
- Validates european vat numbers. Standalone or as a ActiveModel validator.
7
-
8
- ## A note on Brexit
9
-
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
-
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
-
14
- ## Features
15
-
16
- * Simple syntax verification
17
- * Lookup via the VIES web service
18
- * (Optional) lookup via the HMRC web service (for UK VAT numbers)
19
- * ActiveModel/Rails integration
20
- * Works standalone without ActiveModel
21
- * Minimal runtime dependencies
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.
23
- * *Experimental* checksum verification
24
-
25
- valvat is tested and works with ruby MRI 2.6/2.7/3.0/3.1/3.2, 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).
26
-
27
- ## Installation
28
-
29
- Add it to your Gemfile:
30
-
31
- ```ruby
32
- gem 'valvat'
33
- ```
34
-
35
- And run:
36
-
37
- $ bundle
38
-
39
- Or install it yourself as:
40
-
41
- $ gem install valvat
42
-
43
- ## Validate the syntax of a VAT number
44
-
45
- To verify the syntax of a vat number:
46
-
47
- ```ruby
48
- Valvat.new("DE345789003").valid?
49
- # => true or false
50
- ```
51
-
52
- It is also possible to bypass initializing a Valvat instance and check the syntax of a vat number string directly with:
53
-
54
- ```ruby
55
- Valvat::Syntax.validate("DE345789003")
56
- # => true or false
57
- ```
58
-
59
- ## Validate against the VIES / HMRC web service
60
-
61
- To check if the given vat number exists via the VIES or HMRC web service:
62
-
63
- ```ruby
64
- Valvat.new("DE345789003").exists?
65
- # => true or false or nil
66
- ```
67
-
68
- Or to lookup a vat number string directly:
69
-
70
- ```ruby
71
- Valvat::Lookup.validate("DE345789003")
72
- # => true or false or nil
73
- ```
74
-
75
- To keep backwards compatibility lookups of UK VAT numbers against the HMRC API are only performed with the option `:uk` set to true.
76
-
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.
85
-
86
- ### Details & request identifier
87
-
88
- If you need all details and not only if the VAT is valid, pass {detail: true} as second parameter to the lookup call.
89
-
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
- ```
98
-
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`.
100
-
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)
102
-
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
- ```
112
-
113
- If the given `requester` is invalid, a `Valvat::InvalidRequester` error is thrown.
114
-
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
123
-
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:
125
-
126
- ```ruby
127
- Valvat.new("IE6388047V").exists?(raise_error: true)
128
- ```
129
-
130
- This raises `Valvat::ServiceUnavailable` or `Valvat::MemberStateUnavailable` instead of returning `nil`.
131
-
132
- Visit [https://ec.europa.eu/taxation_customs/vies/#/help](https://ec.europa.eu/taxation_customs/vies/#/help) for more accurate information at what time the service for a specific member state will be down.
133
-
134
- ### Handling of other errors
135
-
136
- All other errors accuring while validating against the web service are raised and must be handled by you. These include:
137
-
138
- * `Valvat::InvalidRequester`
139
- * `Valvat::BlockedError`
140
- * `Valvat::RateLimitError`
141
- * `Valvat::Timeout`
142
- * all IO errors
143
-
144
- If you want to suppress all known error cases. Pass in the `raise_error` option set to `false`:
145
-
146
- ```ruby
147
- Valvat.new("IE6388047V").exists?(raise_error: false)
148
- ```
149
-
150
- This will return `nil` instead of raising a known error.
151
-
152
- ### Set options for the Net::HTTP client
153
-
154
- Use the `:http` key to set options for the http client. These options are directly passed to `Net::HTTP.start`.
155
-
156
- For example to set timeouts:
157
-
158
- ```ruby
159
- Valvat.new("IE6388047V").exists?(http: { open_timeout: 10, read_timeout: 10 })
160
- ```
161
-
162
- ### Skip local validation before lookup
163
-
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`.
165
-
166
- ## Experimental checksum verification
167
-
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:
169
-
170
- ```ruby
171
- Valvat.new("DE345789003").valid_checksum?
172
- # => true or false
173
- ```
174
-
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.
176
-
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.
178
-
179
- To bypass initializing a Valvat instance:
180
-
181
- ```ruby
182
- Valvat::Checksum.validate("DE345789003")
183
- # => true or false
184
- ```
185
-
186
- ## Configuration
187
-
188
- Instead of passing in the same options again and again, Valvat allows to alter its default configuration. This feature is intended to be used when initializing your application (for example in a Rails initializer file).
189
-
190
- ```ruby
191
- Valvat.configure(
192
- uk: true,
193
- raise_error: true,
194
- http: { read_timeout: 5 }
195
- )
196
- ```
197
-
198
- To see all options and the defaults, take a look at [valvat/configuration](https://github.com/yolk/valvat/blob/master/lib/valvat/configuration.rb#L25).
199
-
200
- ## Usage with ActiveModel / Rails
201
-
202
- ### Loading
203
-
204
- 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
205
-
206
- ```ruby
207
- require 'active_model/validations/valvat_validator'
208
- ```
209
-
210
- after ActiveModel has been loaded.
211
-
212
- ### Simple syntax validation
213
-
214
- To validate the attribute `vat_number` add this to your model:
215
-
216
- ```ruby
217
- class MyModel < ActiveRecord::Base
218
- validates :vat_number, valvat: true
219
- end
220
- ```
221
-
222
- ### Additional lookup validation
223
-
224
- To additionally perform an lookup via VIES:
225
-
226
- ```ruby
227
- validates :vat_number, valvat: { lookup: true }
228
- ```
229
-
230
- To also perform an lookup via HMRC for UK VAT numbers:
231
-
232
- ```ruby
233
- validates :vat_number, valvat: { lookup: { uk: true } }
234
- ```
235
-
236
- 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:
237
-
238
- ```ruby
239
- validates :vat_number, valvat: { lookup: { fail_if_down: true } }
240
- ```
241
-
242
- You can pass in any options accepted by `Valvat::Lookup#validate`:
243
-
244
- ```ruby
245
- validates :vat_number, valvat: { lookup: { raise_error: true, http: { read_timeout: 12 } } }
246
- ```
247
-
248
- ### Additional (and experimental) checksum validation
249
-
250
- To additionally perform a checksum validation:
251
-
252
- ```ruby
253
- validates :vat_number, valvat: { checksum: true }
254
- ```
255
-
256
- ### Additional ISO country code validation
257
-
258
- If you want the vat number’s (ISO) country to match another country attribute, use the _match_country_ option:
259
-
260
- ```ruby
261
- validates :vat_number, valvat: { match_country: :country }
262
- ```
263
-
264
- where it is supposed that your model has a method named _country_ which returns the country ISO code you want to match.
265
-
266
- ### Allow blank
267
-
268
- By default blank vat numbers validate to false. To change this add the `:allow_blank` option:
269
-
270
- ```ruby
271
- validates :vat_number, valvat: { allow_blank: true }
272
- ```
273
-
274
- ### Allow vat numbers outside of europe
275
-
276
- To allow vat numbers from outside of europe, add something like this to your model (country_code should return a upcase ISO country code):
277
-
278
- ```ruby
279
- class MyModel < ActiveRecord::Base
280
- validates :vat_number, valvat: true, if: :eu?
281
-
282
- def eu?
283
- Valvat::Utils::EU_MEMBER_STATES.include?(country_code)
284
- end
285
- end
286
- ```
287
-
288
- ## Utilities
289
-
290
- To split a vat number into the country code and the remaining chars:
291
-
292
- ```ruby
293
- Valvat::Utils.split("ATU345789003")
294
- # => ["AT", "U345789003"]
295
- ```
296
-
297
- or
298
-
299
- ```ruby
300
- Valvat.new("ATU345789003").to_a
301
- # => ["AT", "U345789003"]
302
- ```
303
-
304
- 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'.
305
-
306
- To extract the ISO country code of a given vat number:
307
-
308
- ```ruby
309
- Valvat.new("EL7345789003").iso_country_code
310
- # => "GR"
311
- ```
312
-
313
- To extract the vat country code (first two chars in every european vat number):
314
-
315
- ```ruby
316
- Valvat.new("EL7345789003").vat_country_code
317
- # => "EL"
318
- ```
319
-
320
- To normalize a vat number:
321
-
322
- ```ruby
323
- Valvat::Utils.normalize("atu345789003")
324
- # => "ATU345789003"
325
- ```
326
-
327
- This basically just removes trailing spaces and ensures all chars are uppercase.
328
-
329
- ## Usage with IPv6
330
-
331
- There seems to be a problem when using the VIES service over IPv6. Sadly this is nothing this gem can address. For details and proposed solutions have a look at [this question on StackOverflow](http://stackoverflow.com/questions/15616833/vies-vat-api-soap-error-ipv6). Thanks to George Palmer for bringing up this issue.
332
-
333
- ## Links
334
-
335
- * [VIES web service](http://ec.europa.eu/taxation_customs/vies)
336
- * [HMRC web service](https://developer.service.hmrc.gov.uk/api-documentation/docs/api/service/vat-registered-companies-api/1.0)
337
- * [European vat number formats (german)](http://bzst.de/DE/Steuern_International/USt_Identifikationsnummer/Merkblaetter/Aufbau_USt_IdNr.html)
338
- * [European vat number formats on Wikipedia](http://en.wikipedia.org/wiki/European_Union_Value_Added_Tax)
339
-
340
- ## Contributions by
341
-
342
- https://github.com/yolk/valvat/graphs/contributors
343
-
344
- ## BlaBla
345
-
346
- Copyright (c) 2011-2023 mite GmbH
347
-
348
- Beyond that, the implementation is licensed under the MIT License.
349
-
350
- Code was originally extracted from our time tracking webapp [mite](https://mite.de/en/).
data/Rakefile DELETED
@@ -1,10 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'bundler'
4
- Bundler::GemHelper.install_tasks
5
-
6
- require 'rspec/core/rake_task'
7
-
8
- RSpec::Core::RakeTask.new(:spec)
9
-
10
- task default: :spec
data/certs/mite.pem DELETED
@@ -1,26 +0,0 @@
1
- -----BEGIN CERTIFICATE-----
2
- MIIEbDCCAtSgAwIBAgIBATANBgkqhkiG9w0BAQsFADA+MRIwEAYDVQQDDAlzZWJh
3
- c3RpYW4xFDASBgoJkiaJk/IsZAEZFgRtaXRlMRIwEAYKCZImiZPyLGQBGRYCZGUw
4
- HhcNMjMwNDE5MDkxMzEyWhcNMjQwNDE4MDkxMzEyWjA+MRIwEAYDVQQDDAlzZWJh
5
- c3RpYW4xFDASBgoJkiaJk/IsZAEZFgRtaXRlMRIwEAYKCZImiZPyLGQBGRYCZGUw
6
- ggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQDAWAF/CaDp0cmY7Q2vAqVn
7
- TpB3xmKKPNfF1Bh9X3P9pKRBl2iCW+JmqIV+J5Yts9mB+OYKfxjJM7mmQwT8DMf2
8
- KwYIVISGKooRyXPgGgKepYfSfemizey6soCoejIIEHczsRk/FeKcvwlFrqMymBrF
9
- QP5XhnF0TEQvg/sG97wt8hHH7FwcNn+m8I88abP7ygVMNNOL18EiPd2b/WqalGp0
10
- aiN/CyGtJdA766QY/wgeYVEHNszzJ3DD7AYy8PWAwouIqmAmdDx7oHu01yyilIHL
11
- W1l5fqko8TQ3UZjfQBDn4mwUgXT829E7dtQB5O0pkwB2lSY4L2azuC69nVBv7TsB
12
- nBBCTKqr4JknuMJ1nwoGmOfgVqhmsuiGtMyabtagPg1DUpoXMYuf/PbhmSsgedgH
13
- j2nCnREKxACA/A1pG3HyDhYqkeb7VA4M1Fx4s1wHXKZw/pmxCxCbB/w34wwV2OUh
14
- fOtjTuX5/o5Tza2dIeBaENs8xMjqIX6DshtWbrJwyacCAwEAAaN1MHMwCQYDVR0T
15
- BAIwADALBgNVHQ8EBAMCBLAwHQYDVR0OBBYEFLjadA9ioIK4kItaOGJOhPYM/dVJ
16
- MBwGA1UdEQQVMBOBEXNlYmFzdGlhbkBtaXRlLmRlMBwGA1UdEgQVMBOBEXNlYmFz
17
- dGlhbkBtaXRlLmRlMA0GCSqGSIb3DQEBCwUAA4IBgQCQtG2K4dDwQhBkCpSgP8sC
18
- rc8v5siwMa306nG9Bs3c+KbVI8xJM8APqG8y+DUGzx0i+AIE9g5i2c7H9rwXSA9t
19
- BRTXZ6O7Hjmkn4pUC8Yc2ylNgP9pdpYxqwe6ZVah8DdGW7m/dQwSisKtO+0XFwB8
20
- rJmI29qalNK4bzk+DOW9pMdIfIHsbFU7pzTcFBux/MzIqQO24A+zcdYIz7MHBucF
21
- 85qF319BKW5/HgZMgxm26obTKJFEMDODYlNmm5ywvQCHSCyJ1yW/IFiCpqhiLm5w
22
- R8JZvYWO38fAsYF3VowUCmsqOBdaQo+L3aA/NVmhNeh4LddJwjrqY+Duw2Gz+DdP
23
- VyquPzH92Wc7Etd50IFILEkNV2VvRctuyY5/TAWoLKI9RQGYpKxd4jqZRtZFfODY
24
- O1ARwPz8pN+xIvxo8ex8Hz1sazm/iFgVBwHgaI3O3ctK7vF4+fAu6dlLcbEpij9z
25
- 4QlUng62OJRSBV/ejaTTItcAOXBeh028ZFWC0QQR4r0=
26
- -----END CERTIFICATE-----
@@ -1,8 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- gem 'activemodel', '~> 5.0'
4
- gem 'rake'
5
- gem 'rspec', '~> 3.0'
6
- gem 'webmock', '~> 3.0'
7
-
8
- gemspec path: '../'
@@ -1,8 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- gem 'activemodel', '~> 6.0'
4
- gem 'rake'
5
- gem 'rspec', '~> 3.0'
6
- gem 'webmock', '~> 3.0'
7
-
8
- gemspec path: '../'
@@ -1,8 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- gem 'activemodel', '~> 7.0'
4
- gem 'rake'
5
- gem 'rspec', '~> 3.0'
6
- gem 'webmock', '~> 3.0'
7
-
8
- gemspec path: '../'
data/gemfiles/standalone DELETED
@@ -1,7 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- gem 'rake'
4
- gem 'rspec', '~> 3.0'
5
- gem 'webmock', '~> 3.0'
6
-
7
- gemspec path: '../'
@@ -1,274 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'spec_helper'
4
-
5
- if defined?(ActiveModel)
6
- class Invoice < ModelBase
7
- validates :vat_number, valvat: true
8
- end
9
-
10
- class InvoiceWithLookup < ModelBase
11
- validates :vat_number, valvat: { lookup: true }
12
- end
13
-
14
- class InvoiceWithLookupAndFailIfDown < ModelBase
15
- validates :vat_number, valvat: { lookup: :fail_if_down }
16
- end
17
-
18
- class InvoiceAllowBlank < ModelBase
19
- validates :vat_number, valvat: { allow_blank: true }
20
- end
21
-
22
- class InvoiceAllowBlankOnAll < ModelBase
23
- validates :vat_number, valvat: true, allow_blank: true
24
- end
25
-
26
- class InvoiceCheckCountry < ModelBase
27
- validates :vat_number, valvat: { match_country: :country }
28
-
29
- def country
30
- @attributes[:country]
31
- end
32
- end
33
-
34
- class InvoiceCheckCountryWithLookup < ModelBase
35
- validates :vat_number, valvat: { match_country: :country, lookup: true }
36
-
37
- def country
38
- @attributes[:country]
39
- end
40
- end
41
-
42
- class InvoiceWithChecksum < ModelBase
43
- validates :vat_number, valvat: { checksum: true }
44
- end
45
-
46
- describe Invoice do
47
- before do
48
- I18n.locale = :en
49
- end
50
-
51
- context 'with valid VAT number' do
52
- it 'is valid' do
53
- expect(described_class.new(vat_number: 'DE259597697')).to be_valid
54
- end
55
- end
56
-
57
- context 'with invalid VAT number' do
58
- let(:invoice) { described_class.new(vat_number: 'DE259597697123') }
59
-
60
- it 'is not valid' do
61
- expect(invoice).not_to be_valid
62
- end
63
-
64
- it 'adds default (country specific) error message' do
65
- invoice.valid?
66
- expect(invoice.errors[:vat_number]).to eql(['is not a valid German VAT number'])
67
- end
68
-
69
- context 'with DE locale' do
70
- before do
71
- I18n.locale = :de
72
- end
73
-
74
- it 'adds translated error message' do
75
- invoice.valid?
76
- expect(invoice.errors[:vat_number]).to eql(['ist keine gültige deutsche USt-IdNr.'])
77
- end
78
- end
79
-
80
- context 'with PT locale' do
81
- before do
82
- I18n.locale = :pt
83
- end
84
-
85
- it 'adds translated error message' do
86
- invoice.valid?
87
- expect(invoice.errors[:vat_number]).to eql(['O NIF alemão não é válido.'])
88
- end
89
- end
90
-
91
- context 'with i18n translation in place' do
92
- before do
93
- I18n.backend.store_translations(:en, activemodel: {
94
- errors: { models: { invoice: { invalid_vat: 'is ugly.' } } }
95
- })
96
- end
97
-
98
- after { I18n.reload! }
99
-
100
- it 'uses translation' do
101
- invoice.valid?
102
- expect(invoice.errors[:vat_number]).to eql(['is ugly.'])
103
- end
104
- end
105
-
106
- context 'with i18n translation with country_adjective placeholder in place' do
107
- before do
108
- msg = 'is not a %{country_adjective} vat' # rubocop:disable Style/FormatStringToken
109
- translation = { activemodel: { errors: { models: { invoice: { invalid_vat: msg } } } } }
110
- I18n.backend.store_translations(:en, translation)
111
- end
112
-
113
- after { I18n.reload! }
114
-
115
- it 'replaces country_adjective placeholder' do
116
- invoice = described_class.new(vat_number: 'IE123')
117
- invoice.valid?
118
- expect(invoice.errors[:vat_number]).to eql(['is not a Irish vat'])
119
- end
120
-
121
- it "falls back to 'European' if country is missing" do
122
- invoice = described_class.new(vat_number: 'XX123')
123
- invoice.valid?
124
- expect(invoice.errors[:vat_number]).to eql(['is not a European vat'])
125
- end
126
- end
127
- end
128
-
129
- context 'with blank VAT number' do
130
- it 'is not valid' do
131
- expect(described_class.new(vat_number: '')).not_to be_valid
132
- expect(described_class.new(vat_number: nil)).not_to be_valid
133
- end
134
- end
135
- end
136
-
137
- describe InvoiceWithLookup do
138
- context 'with valid but not existing VAT number' do
139
- before do
140
- allow(Valvat::Syntax).to receive_messages(validate: true)
141
- allow(Valvat::Lookup).to receive_messages(validate: false)
142
- end
143
-
144
- it 'is not valid' do
145
- expect(described_class.new(vat_number: 'DE123')).not_to be_valid
146
- end
147
- end
148
-
149
- context 'with valid and existing VAT number' do
150
- before do
151
- allow(Valvat::Syntax).to receive_messages(validate: true)
152
- allow(Valvat::Lookup).to receive_messages(validate: true)
153
- end
154
-
155
- it 'is valid' do
156
- expect(described_class.new(vat_number: 'DE123')).to be_valid
157
- end
158
- end
159
-
160
- context 'with valid VAT number and VIES country service down' do
161
- before do
162
- allow(Valvat::Syntax).to receive_messages(validate: true)
163
- allow(Valvat::Lookup).to receive_messages(validate: nil)
164
- end
165
-
166
- it 'is valid' do
167
- expect(described_class.new(vat_number: 'DE123')).to be_valid
168
- end
169
- end
170
- end
171
-
172
- describe InvoiceWithLookupAndFailIfDown do
173
- let(:record) { described_class.new }
174
-
175
- context 'with valid VAT number and VIES country service down' do
176
- before do
177
- allow(Valvat::Syntax).to receive_messages(validate: true)
178
- allow(Valvat::Lookup).to receive_messages(validate: nil)
179
- end
180
-
181
- it 'is not valid' do
182
- expect(record).not_to be_valid
183
- msg = 'Unable to validate your VAT number: the VIES service is down. Please try again later.'
184
- expect(record.errors[:vat_number]).to eql([msg])
185
- end
186
- end
187
- end
188
-
189
- describe InvoiceAllowBlank do
190
- context 'with blank VAT number' do
191
- it 'is valid' do
192
- expect(described_class.new(vat_number: '')).to be_valid
193
- expect(described_class.new(vat_number: nil)).to be_valid
194
- end
195
- end
196
- end
197
-
198
- describe InvoiceAllowBlankOnAll do
199
- context 'with blank VAT number' do
200
- it 'is valid' do
201
- expect(described_class.new(vat_number: '')).to be_valid
202
- expect(described_class.new(vat_number: nil)).to be_valid
203
- end
204
- end
205
- end
206
-
207
- describe InvoiceCheckCountry do
208
- it 'is not valid on blank country' do
209
- expect(described_class.new(country: nil, vat_number: 'DE259597697')).not_to be_valid
210
- expect(described_class.new(country: '', vat_number: 'DE259597697')).not_to be_valid
211
- end
212
-
213
- it 'is not valid on wired country' do
214
- expect(described_class.new(country: 'XAXXX', vat_number: 'DE259597697')).not_to be_valid
215
- expect(described_class.new(country: 'ZO', vat_number: 'DE259597697')).not_to be_valid
216
- end
217
-
218
- it 'is not valid on mismatching (eu) country' do
219
- expect(described_class.new(country: 'FR', vat_number: 'DE259597697')).not_to be_valid
220
- expect(described_class.new(country: 'AT', vat_number: 'DE259597697')).not_to be_valid
221
- expect(described_class.new(country: 'DE', vat_number: 'ATU65931334')).not_to be_valid
222
- end
223
-
224
- it 'is valid on matching country' do
225
- expect(described_class.new(country: 'DE', vat_number: 'DE259597697')).to be_valid
226
- expect(described_class.new(country: 'AT', vat_number: 'ATU65931334')).to be_valid
227
- end
228
-
229
- it 'gives back error message with country from :country_match' do
230
- invoice = described_class.new(country: 'FR', vat_number: 'DE259597697')
231
- invoice.valid?
232
- expect(invoice.errors[:vat_number]).to eql(['is not a valid French VAT number'])
233
- end
234
-
235
- it 'gives back error message with country from :country_match even on invalid VAT number' do
236
- invoice = described_class.new(country: 'FR', vat_number: 'DE259597697123')
237
- invoice.valid?
238
- expect(invoice.errors[:vat_number]).to eql(['is not a valid French VAT number'])
239
- end
240
- end
241
-
242
- describe InvoiceCheckCountryWithLookup do
243
- before do
244
- allow(Valvat::Syntax).to receive_messages(validate: true)
245
- allow(Valvat::Lookup).to receive_messages(validate: true)
246
- end
247
-
248
- it 'avoids lookup or syntax check on failed because of mismatching country' do
249
- described_class.new(country: 'FR', vat_number: 'DE259597697').valid?
250
- expect(Valvat::Syntax).not_to have_received(:validate)
251
- expect(Valvat::Lookup).not_to have_received(:validate)
252
- end
253
-
254
- it 'check syntax and looup on matching country' do
255
- described_class.new(country: 'DE', vat_number: 'DE259597697').valid?
256
- expect(Valvat::Syntax).to have_received(:validate)
257
- expect(Valvat::Lookup).to have_received(:validate)
258
- end
259
- end
260
-
261
- describe InvoiceWithChecksum do
262
- context 'with valid VAT number' do
263
- it 'is valid' do
264
- expect(described_class.new(vat_number: 'DE259597697')).to be_valid
265
- end
266
- end
267
-
268
- context 'with invalid VAT number' do
269
- it 'is not valid' do
270
- expect(described_class.new(vat_number: 'DE259597687')).not_to be_valid
271
- end
272
- end
273
- end
274
- end