valvat 1.4.1 → 1.4.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/lib/valvat/version.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +34 -82
- metadata.gz.sig +0 -0
- data/.editorconfig +0 -15
- data/.github/workflows/rubocop.yml +0 -17
- data/.github/workflows/specs.yml +0 -47
- data/.gitignore +0 -9
- data/.rubocop.yml +0 -24
- data/CHANGES.md +0 -419
- data/Gemfile +0 -14
- data/Guardfile +0 -7
- data/MIT-LICENSE +0 -20
- data/README.md +0 -350
- data/Rakefile +0 -10
- data/certs/mite.pem +0 -26
- data/gemfiles/activemodel-5 +0 -8
- data/gemfiles/activemodel-6 +0 -8
- data/gemfiles/activemodel-7 +0 -8
- data/gemfiles/standalone +0 -7
- data/spec/active_model/validations/valvat_validator_spec.rb +0 -274
- data/spec/spec_helper.rb +0 -37
- data/spec/valvat/checksum/at_spec.rb +0 -17
- data/spec/valvat/checksum/be_spec.rb +0 -17
- data/spec/valvat/checksum/bg_spec.rb +0 -18
- data/spec/valvat/checksum/cy_spec.rb +0 -17
- data/spec/valvat/checksum/de_spec.rb +0 -17
- data/spec/valvat/checksum/dk_spec.rb +0 -17
- data/spec/valvat/checksum/ee_spec.rb +0 -17
- data/spec/valvat/checksum/es_spec.rb +0 -65
- data/spec/valvat/checksum/fi_spec.rb +0 -17
- data/spec/valvat/checksum/fr_spec.rb +0 -17
- data/spec/valvat/checksum/gb_spec.rb +0 -34
- data/spec/valvat/checksum/gr_spec.rb +0 -17
- data/spec/valvat/checksum/hr_spec.rb +0 -17
- data/spec/valvat/checksum/hu_spec.rb +0 -17
- data/spec/valvat/checksum/ie_spec.rb +0 -24
- data/spec/valvat/checksum/it_spec.rb +0 -25
- data/spec/valvat/checksum/lt_spec.rb +0 -17
- data/spec/valvat/checksum/lu_spec.rb +0 -17
- data/spec/valvat/checksum/mt_spec.rb +0 -17
- data/spec/valvat/checksum/nl_spec.rb +0 -17
- data/spec/valvat/checksum/pl_spec.rb +0 -21
- data/spec/valvat/checksum/pt_spec.rb +0 -30
- data/spec/valvat/checksum/ro_spec.rb +0 -17
- data/spec/valvat/checksum/se_spec.rb +0 -21
- data/spec/valvat/checksum/si_spec.rb +0 -25
- data/spec/valvat/checksum_spec.rb +0 -40
- data/spec/valvat/lookup/hmrc_spec.rb +0 -58
- data/spec/valvat/lookup/vies_spec.rb +0 -25
- data/spec/valvat/lookup_spec.rb +0 -493
- data/spec/valvat/options_spec.rb +0 -23
- data/spec/valvat/syntax_spec.rb +0 -68
- data/spec/valvat/utils_spec.rb +0 -125
- data/spec/valvat_spec.rb +0 -276
- 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
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-----
|
data/gemfiles/activemodel-5
DELETED
data/gemfiles/activemodel-6
DELETED
data/gemfiles/activemodel-7
DELETED
data/gemfiles/standalone
DELETED
@@ -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
|