valvat 1.3.0 → 1.4.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: f03e6103f577ebcec25d3cbd5c4e2e13c914945c13a1767912f9f49380c9a6ae
4
- data.tar.gz: db8423cf0d17a8c3a7a840d7d22ff887b6296442da31fc11931aa24aafd6c630
3
+ metadata.gz: 15db8a8eed2ca747b9a57a31d9b86b3cf15de8805c60e4c9088f6d4307c61f3e
4
+ data.tar.gz: 7e39c7bce5487ca35f919c92bce4b424feacdded7a2ae917d272836bb2a224f7
5
5
  SHA512:
6
- metadata.gz: c9c92f073fc78fae74582d093bdf76f2747dab68aa44eb7f1106bb82bdc8f63b47a5236e8e1d766bc49a3e68b74f3723c45be6ff9e91f96548cfc526cad33ef1
7
- data.tar.gz: 3127010ce2d38d7a75ebcb0688850414d8149cb9db5fe8f6f575c2d1bf0ff2bae0b68a39878df8f851654b5d6cea766b2d63c91639aca5d7696776ed01ed3042
6
+ metadata.gz: 0f4f6c82582854e8bed285713f0e98322d4caaddc9ad544f75116a22c5522e8ef224fdf126e704396a5c2651819cc5c155536a6d736923e80966c9b9a4a72810
7
+ data.tar.gz: 6d2f3e585eb86086600e6976df74cf1fe46a145aedaa25fe3eb8fad3eb8bd5eba7db3c24d2b43efead054bec086188512767816cfe52d4fe1eb0280a5f870e23
checksums.yaml.gz.sig CHANGED
Binary file
@@ -0,0 +1,17 @@
1
+ name: RuboCop
2
+
3
+ on: [push, pull_request]
4
+
5
+ jobs:
6
+ build:
7
+ runs-on: ubuntu-latest
8
+
9
+ steps:
10
+ - uses: actions/checkout@v3
11
+ - name: Set up Ruby 2.7
12
+ uses: ruby/setup-ruby@v1
13
+ with:
14
+ ruby-version: 2.7
15
+ bundler-cache: true
16
+ - name: Run RuboCop
17
+ run: bundle exec rubocop --parallel
@@ -34,7 +34,7 @@ jobs:
34
34
  gemfile: 'activemodel-5'
35
35
 
36
36
  steps:
37
- - uses: actions/checkout@v2
37
+ - uses: actions/checkout@v3
38
38
  - name: Set up Ruby
39
39
  uses: ruby/setup-ruby@v1
40
40
  with:
data/.rubocop.yml CHANGED
@@ -1,7 +1,7 @@
1
1
  require: rubocop-rspec
2
2
  AllCops:
3
3
  NewCops: enable
4
- TargetRubyVersion: 2.5
4
+ TargetRubyVersion: 2.6
5
5
 
6
6
  Metrics/BlockLength:
7
7
  Exclude:
data/CHANGES.md CHANGED
@@ -1,7 +1,15 @@
1
1
 
2
2
  ### dev
3
3
 
4
- [full changelog](http://github.com/yolk/valvat/compare/v1.3.0...master)
4
+ [full changelog](http://github.com/yolk/valvat/compare/v1.4.0...master)
5
+
6
+ ### 1.4.0 / 2023-07-20
7
+
8
+ [full changelog](http://github.com/yolk/valvat/compare/v1.3.0...v1.4.0)
9
+
10
+ * Valvat.configure: Allow global configuration
11
+ * Update the Cyprus syntax regular expression by [Orien Madgwick](https://github.com/orien))
12
+ * Valvat::Checksum::ES: Fixed issue with VAT ids starting with '*00' #124 / #115 (by [Thomas Scalise](https://github.com/KirtashW17))
5
13
 
6
14
  ### 1.3.0 / 2023-04-19
7
15
 
data/Gemfile CHANGED
@@ -5,4 +5,10 @@ source 'https://rubygems.org'
5
5
  # Specify your gem's dependencies in valvat.gemspec
6
6
  gemspec
7
7
 
8
+ gem 'activemodel', '>= 5.0'
8
9
  gem 'guard-rspec', '~>4.0'
10
+ gem 'rake'
11
+ gem 'rspec', '~> 3.0'
12
+ gem 'rubocop', '~> 1.50'
13
+ gem 'rubocop-rspec', '~> 2.19'
14
+ gem 'webmock', '~> 3.0'
data/MIT-LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2011-2022 mite GmbH
1
+ Copyright (c) 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
@@ -183,6 +183,20 @@ Valvat::Checksum.validate("DE345789003")
183
183
  # => true or false
184
184
  ```
185
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
+
186
200
  ## Usage with ActiveModel / Rails
187
201
 
188
202
  ### Loading
@@ -329,8 +343,8 @@ https://github.com/yolk/valvat/graphs/contributors
329
343
 
330
344
  ## BlaBla
331
345
 
332
- Copyright (c) 2011-2022 mite GmbH
346
+ Copyright (c) 2011-2023 mite GmbH
333
347
 
334
348
  Beyond that, the implementation is licensed under the MIT License.
335
349
 
336
- Code was originally extracted from our time tracking webapp [mite](https://mite.yo.lk/en/).
350
+ Code was originally extracted from our time tracking webapp [mite](https://mite.de/en/).
@@ -1,5 +1,8 @@
1
- source "https://rubygems.org"
1
+ source 'https://rubygems.org'
2
2
 
3
- gem "activemodel", "~> 5.0"
3
+ gem 'activemodel', '~> 5.0'
4
+ gem 'rake'
5
+ gem 'rspec', '~> 3.0'
6
+ gem 'webmock', '~> 3.0'
4
7
 
5
- gemspec path: "../"
8
+ gemspec path: '../'
@@ -1,5 +1,8 @@
1
- source "https://rubygems.org"
1
+ source 'https://rubygems.org'
2
2
 
3
- gem "activemodel", "~> 6.0"
3
+ gem 'activemodel', '~> 6.0'
4
+ gem 'rake'
5
+ gem 'rspec', '~> 3.0'
6
+ gem 'webmock', '~> 3.0'
4
7
 
5
- gemspec path: "../"
8
+ gemspec path: '../'
@@ -1,5 +1,8 @@
1
- source "https://rubygems.org"
1
+ source 'https://rubygems.org'
2
2
 
3
- gem "activemodel", "~> 7.0"
3
+ gem 'activemodel', '~> 7.0'
4
+ gem 'rake'
5
+ gem 'rspec', '~> 3.0'
6
+ gem 'webmock', '~> 3.0'
4
7
 
5
- gemspec path: "../"
8
+ gemspec path: '../'
data/gemfiles/standalone CHANGED
@@ -1,3 +1,7 @@
1
- source "https://rubygems.org"
1
+ source 'https://rubygems.org'
2
2
 
3
- gemspec path: "../"
3
+ gem 'rake'
4
+ gem 'rspec', '~> 3.0'
5
+ gem 'webmock', '~> 3.0'
6
+
7
+ gemspec path: '../'
@@ -9,7 +9,7 @@ class Valvat
9
9
  end
10
10
 
11
11
  def str_wo_country
12
- super[1..-1]
12
+ super[1..]
13
13
  end
14
14
  end
15
15
  end
@@ -23,9 +23,9 @@ class Valvat
23
23
  !(
24
24
  # [KLM]: CD first two numerical digits must be between 01 and 56 (both inclusive)
25
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)
26
+ (vat.to_s_wo_country[1..2].to_i > 56 || vat.to_s_wo_country[1..2].to_i < 1)) ||
27
+ # Exceptions: X0000000T, 00000001R, 00000000T & 99999999R are invalid.
28
+ %w[X0000000T 00000001R 00000000T 99999999R].include?(vat.to_s_wo_country)
29
29
  )
30
30
  end
31
31
 
@@ -55,7 +55,7 @@ class Valvat
55
55
 
56
56
  def str_wo_country
57
57
  str = super
58
- str[0] =~ /\d/ ? str : str[1..-1]
58
+ str[0] =~ /\d/ ? str : str[1..]
59
59
  end
60
60
 
61
61
  def person?
@@ -5,26 +5,33 @@ class Valvat
5
5
  class FR < Base
6
6
  # the valid characters for the first two digits (O and I are missing)
7
7
  ALPHABET = '0123456789ABCDEFGHJKLMNPQRSTUVWXYZ'
8
+ NUMERIC = /^\d+$/.freeze
8
9
 
9
10
  def validate
10
- return super if str_wo_country[0..1] =~ /^\d+$/
11
+ return super if str_wo_country[0..1] =~ NUMERIC
11
12
 
12
- numeric_start = str_wo_country[0] =~ /\d/
13
+ check = alt_check_digit
13
14
 
14
- check = (ALPHABET.index(str_wo_country[0]) * (numeric_start ? 24 : 34)) +
15
- ALPHABET.index(str_wo_country[1]) - (numeric_start ? 10 : 100)
16
-
17
- (str_wo_country[2..-1].to_i + 1 + (check / 11)) % 11 == check % 11
15
+ (str_wo_country[2..].to_i + 1 + (check / 11)) % 11 == check % 11
18
16
  end
19
17
 
18
+ private
19
+
20
20
  def check_digit
21
- siren = str_wo_country[2..-1].to_i
21
+ siren = str_wo_country[2..].to_i
22
22
  (12 + ((3 * siren) % 97)) % 97
23
23
  end
24
24
 
25
25
  def given_check_digit
26
26
  str_wo_country[0..1].to_i
27
27
  end
28
+
29
+ def alt_check_digit
30
+ first_is_numeric = str_wo_country[0] =~ NUMERIC
31
+
32
+ (ALPHABET.index(str_wo_country[0]) * (first_is_numeric ? 24 : 34)) +
33
+ ALPHABET.index(str_wo_country[1]) - (first_is_numeric ? 10 : 100)
34
+ end
28
35
  end
29
36
  end
30
37
  end
@@ -6,7 +6,7 @@ class Valvat
6
6
  check_digit_length 0
7
7
 
8
8
  def validate
9
- vat.to_s_wo_country[-2..-1].to_i.positive? &&
9
+ vat.to_s_wo_country[-2..].to_i.positive? &&
10
10
  super
11
11
  end
12
12
 
@@ -21,7 +21,7 @@ class Valvat
21
21
  private
22
22
 
23
23
  def given_check_digit_str
24
- str_wo_country[-self.class.check_digit_length..-1]
24
+ str_wo_country[-self.class.check_digit_length..]
25
25
  end
26
26
 
27
27
  def given_check_digit
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'singleton'
4
+
5
+ class Valvat
6
+ ##
7
+ # Configuration options should be set by passing a hash:
8
+ #
9
+ # Valvat.configure(
10
+ # uk: true
11
+ # )
12
+ #
13
+ def self.configure(options)
14
+ Configuration.instance.configure(options) unless options.nil?
15
+ end
16
+
17
+ # Read-only access to config
18
+ def self.config
19
+ Configuration.instance
20
+ end
21
+
22
+ class Configuration
23
+ include Singleton
24
+
25
+ DEFAULTS = {
26
+ # Set to true to always raise error, even on temporary maintenance downtime errors,
27
+ # set to false to suppress all errors and return nil instead
28
+ raise_error: nil,
29
+
30
+ # Set options for the http client.
31
+ # These options are directly passed to `Net::HTTP.start`
32
+ http: {}.freeze,
33
+
34
+ # Return details hash on lookup instead of boolean
35
+ detail: false,
36
+
37
+ # Your own VAT number used on lookup
38
+ requester: nil,
39
+
40
+ # Skip local validation on lookup
41
+ skip_local_validation: false,
42
+
43
+ # Use lookup via HMRC for VAT numbers from the UK
44
+ # if set to false lookup will always return false for UK VAT numbers
45
+ uk: false
46
+ }.freeze
47
+
48
+ def self.initialize
49
+ instance.send(:initialize)
50
+ end
51
+
52
+ def [](key)
53
+ @data[key]
54
+ end
55
+
56
+ def configure(options)
57
+ @data = @data.merge(Utils.deep_symbolize_keys(options))
58
+ end
59
+
60
+ def initialize
61
+ @data = DEFAULTS.clone
62
+ end
63
+ end
64
+ end
@@ -1,13 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'net/http'
4
+ require_relative '../options'
4
5
 
5
6
  class Valvat
6
7
  class Lookup
7
8
  class Base
8
9
  def initialize(vat, options = {})
9
10
  @vat = Valvat(vat)
10
- @options = options
11
+ @options = Valvat::Options(options)
11
12
  @requester = @options[:requester] && Valvat(@options[:requester])
12
13
  end
13
14
 
@@ -59,14 +60,7 @@ class Valvat
59
60
  end
60
61
 
61
62
  def options_for(uri)
62
- options = if @options.key?(:savon)
63
- puts 'DEPRECATED: The option :savon is deprecated. Use :http instead.'
64
- @options[:savon]
65
- else
66
- @options[:http]
67
- end || {}
68
-
69
- options.merge({ use_ssl: URI::HTTPS === uri })
63
+ @options[:http].merge({ use_ssl: URI::HTTPS === uri })
70
64
  end
71
65
  end
72
66
  end
@@ -15,7 +15,7 @@ class Valvat
15
15
  }.freeze
16
16
 
17
17
  def perform
18
- return { valid: false } unless @options[:uk] == true
18
+ return { valid: false } unless @options[:uk]
19
19
 
20
20
  parse(fetch(endpoint_uri).body)
21
21
  end
data/lib/valvat/lookup.rb CHANGED
@@ -2,13 +2,13 @@
2
2
 
3
3
  require_relative 'lookup/vies'
4
4
  require_relative 'lookup/hmrc'
5
+ require_relative 'options'
5
6
 
6
7
  class Valvat
7
8
  class Lookup
8
9
  def initialize(vat, options = {})
9
10
  @vat = Valvat(vat)
10
- @options = options || {}
11
- @options[:requester] ||= @options[:requester_vat]
11
+ @options = Valvat::Options(options)
12
12
  end
13
13
 
14
14
  def validate
@@ -26,20 +26,14 @@ class Valvat
26
26
 
27
27
  private
28
28
 
29
- def valid?
30
- response[:valid]
31
- end
32
-
33
29
  def response
34
30
  @response ||= webservice.new(@vat, @options).perform
35
31
  end
36
32
 
37
33
  def webservice
38
- case @vat.vat_country_code
39
- when 'GB' then HMRC
40
- else
41
- VIES
42
- end
34
+ return HMRC if @vat.vat_country_code == 'GB'
35
+
36
+ VIES
43
37
  end
44
38
 
45
39
  def show_details?
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'configuration'
4
+
5
+ class Valvat
6
+ class Options
7
+ DEPRECATED_KEYS = {
8
+ requester_vat: :requester,
9
+ savon: :http
10
+ }.freeze
11
+
12
+ def initialize(options, silence: false)
13
+ @options = options || {}
14
+
15
+ DEPRECATED_KEYS.each do |deprecated, key|
16
+ if @options.key?(deprecated)
17
+ puts "DEPRECATED: The option :#{deprecated} is deprecated. Use :#{key} instead." unless silence
18
+ @options[key] ||= @options[deprecated]
19
+ end
20
+ end
21
+ end
22
+
23
+ def [](key)
24
+ @options.key?(key) ? @options[key] : Valvat.config[key]
25
+ end
26
+ end
27
+
28
+ def self.Options(options)
29
+ options.is_a?(Valvat::Options) ? options : Valvat::Options.new(options)
30
+ end
31
+ end
data/lib/valvat/syntax.rb CHANGED
@@ -6,7 +6,7 @@ class Valvat
6
6
  'AT' => /\AATU[0-9]{8}\Z/, # Austria
7
7
  'BE' => /\ABE[0-1][0-9]{9}\Z/, # Belgium
8
8
  'BG' => /\ABG[0-9]{9,10}\Z/, # Bulgaria
9
- 'CY' => /\ACY(?!12)[0-59][0-9]{7}[A-Z]\Z/, # Cyprus
9
+ 'CY' => /\ACY(?!12)[0-69][0-9]{7}[A-Z]\Z/, # Cyprus
10
10
  'CZ' => /\ACZ[0-9]{8,10}\Z/, # Czech Republic
11
11
  'DE' => /\ADE[0-9]{9}\Z/, # Germany
12
12
  'DK' => /\ADK[0-9]{8}\Z/, # Denmark
data/lib/valvat/utils.rb CHANGED
@@ -33,5 +33,17 @@ class Valvat
33
33
  def self.country_is_supported?(iso_country)
34
34
  SUPPORTED_STATES.include?(iso_country)
35
35
  end
36
+
37
+ def self.deep_symbolize_keys(value)
38
+ value = value.transform_keys do |key|
39
+ key.to_sym
40
+ rescue StandardError
41
+ key
42
+ end
43
+
44
+ value.transform_values! do |val|
45
+ val.is_a?(Hash) ? deep_symbolize_keys(val) : val
46
+ end
47
+ end
36
48
  end
37
49
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Valvat
4
- VERSION = '1.3.0'
4
+ VERSION = '1.4.0'
5
5
  end
data/lib/valvat.rb CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  require 'valvat/error'
4
4
  require 'valvat/utils'
5
+ require 'valvat/options'
6
+ require 'valvat/configuration'
5
7
  require 'valvat/syntax'
6
8
  require 'valvat/checksum'
7
9
  require 'valvat/version'
@@ -55,7 +57,7 @@ class Valvat
55
57
  def ==(other)
56
58
  raw == other.raw
57
59
  end
58
- alias_method :eql?, :==
60
+ alias eql? ==
59
61
 
60
62
  def inspect
61
63
  "#<Valvat #{[raw, iso_country_code].compact.join(' ')}>"
@@ -4,7 +4,7 @@ require 'spec_helper'
4
4
 
5
5
  describe Valvat::Checksum::ES do
6
6
  %w[ESA13585625 ESB83871236 ESE54507058 ES25139013J ESQ1518001A ESQ5018001G ESX4942978W ESX7676464F ESB10317980
7
- ESY3860557K ESY2207765D ES28350472M ES41961720Z ESM1171170X ESK0928769Y].each do |valid_vat|
7
+ ESY3860557K ESY2207765D ES28350472M ES41961720Z ESM1171170X ESK0928769Y ES50095545G].each do |valid_vat|
8
8
  it "returns true on valid VAT #{valid_vat}" do
9
9
  expect(Valvat::Checksum.validate(valid_vat)).to be(true)
10
10
  end
@@ -7,6 +7,10 @@ describe Valvat::Lookup::HMRC do
7
7
  stub_const('Valvat::Lookup::HMRC::ENDPOINT_URL', 'https://test-api.service.hmrc.gov.uk/organisations/vat/check-vat-number/lookup')
8
8
  end
9
9
 
10
+ after do
11
+ Valvat.configure(uk: false)
12
+ end
13
+
10
14
  it 'returns hash with valid: true on success' do
11
15
  response = described_class.new('GB553557881', { uk: true }).perform
12
16
 
@@ -29,4 +33,26 @@ describe Valvat::Lookup::HMRC do
29
33
  response = described_class.new('GB553557881', {}).perform
30
34
  expect(response).to match({ valid: false })
31
35
  end
36
+
37
+ it 'returns valid: false when uk option is set to false' do
38
+ response = described_class.new('GB553557881', { uk: false }).perform
39
+ expect(response).to match({ valid: false })
40
+ end
41
+
42
+ it 'returns valid: false when uk option is not set' do
43
+ response = described_class.new('GB553557881').perform
44
+ expect(response).to match({ valid: false })
45
+ end
46
+
47
+ it 'respects global :uk setting' do
48
+ Valvat.configure(uk: true)
49
+ response = described_class.new('GB553557881').perform
50
+ expect(response).to include({ valid: true })
51
+ end
52
+
53
+ it 'overwrite global :uk setting' do
54
+ Valvat.configure(uk: true)
55
+ response = described_class.new('GB553557881', uk: false).perform
56
+ expect(response).to include({ valid: false })
57
+ end
32
58
  end
@@ -6,6 +6,8 @@ describe Valvat::Lookup::VIES do
6
6
  it 'returns hash with valid: true on success' do
7
7
  response = described_class.new('IE6388047V', {}).perform
8
8
 
9
+ skip 'VIES is down' if response[:error].is_a?(Valvat::MemberStateUnavailable)
10
+
9
11
  expect(response).to match({
10
12
  valid: true,
11
13
  address: '3RD FLOOR, GORDON HOUSE, BARROW STREET, DUBLIN 4',
@@ -107,6 +107,8 @@ describe Valvat::Lookup do
107
107
  it 'supports old :requester_vat option for backwards compatibility' do
108
108
  result = described_class.validate('IE6388047V', requester_vat: 'LU21416127')
109
109
 
110
+ skip 'VIES is down' if result.nil?
111
+
110
112
  expect(result).to match({
111
113
  request_date: kind_of(Date),
112
114
  request_identifier: /\A[\w\W]{16}\Z/,
@@ -150,6 +152,28 @@ describe Valvat::Lookup do
150
152
  'INVALID_REQUEST (Invalid requesterVrn - Vrn parameters should be 9 or 12 digits)')
151
153
  end
152
154
  end
155
+
156
+ context 'when set in global config' do
157
+ before { Valvat.configure(requester: 'IE6388047V') }
158
+ after { Valvat.configure(requester: nil) }
159
+
160
+ it 'returns hash of details instead of true' do
161
+ result = described_class.validate('IE6388047V')
162
+
163
+ skip 'VIES is down' if result.nil?
164
+
165
+ expect(result).to match({
166
+ request_date: kind_of(Date),
167
+ request_identifier: /\A[\w\W]{16}\Z/,
168
+ country_code: 'IE',
169
+ vat_number: '6388047V',
170
+ name: 'GOOGLE IRELAND LIMITED',
171
+ company_type: nil,
172
+ address: '3RD FLOOR, GORDON HOUSE, BARROW STREET, DUBLIN 4',
173
+ valid: true
174
+ })
175
+ end
176
+ end
153
177
  end
154
178
  end
155
179
 
@@ -363,7 +387,7 @@ describe Valvat::Lookup do
363
387
 
364
388
  describe 'Error : MESSAGE_THROTTLED_OUT' do
365
389
  before do
366
- stub_request(:get, /test-api.service.hmrc.gov.uk/).to_return(
390
+ stub_request(:get, /test-api\.service\.hmrc\.gov\.uk/).to_return(
367
391
  status: 429,
368
392
  body: '{"code":"MESSAGE_THROTTLED_OUT"}'
369
393
  )
@@ -380,7 +404,7 @@ describe Valvat::Lookup do
380
404
 
381
405
  describe 'Error : SCHEDULED_MAINTENANCE' do
382
406
  before do
383
- stub_request(:get, /test-api.service.hmrc.gov.uk/).to_return(
407
+ stub_request(:get, /test-api\.service\.hmrc\.gov\.uk/).to_return(
384
408
  status: 503,
385
409
  body: '{"code":"SCHEDULED_MAINTENANCE"}'
386
410
  )
@@ -399,7 +423,7 @@ describe Valvat::Lookup do
399
423
 
400
424
  describe 'Error : SERVER_ERROR' do
401
425
  before do
402
- stub_request(:get, /test-api.service.hmrc.gov.uk/).to_return(
426
+ stub_request(:get, /test-api\.service\.hmrc\.gov\.uk/).to_return(
403
427
  status: 503,
404
428
  body: '{"code":"SERVER_ERROR"}'
405
429
  )
@@ -418,7 +442,7 @@ describe Valvat::Lookup do
418
442
 
419
443
  describe 'Error : GATEWAY_TIMEOUT' do
420
444
  before do
421
- stub_request(:get, /test-api.service.hmrc.gov.uk/).to_return(
445
+ stub_request(:get, /test-api\.service\.hmrc\.gov\.uk/).to_return(
422
446
  status: 504,
423
447
  body: '{"code":"GATEWAY_TIMEOUT"}'
424
448
  )
@@ -435,7 +459,7 @@ describe Valvat::Lookup do
435
459
 
436
460
  describe 'Network timeout' do
437
461
  before do
438
- stub_request(:get, /test-api.service.hmrc.gov.uk/).to_timeout
462
+ stub_request(:get, /test-api\.service\.hmrc\.gov\.uk/).to_timeout
439
463
  end
440
464
 
441
465
  it 'raises error' do
@@ -451,7 +475,7 @@ describe Valvat::Lookup do
451
475
 
452
476
  describe 'Error : INTERNAL_SERVER_ERROR' do
453
477
  before do
454
- stub_request(:get, /test-api.service.hmrc.gov.uk/).to_return(
478
+ stub_request(:get, /test-api\.service\.hmrc\.gov\.uk/).to_return(
455
479
  status: 500,
456
480
  body: '{"code":"INTERNAL_SERVER_ERROR"}'
457
481
  )
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Valvat::Options do
6
+ describe '#[]' do
7
+ it 'returns global config by default' do
8
+ expect(described_class.new({})[:uk]).to be(false)
9
+ end
10
+
11
+ it 'returns option if set' do
12
+ expect(described_class.new({ uk: true })[:uk]).to be(true)
13
+ end
14
+
15
+ context 'when options contains deprecated key' do
16
+ let(:options) { described_class.new({ requester_vat: 'DE123' }, silence: true) }
17
+
18
+ it 'returns it on new key' do
19
+ expect(options[:requester]).to be('DE123')
20
+ end
21
+ end
22
+ end
23
+ end
@@ -21,7 +21,7 @@ describe Valvat::Syntax do
21
21
  it_validates(%w[ATU03458890], %w[ATU034588908 ATU0345908 ATU0345889Y])
22
22
  it_validates(%w[BE0817331995 BE1817331999], %w[BE081733199 BE08173319944 BE081733199H BE2817331999])
23
23
  it_validates(%w[BG468134789 BG4681347897], %w[BG46813478979 BG4681347897C BG46813478G BG46813478])
24
- it_validates(%w[CY36579347A CY36579347C], %w[CY36579347 CY365793478 CY365793478A CY365793G])
24
+ it_validates(%w[CY36579347A CY36579347C CY60000347C], %w[CY36579347 CY365793478 CY365793478A CY365793G])
25
25
  it_validates(%w[CZ56389267 CZ563892670 CZ5638926790], %w[CZ5638926 CZ56389268901])
26
26
  it_validates(%w[DE345889003], %w[DE34588900 DE3458890090 DE34588900C])
27
27
  it_validates(%w[DK67893463], %w[DK678934637 DK6789346 DK6789346H])
@@ -112,4 +112,14 @@ describe Valvat::Utils do
112
112
  end
113
113
  end
114
114
  end
115
+
116
+ describe '#deep_symbolize_keys' do
117
+ it 'symbolizes keys of flat hash' do
118
+ expect(described_class.deep_symbolize_keys({ 'a' => 1, :b => 2 })).to eql({ a: 1, b: 2 })
119
+ end
120
+
121
+ it 'symbolizes all hashes' do
122
+ expect(described_class.deep_symbolize_keys({ 'a' => 1, :b => { 'c' => 3 } })).to eql({ a: 1, b: { c: 3 } })
123
+ end
124
+ end
115
125
  end
data/spec/valvat_spec.rb CHANGED
@@ -44,22 +44,22 @@ describe Valvat do
44
44
 
45
45
  describe 'object equality' do
46
46
  it 'returns true when the underlying number are the same' do
47
- first = "DE259597697"
48
- second = "DE259597697"
47
+ first = 'DE259597697'
48
+ second = 'DE259597697'
49
49
 
50
50
  expect(described_class.new(first)).to eql(described_class.new(second))
51
51
  end
52
52
 
53
53
  it 'returns true when the underlying number are the same when normalized' do
54
- first = "DE259597697"
55
- second = "DE 2595 9 7697 "
54
+ first = 'DE259597697'
55
+ second = 'DE 2595 9 7697 '
56
56
 
57
57
  expect(described_class.new(first)).to eql(described_class.new(second))
58
58
  end
59
59
 
60
60
  it 'returns false when the underlying number are different' do
61
- first = "DE259597697"
62
- second = "ATU458890031"
61
+ first = 'DE259597697'
62
+ second = 'ATU458890031'
63
63
 
64
64
  expect(described_class.new(first)).not_to eql(described_class.new(second))
65
65
  end
@@ -140,14 +140,6 @@ describe Valvat do
140
140
  end
141
141
  end
142
142
 
143
- describe '#european?' do
144
- it 'returns true' do
145
- expect(de_vat).to be_european
146
- expect(at_vat).to be_european
147
- expect(gr_vat).to be_european
148
- end
149
- end
150
-
151
143
  describe '#to_s' do
152
144
  it 'returns full VAT number' do
153
145
  expect(de_vat.to_s).to eql('DE259597697')
@@ -206,13 +198,6 @@ describe Valvat do
206
198
  end
207
199
  end
208
200
 
209
- describe '#european?' do
210
- it 'returns false' do
211
- expect(us_vat).not_to be_european
212
- expect(ch_vat).not_to be_european
213
- end
214
- end
215
-
216
201
  describe '#to_s' do
217
202
  it 'returns full given VAT number' do
218
203
  expect(us_vat.to_s).to eql('US345889003')
@@ -270,15 +255,6 @@ describe Valvat do
270
255
  end
271
256
  end
272
257
 
273
- describe '#european?' do
274
- it 'returns false' do
275
- expect(only_iso_vat).not_to be_european
276
- expect(num_vat).not_to be_european
277
- expect(empty_vat).not_to be_european
278
- expect(nil_vat).not_to be_european
279
- end
280
- end
281
-
282
258
  describe '#to_s' do
283
259
  it 'returns full given VAT number' do
284
260
  expect(only_iso_vat.to_s).to eql('DE')
data/valvat.gemspec CHANGED
@@ -4,27 +4,21 @@ $LOAD_PATH.push File.expand_path('lib', __dir__)
4
4
  require 'valvat/version'
5
5
 
6
6
  Gem::Specification.new do |s|
7
- s.name = 'valvat'
8
- s.version = Valvat::VERSION
9
- s.platform = Gem::Platform::RUBY
10
- s.license = 'MIT'
11
- s.authors = ['Sebastian Munz']
12
- s.email = ['sebastian@mite.de']
13
- s.homepage = 'https://github.com/yolk/valvat'
14
- s.summary = 'Validates european vat numbers. Standalone or as a ActiveModel validator.'
15
- s.description = 'Validates european vat numbers. Standalone or as a ActiveModel validator.'
16
- s.files = `git ls-files`.split("\n")
17
- s.require_paths = ['lib']
18
- s.cert_chain = ['certs/mite.pem']
19
- s.signing_key = File.expand_path('~/.ssh/gem-private_key.pem') if $PROGRAM_NAME =~ /gem\z/
20
- s.required_ruby_version = '>= 2.5.0'
7
+ s.name = 'valvat'
8
+ s.version = Valvat::VERSION
9
+ s.platform = Gem::Platform::RUBY
10
+ s.license = 'MIT'
11
+ s.authors = ['Sebastian Munz']
12
+ s.email = ['sebastian@mite.de']
13
+ s.homepage = 'https://github.com/yolk/valvat'
14
+ s.summary = 'Validates european vat numbers. Standalone or as a ActiveModel validator.'
15
+ s.description = 'Validates european vat numbers. Standalone or as a ActiveModel validator.'
16
+ s.files = `git ls-files`.split("\n")
17
+ s.require_paths = ['lib']
18
+ s.cert_chain = ['certs/mite.pem']
19
+ s.signing_key = File.expand_path('~/.ssh/gem-private_key.pem') if $PROGRAM_NAME =~ /gem\z/
20
+ s.metadata['rubygems_mfa_required'] = 'true'
21
+ s.required_ruby_version = '>= 2.6.0'
21
22
 
22
23
  s.add_runtime_dependency('rexml', '>= 3.2', '< 4.0')
23
-
24
- s.add_development_dependency 'activemodel', '>= 5.0'
25
- s.add_development_dependency 'rake'
26
- s.add_development_dependency 'rspec', '~> 3.0'
27
- s.add_development_dependency 'webmock', '~> 3.0'
28
-
29
- s.metadata['rubygems_mfa_required'] = 'true'
30
24
  end
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: valvat
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sebastian Munz
@@ -35,7 +35,7 @@ cert_chain:
35
35
  O1ARwPz8pN+xIvxo8ex8Hz1sazm/iFgVBwHgaI3O3ctK7vF4+fAu6dlLcbEpij9z
36
36
  4QlUng62OJRSBV/ejaTTItcAOXBeh028ZFWC0QQR4r0=
37
37
  -----END CERTIFICATE-----
38
- date: 2023-04-19 00:00:00.000000000 Z
38
+ date: 2023-07-20 00:00:00.000000000 Z
39
39
  dependencies:
40
40
  - !ruby/object:Gem::Dependency
41
41
  name: rexml
@@ -57,62 +57,6 @@ dependencies:
57
57
  - - "<"
58
58
  - !ruby/object:Gem::Version
59
59
  version: '4.0'
60
- - !ruby/object:Gem::Dependency
61
- name: activemodel
62
- requirement: !ruby/object:Gem::Requirement
63
- requirements:
64
- - - ">="
65
- - !ruby/object:Gem::Version
66
- version: '5.0'
67
- type: :development
68
- prerelease: false
69
- version_requirements: !ruby/object:Gem::Requirement
70
- requirements:
71
- - - ">="
72
- - !ruby/object:Gem::Version
73
- version: '5.0'
74
- - !ruby/object:Gem::Dependency
75
- name: rake
76
- requirement: !ruby/object:Gem::Requirement
77
- requirements:
78
- - - ">="
79
- - !ruby/object:Gem::Version
80
- version: '0'
81
- type: :development
82
- prerelease: false
83
- version_requirements: !ruby/object:Gem::Requirement
84
- requirements:
85
- - - ">="
86
- - !ruby/object:Gem::Version
87
- version: '0'
88
- - !ruby/object:Gem::Dependency
89
- name: rspec
90
- requirement: !ruby/object:Gem::Requirement
91
- requirements:
92
- - - "~>"
93
- - !ruby/object:Gem::Version
94
- version: '3.0'
95
- type: :development
96
- prerelease: false
97
- version_requirements: !ruby/object:Gem::Requirement
98
- requirements:
99
- - - "~>"
100
- - !ruby/object:Gem::Version
101
- version: '3.0'
102
- - !ruby/object:Gem::Dependency
103
- name: webmock
104
- requirement: !ruby/object:Gem::Requirement
105
- requirements:
106
- - - "~>"
107
- - !ruby/object:Gem::Version
108
- version: '3.0'
109
- type: :development
110
- prerelease: false
111
- version_requirements: !ruby/object:Gem::Requirement
112
- requirements:
113
- - - "~>"
114
- - !ruby/object:Gem::Version
115
- version: '3.0'
116
60
  description: Validates european vat numbers. Standalone or as a ActiveModel validator.
117
61
  email:
118
62
  - sebastian@mite.de
@@ -121,7 +65,8 @@ extensions: []
121
65
  extra_rdoc_files: []
122
66
  files:
123
67
  - ".editorconfig"
124
- - ".github/workflows/ruby.yml"
68
+ - ".github/workflows/rubocop.yml"
69
+ - ".github/workflows/specs.yml"
125
70
  - ".gitignore"
126
71
  - ".rubocop.yml"
127
72
  - CHANGES.md
@@ -131,7 +76,6 @@ files:
131
76
  - README.md
132
77
  - Rakefile
133
78
  - certs/mite.pem
134
- - certs/yolk.pem
135
79
  - gemfiles/activemodel-5
136
80
  - gemfiles/activemodel-6
137
81
  - gemfiles/activemodel-7
@@ -164,6 +108,7 @@ files:
164
108
  - lib/valvat/checksum/ro.rb
165
109
  - lib/valvat/checksum/se.rb
166
110
  - lib/valvat/checksum/si.rb
111
+ - lib/valvat/configuration.rb
167
112
  - lib/valvat/error.rb
168
113
  - lib/valvat/local.rb
169
114
  - lib/valvat/locales/bg.yml
@@ -190,6 +135,7 @@ files:
190
135
  - lib/valvat/lookup/base.rb
191
136
  - lib/valvat/lookup/hmrc.rb
192
137
  - lib/valvat/lookup/vies.rb
138
+ - lib/valvat/options.rb
193
139
  - lib/valvat/syntax.rb
194
140
  - lib/valvat/utils.rb
195
141
  - lib/valvat/version.rb
@@ -224,6 +170,7 @@ files:
224
170
  - spec/valvat/lookup/hmrc_spec.rb
225
171
  - spec/valvat/lookup/vies_spec.rb
226
172
  - spec/valvat/lookup_spec.rb
173
+ - spec/valvat/options_spec.rb
227
174
  - spec/valvat/syntax_spec.rb
228
175
  - spec/valvat/utils_spec.rb
229
176
  - spec/valvat_spec.rb
@@ -241,7 +188,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
241
188
  requirements:
242
189
  - - ">="
243
190
  - !ruby/object:Gem::Version
244
- version: 2.5.0
191
+ version: 2.6.0
245
192
  required_rubygems_version: !ruby/object:Gem::Requirement
246
193
  requirements:
247
194
  - - ">="
metadata.gz.sig CHANGED
Binary file
data/certs/yolk.pem DELETED
@@ -1,26 +0,0 @@
1
- -----BEGIN CERTIFICATE-----
2
- MIIEZDCCAsygAwIBAgIBATANBgkqhkiG9w0BAQsFADA8MRIwEAYDVQQDDAlzZWJh
3
- c3RpYW4xEjAQBgoJkiaJk/IsZAEZFgJ5bzESMBAGCgmSJomT8ixkARkWAmxrMB4X
4
- DTIyMDEyNjE4MjIxNFoXDTIzMDEyNjE4MjIxNFowPDESMBAGA1UEAwwJc2ViYXN0
5
- aWFuMRIwEAYKCZImiZPyLGQBGRYCeW8xEjAQBgoJkiaJk/IsZAEZFgJsazCCAaIw
6
- DQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBAM8Gdm81LvuqMyJr9sO+KtJz+PhM
7
- x75w6uc5q3J8sTHGhOtWJlXiBFf8gbBkxUsQwDMEEbJ+WV63oqq9InVBrMHg9FxH
8
- 415dC0UlCv5IjKij4N5OVRnUTZDoxXczVVscNFyQcRhJO1TqORw6uOF8gd/MVWl4
9
- 6gJapzkLBMTIaqRUVbX3hTJpiGc1RV2zJmLkkvBtJ+lzqza0bklXh52LLs2UpTc1
10
- e5ADVoq9K09G5QXES/GlFMYerQbtdXl0KpUQugXtRFAOoOrFKQFLETZSDq80lC7p
11
- +zN+wNOEAuHtJP7EZVk/gU8hEkSDMexW5NRndgeQb+N/JH8DIRBbhOytZbAo19Pq
12
- LEZBucHheI0xstLWuIP+ktwa/rIWv5v4gv3JZ/4H3q6tGPHigLKneRmaXo3e6jna
13
- RFDxQLXbJgI37qusk4Qyl/iBVSBZ+TABBvA/jPXnHdd29qkuMTXvWLIiBDM6H0+2
14
- SUabsieR1CqNZs/6YLO7nQHwFudHqzo8OB4+3QIDAQABo3EwbzAJBgNVHRMEAjAA
15
- MAsGA1UdDwQEAwIEsDAdBgNVHQ4EFgQUfC99QRDzqEe0tw1Da+XR9u4dmjEwGgYD
16
- VR0RBBMwEYEPc2ViYXN0aWFuQHlvLmxrMBoGA1UdEgQTMBGBD3NlYmFzdGlhbkB5
17
- by5sazANBgkqhkiG9w0BAQsFAAOCAYEAwYCyAFFXgYXWgaO8vQEZoQSjp5v6g1v/
18
- t9TcO8JmX6UqEgoRHsdxPEyCK9RroYIv7X5GDyJ12ZdiGpzCqJiBIC9Gz3cCWAbp
19
- LtnkhO8SQbz5B0NMOvo4o6XnbAr+rhVihuJmf0zXInnm1KZW/Yi+4JNAebPqwF1S
20
- VZ/2Dz2BtTuTFhqlHOGxV2NxcnZjFff9kfUOLwl/oNUKgBecsMP5aW74zSOmc2fO
21
- 3sykOkKf5mWSY/KSuaCmAP1Ou3UUXOQmxiPUW9SDAzhYGKS63yPMkzJAziDP9ewI
22
- zmOE2OJr0NuCmH9ykqlJZU4wnmloCnE1+8kHCl4+76cgBnN5gnYnzUb4RDM3J4EI
23
- Jdm7+JxQbgAP/HJ2C2ara+uwc9jwhw2s1b2+TPnVCZdh9uBttHWfk0wgDoeFwky1
24
- BUdT7mtr41GgvWnIjaGWAldSuabxx5H+PKS5FzjNDMHThRZWuvYp/nP2RXDh4gIa
25
- 7hV09P+XxvS96G+petG5KmC/lev8VqKu
26
- -----END CERTIFICATE-----