Add data and helper methods

main
Guillaume Dott 2024-11-12 14:37:26 +01:00
parent ec9bdf9be7
commit 0e890b8650
8 changed files with 280 additions and 15 deletions

2
.gitignore vendored
View File

@ -6,3 +6,5 @@
/pkg/ /pkg/
/spec/reports/ /spec/reports/
/tmp/ /tmp/
/vendor/
/Gemfile.lock

View File

@ -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

View File

@ -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

176
lib/vat_rate.yml 100644
View File

@ -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

View File

@ -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

View File

@ -1,4 +0,0 @@
module VatRate
VERSION: String
# See the writing guide of rbs: https://github.com/ruby/rbs#guides
end

View File

@ -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

View File

@ -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