Add data and helper methods
parent
ec9bdf9be7
commit
0e890b8650
|
@ -6,3 +6,5 @@
|
||||||
/pkg/
|
/pkg/
|
||||||
/spec/reports/
|
/spec/reports/
|
||||||
/tmp/
|
/tmp/
|
||||||
|
/vendor/
|
||||||
|
/Gemfile.lock
|
||||||
|
|
6
Rakefile
6
Rakefile
|
@ -1,4 +1,8 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require "bundler/gem_tasks"
|
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"
|
require_relative "vat_rate/version"
|
||||||
|
|
||||||
module VatRate
|
require 'psych'
|
||||||
class Error < StandardError; end
|
require 'date'
|
||||||
# Your code goes here...
|
|
||||||
|
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
|
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
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module VatRate
|
class VatRate
|
||||||
VERSION = "0.1.0"
|
VERSION = "0.1.0"
|
||||||
end
|
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.authors = ["Guillaume Dott"]
|
||||||
spec.email = ["guillaume+github@dott.fr"]
|
spec.email = ["guillaume+github@dott.fr"]
|
||||||
|
|
||||||
spec.summary = "TODO: Write a short summary, because RubyGems requires one."
|
spec.summary = "VAT rates and helper methods"
|
||||||
spec.description = "TODO: Write a longer description or delete this line."
|
spec.homepage = "https://code.amnesix.eu/guillaume/vat_rate"
|
||||||
spec.homepage = "TODO: Put your gem's website or public repo URL here."
|
|
||||||
spec.required_ruby_version = ">= 3.0.0"
|
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["homepage_uri"] = spec.homepage
|
||||||
spec.metadata["source_code_uri"] = "TODO: Put your gem's public repo URL here."
|
spec.metadata["source_code_uri"] = "https://code.amnesix.eu/guillaume/vat_rate"
|
||||||
spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
|
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.
|
# 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.
|
# 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
|
# Uncomment to register a new dependency of your gem
|
||||||
# spec.add_dependency "example-gem", "~> 1.0"
|
# 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
|
# For more information and examples about making a new gem, check out our
|
||||||
# guide at: https://bundler.io/guides/creating_gem.html
|
# guide at: https://bundler.io/guides/creating_gem.html
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue