Add data and helper methods
parent
ec9bdf9be7
commit
0e890b8650
|
@ -6,3 +6,5 @@
|
|||
/pkg/
|
||||
/spec/reports/
|
||||
/tmp/
|
||||
/vendor/
|
||||
/Gemfile.lock
|
||||
|
|
6
Rakefile
6
Rakefile
|
@ -1,4 +1,8 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require "bundler/gem_tasks"
|
||||
task default: %i[]
|
||||
|
||||
require "minitest/test_task"
|
||||
Minitest::TestTask.create
|
||||
|
||||
task default: :test
|
||||
|
|
|
@ -2,7 +2,50 @@
|
|||
|
||||
require_relative "vat_rate/version"
|
||||
|
||||
module VatRate
|
||||
class Error < StandardError; end
|
||||
# Your code goes here...
|
||||
require 'psych'
|
||||
require 'date'
|
||||
|
||||
class VatRate
|
||||
CATEGORIES = %i(standard parking reduced super_reduced)
|
||||
RATES = Psych.safe_load_file(__dir__ + "/vat_rate.yml", permitted_classes: [Date])
|
||||
|
||||
def initialize(country:, category: :standard, date: Date.today, rate: nil)
|
||||
raise ArgumentError unless CATEGORIES.include?(category)
|
||||
|
||||
@category = category
|
||||
@country = country.to_s
|
||||
@date = date
|
||||
|
||||
if rate
|
||||
@rate = rate
|
||||
elsif RATES["#{@category}_rates"].key?(@country)
|
||||
@rate = RATES["#{@category}_rates"][@country].detect do |rate_data|
|
||||
if rate
|
||||
rate == rate_data['rate']
|
||||
else
|
||||
!rate_data.key?('from') || date.to_date >= rate_data['from']
|
||||
end
|
||||
end&.fetch('rate') || 0
|
||||
else
|
||||
@rate = 0
|
||||
end
|
||||
end
|
||||
|
||||
attr_reader :rate
|
||||
|
||||
def amount_with_vat(amount)
|
||||
amount * (100 + @rate) / 100.0
|
||||
end
|
||||
|
||||
def amount_without_vat(amount)
|
||||
amount * 100.0 / (100 + @rate)
|
||||
end
|
||||
|
||||
def vat_amount(amount, has_vat: false)
|
||||
if has_vat
|
||||
amount * @rate / (100.0 + @rate)
|
||||
else
|
||||
amount * @rate / 100.0
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,176 @@
|
|||
standard_rates:
|
||||
AT:
|
||||
- rate: 20
|
||||
BE:
|
||||
- rate: 21
|
||||
BG:
|
||||
- rate: 20
|
||||
HR:
|
||||
- rate: 25
|
||||
CY:
|
||||
- rate: 19
|
||||
CZ:
|
||||
- rate: 21
|
||||
DK:
|
||||
- rate: 25
|
||||
EE:
|
||||
- rate: 22
|
||||
FI:
|
||||
- rate: 24
|
||||
FR:
|
||||
- rate: 20
|
||||
from: 2014-01-01
|
||||
- rate: 19.6
|
||||
DE:
|
||||
- rate: 19
|
||||
GR:
|
||||
- rate: 24
|
||||
HU:
|
||||
- rate: 27
|
||||
IS:
|
||||
- rate: 24
|
||||
IE:
|
||||
- rate: 23
|
||||
IT:
|
||||
- rate: 22
|
||||
LV:
|
||||
- rate: 21
|
||||
LT:
|
||||
- rate: 21
|
||||
LU:
|
||||
- rate: 17
|
||||
MT:
|
||||
- rate: 18
|
||||
NL:
|
||||
- rate: 21
|
||||
"NO":
|
||||
- rate: 25
|
||||
PL:
|
||||
- rate: 23
|
||||
PT:
|
||||
- rate: 23
|
||||
RO:
|
||||
- rate: 19
|
||||
SK:
|
||||
- rate: 20
|
||||
SI:
|
||||
- rate: 22
|
||||
ES:
|
||||
- rate: 21
|
||||
SE:
|
||||
- rate: 25
|
||||
CH:
|
||||
- rate: 8.1
|
||||
TR:
|
||||
- rate: 20
|
||||
GB:
|
||||
- rate: 20
|
||||
parking_rates:
|
||||
AT:
|
||||
- rate: 13
|
||||
BE:
|
||||
- rate: 12
|
||||
IE:
|
||||
- rate: 13.5
|
||||
LU:
|
||||
- rate: 14
|
||||
PT:
|
||||
- rate: 13
|
||||
reduced_rates:
|
||||
AT:
|
||||
- rate: 10
|
||||
- rate: 13
|
||||
BE:
|
||||
- rate: 6
|
||||
- rate: 12
|
||||
BG:
|
||||
- rate: 9
|
||||
HR:
|
||||
- rate: 5
|
||||
- rate: 13
|
||||
CY:
|
||||
- rate: 5
|
||||
- rate: 9
|
||||
CZ:
|
||||
- rate: 12
|
||||
EE:
|
||||
- rate: 9
|
||||
FI:
|
||||
- rate: 10
|
||||
- rate: 14
|
||||
FR:
|
||||
- rate: 5.5
|
||||
- rate: 10
|
||||
DE:
|
||||
- rate: 7
|
||||
GR:
|
||||
- rate: 6
|
||||
- rate: 13
|
||||
HU:
|
||||
- rate: 5
|
||||
- rate: 18
|
||||
IS:
|
||||
- rate: 11
|
||||
IE:
|
||||
- rate: 9
|
||||
- rate: 13.5
|
||||
IT:
|
||||
- rate: 5
|
||||
- rate: 10
|
||||
LV:
|
||||
- rate: 5
|
||||
- rate: 12
|
||||
LT:
|
||||
- rate: 5
|
||||
- rate: 9
|
||||
LU:
|
||||
- rate: 8
|
||||
MT:
|
||||
- rate: 5
|
||||
- rate: 7
|
||||
NL:
|
||||
- rate: 9
|
||||
"NO":
|
||||
- rate: 12
|
||||
- rate: 15
|
||||
PL:
|
||||
- rate: 5
|
||||
- rate: 8
|
||||
PT:
|
||||
- rate: 6
|
||||
- rate: 13
|
||||
RO:
|
||||
- rate: 5
|
||||
- rate: 9
|
||||
SK:
|
||||
- rate: 10
|
||||
SI:
|
||||
- rate: 5
|
||||
- rate: 9.5
|
||||
ES:
|
||||
- rate: 10
|
||||
SE:
|
||||
- rate: 6
|
||||
- rate: 12
|
||||
CH:
|
||||
- rate: 2.6
|
||||
- rate: 3.8
|
||||
TR:
|
||||
- rate: 10
|
||||
GB:
|
||||
- rate: 5
|
||||
super_reduced_rates:
|
||||
FR:
|
||||
- rate: 2.1
|
||||
IE:
|
||||
- rate: 4.8
|
||||
IT:
|
||||
- rate: 4
|
||||
LU:
|
||||
- rate: 3
|
||||
SK:
|
||||
- rate: 5
|
||||
ES:
|
||||
- rate: 4
|
||||
TR:
|
||||
- rate: 1
|
|
@ -1,5 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module VatRate
|
||||
class VatRate
|
||||
VERSION = "0.1.0"
|
||||
end
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
module VatRate
|
||||
VERSION: String
|
||||
# See the writing guide of rbs: https://github.com/ruby/rbs#guides
|
||||
end
|
|
@ -0,0 +1,43 @@
|
|||
require 'minitest/autorun'
|
||||
require 'vat_rate'
|
||||
|
||||
class TestVatRate < Minitest::Test
|
||||
def test_should_check_data
|
||||
assert_kind_of Hash, VatRate::RATES
|
||||
|
||||
VatRate::CATEGORIES.each do |category|
|
||||
VatRate::RATES["#{category}_rates"].each do |country, rates|
|
||||
assert_kind_of String, country
|
||||
assert_kind_of Array, rates
|
||||
rates.each do |rate|
|
||||
assert rate.key?('rate')
|
||||
assert_kind_of Numeric, rate['rate']
|
||||
assert_kind_of Date, rate['from'] if rate['from']
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_should_initialize_rate
|
||||
vat_rate = VatRate.new(country: :FR)
|
||||
assert_equal 20, vat_rate.rate
|
||||
|
||||
vat_rate = VatRate.new(country: "FR")
|
||||
assert_equal 20, vat_rate.rate
|
||||
end
|
||||
|
||||
def test_should_get_correct_rate_for_date
|
||||
vat_rate = VatRate.new(country: "FR", date: Date.new(2011))
|
||||
assert_equal 19.6, vat_rate.rate
|
||||
end
|
||||
|
||||
def test_should_get_amounts
|
||||
vat_rate = VatRate.new(country: "FR")
|
||||
assert_equal 20, vat_rate.rate
|
||||
assert_equal 40, vat_rate.vat_amount(200)
|
||||
assert_equal 40, vat_rate.vat_amount(200, has_vat: false)
|
||||
assert_equal 40, vat_rate.vat_amount(240, has_vat: true)
|
||||
assert_equal 240, vat_rate.amount_with_vat(200)
|
||||
assert_equal 200, vat_rate.amount_without_vat(240)
|
||||
end
|
||||
end
|
|
@ -8,16 +8,15 @@ Gem::Specification.new do |spec|
|
|||
spec.authors = ["Guillaume Dott"]
|
||||
spec.email = ["guillaume+github@dott.fr"]
|
||||
|
||||
spec.summary = "TODO: Write a short summary, because RubyGems requires one."
|
||||
spec.description = "TODO: Write a longer description or delete this line."
|
||||
spec.homepage = "TODO: Put your gem's website or public repo URL here."
|
||||
spec.summary = "VAT rates and helper methods"
|
||||
spec.homepage = "https://code.amnesix.eu/guillaume/vat_rate"
|
||||
spec.required_ruby_version = ">= 3.0.0"
|
||||
|
||||
spec.metadata["allowed_push_host"] = "TODO: Set to your gem server 'https://example.com'"
|
||||
spec.metadata["allowed_push_host"] = "https://rubygems.org"
|
||||
|
||||
spec.metadata["homepage_uri"] = spec.homepage
|
||||
spec.metadata["source_code_uri"] = "TODO: Put your gem's public repo URL here."
|
||||
spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
|
||||
spec.metadata["source_code_uri"] = "https://code.amnesix.eu/guillaume/vat_rate"
|
||||
spec.metadata["changelog_uri"] = "https://code.amnesix.eu/guillaume/vat_rate/src/branch/main/CHANGELOG.md"
|
||||
|
||||
# Specify which files should be added to the gem when it is released.
|
||||
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
||||
|
@ -35,6 +34,8 @@ Gem::Specification.new do |spec|
|
|||
# Uncomment to register a new dependency of your gem
|
||||
# spec.add_dependency "example-gem", "~> 1.0"
|
||||
|
||||
spec.add_development_dependency "minitest"
|
||||
|
||||
# For more information and examples about making a new gem, check out our
|
||||
# guide at: https://bundler.io/guides/creating_gem.html
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue