Module: Europe::Vat

Defined in:
lib/europe/vat/vat.rb,
lib/europe/vat/rates.rb,
lib/europe/vat/format.rb

Overview

VAT

Defined Under Namespace

Modules: Format, Rates

Constant Summary collapse

API_URL =
'https://ec.europa.eu/taxation_customs/vies/rest-api/check-vat-number'
HEADERS =
{
  'Content-Type' => 'application/json',
  'Accept' => 'application/json'
}.freeze
VIES_ERRORS =
{
  'INVALID_INPUT' => :invalid_input,
  'GLOBAL_MAX_CONCURRENT_REQ' => :rate_limited,
  'MS_MAX_CONCURRENT_REQ' => :rate_limited,
  'SERVICE_UNAVAILABLE' => :service_unavailable,
  'MS_UNAVAILABLE' => :ms_unavailable,
  'TIMEOUT' => :timeout
}.freeze

Class Method Summary collapse

Class Method Details

.charge_vat?(origin_country, number) ⇒ Boolean

Returns:

  • (Boolean)


68
69
70
71
72
73
# File 'lib/europe/vat/vat.rb', line 68

def self.charge_vat?(origin_country, number)
  return false if number.nil? || number.empty?

  Europe::Vat::Fromat::VAT_REGEX.key?(origin_country.to_sym) ||
    Europe::Vat::Fromat::VAT_REGEX.key?(number[0..1].to_sym)
end

.convert_date(date) ⇒ Object



62
63
64
65
66
# File 'lib/europe/vat/vat.rb', line 62

def self.convert_date(date)
  return unless date

  Date.parse(date)
end

.handle_error_response(response) ⇒ Object



42
43
44
45
46
47
48
# File 'lib/europe/vat/vat.rb', line 42

def self.handle_error_response(response)
  body = JSON.parse(response.body)
  error_code = body.dig('errorWrappers', 0, 'error')
  VIES_ERRORS[error_code] || :service_error
rescue JSON::ParserError
  :service_error
end

.send_request(country_code, number) ⇒ Object



75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/europe/vat/vat.rb', line 75

def self.send_request(country_code, number)
  uri = URI.parse(API_URL)

  Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
    request = Net::HTTP::Post.new(uri.request_uri, HEADERS)
    request.body = JSON.generate(
      countryCode: country_code,
      vatNumber: number
    )
    http.request(request)
  end
end

.setup_response(response) ⇒ Object



50
51
52
53
54
55
56
57
58
59
60
# File 'lib/europe/vat/vat.rb', line 50

def self.setup_response(response)
  body = JSON.parse(response.body)
  {
    valid: body['valid'] == true,
    country_code: body['countryCode'],
    vat_number: body['vatNumber'],
    request_date: convert_date(body['requestDate']),
    name: body['name'],
    address: body['address']
  }
end

.validate(number) ⇒ Object



29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/europe/vat/vat.rb', line 29

def self.validate(number)
  return :invalid_input if number.size < 4

  response = send_request(number[0..1], number[2..-1])
  return handle_error_response(response) unless response.is_a?(Net::HTTPSuccess)

  setup_response(response)
rescue Net::OpenTimeout, Net::ReadTimeout
  :timeout
rescue Errno::ECONNREFUSED, Errno::ECONNRESET, Errno::ETIMEDOUT, SocketError, OpenSSL::SSL::SSLError
  :service_unavailable
end