Module: VatCalculator

Defined in:
lib/vat_calculator.rb,
lib/vat_calculator/railtie.rb

Defined Under Namespace

Classes: NoCountryException, NoRuleFoundException, Railtie

Constant Summary collapse

DEFAULT_BASE_COUNTRY =
'FR'
VAT_RATES =

EUROPEAN_COUNTRIES = %w(DE AT BE BG CY DK ES EE FI FR EL HU IE IT LV LT LU MT NL PL GB RO SK SI SE CZ) # @deprecated

{
  'FR'      => {
    :rate         => 19.6
    # FIXME (Did): no exceptions an accouting person told me (to be double checked)
    # :exceptions   => {
    #   'GF'  => 0.0,     # French Guyana
    #   'GP'  => 8.5,     # Guadeloupe
    #   'MQ'  => 8.5,     # Martinique
    #   'RE'  => 8.5      # RĂ©union
    # }
  },

  'GP'      => 8.5,
  'MQ'      => 8.5,
  'RE'      => 8.5,

  'BE'      => 21
}

Class Method Summary collapse

Class Method Details

.formalize_rate_rule(data) ⇒ Object



36
37
38
39
40
41
42
43
44
45
46
# File 'lib/vat_calculator.rb', line 36

def self.formalize_rate_rule(data)
  unless data.is_a?(Hash)
    data = { :rate => data.to_f }
  end

  OpenStruct.new({
    :exceptions         => {},
    :rate               => 0.0,
    :no_rate            => 0.0
  }.merge(data))
end

.get(country_code, options = {}) ⇒ Object

Possible options are:

:base_country_code    the country of the seller, if not given, then take the one by default [optional]
:vat_number           in case the buyer left his vat number. Validation should have been done before [optional]
:validation           :none, :simple (just check the format of the vat number), :full (format + existence of the vat number). By default, :none

Raises:



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/vat_calculator.rb', line 61

def self.get(country_code, options = {})
  raise NoCountryException if country_code.nil?

  country_code.upcase!

  base_country_code = self.base_country

  if options[:base_country_code] && options[:base_country_code] != self.base_country # different country code for the seller ?
    if rule_data = VAT_RATES[options[:base_country_code]]
      base_country_code = options[:base_country_code]
      rule = self.formalize_rate_rule(rule_data)
    end
  else
    rule = self.current_rate_rule
  end

  raise NoRuleFoundException if rule.nil?

  # same country for both the buyer and the seller, no need to go further
  return rule.rate if base_country_code == country_code

  if self.is_an_european_country?(country_code)
    # case when the country of the buyer is in Europe, check if he has a vat_number
    if options[:vat_number].present? && self.validate_vat_number?(options[:vat_number], options[:validation])
      rule.no_rate
    else
      rule.rate
    end
  elsif rate = rule.exceptions[country_code] # exceptions (France for instance has many exceptions for the DOM-TOM territories)
    rate
  else
    rule.no_rate
  end
end

.is_an_european_country?(country_code) ⇒ Boolean

Returns:

  • (Boolean)


96
97
98
# File 'lib/vat_calculator.rb', line 96

def self.is_an_european_country?(country_code)
  VatValidator::VAT_PATTERNS.keys.include?(country_code.upcase)
end

.validate_vat_number?(number, level = :none) ⇒ Boolean

Returns:

  • (Boolean)


100
101
102
103
104
105
106
107
# File 'lib/vat_calculator.rb', line 100

def self.validate_vat_number?(number, level = :none)
  case level
  when :simple  then self.vat_format_valid?(number)
  when :full    then self.vat_format_valid?(number) && self.vat_number_existence?(number)
  else
    true
  end
end

.vat_format_valid?(number) ⇒ Boolean

Returns:

  • (Boolean)


109
110
111
# File 'lib/vat_calculator.rb', line 109

def self.vat_format_valid?(number)
  number =~ VatValidator::VAT_PATTERNS.values.detect { |p| number.to_s =~ p }
end

.vat_number_existence?(number) ⇒ Boolean

Returns:

  • (Boolean)


113
114
115
# File 'lib/vat_calculator.rb', line 113

def self.vat_number_existence?(number)
  VatValidator::ViesChecker.check(number)
end