ministryofjustice/Claim-for-Crown-Court-Defence

View on GitHub
app/models/vat_rate.rb

Summary

Maintainability
A
0 mins
Test Coverage
A
100%
# == Schema Information
#
# Table name: vat_rates
#
#  id               :integer          not null, primary key
#  rate_base_points :integer
#  effective_date   :date
#  created_at       :datetime
#  updated_at       :datetime
#

# Class to return the vat rate in base points (i.e. 1750 = a vat rate of 17.5%).
# All rates are cached in a class variable on first use to prevent re-reading the vat_rates table
# every time.
#
class VatRate < ApplicationRecord
  class MissingVatRateError < RuntimeError; end

  validates :effective_date, uniqueness: true

  class << self
    def for_date(date)
      rate_for_date(date)
    end

    # Apply past, present or 0% VAT rates
    def vat_amount(amount_excluding_vat, date, calculate: true)
      rate = calculate ? VatRate.for_date(date) : 0
      (amount_excluding_vat * rate / 10_000.0).round(2)
    end

    # returns "22.25%", "17/5%', 8%", etc
    def pretty_rate(date)
      rate = rate_for_date(date) / 100.0

      # transform to integer if whole number to supress printing of .0
      rate = rate.to_i if (rate - rate.to_i).zero?
      format('%{rate}%%', rate: rate.to_s)
    end

    private

    def rates
      VatRate.order(effective_date: :desc)
    end

    def rate_for_date(date)
      result = nil
      rates.each do |rec|
        unless date < rec.effective_date
          result = rec
          break
        end
      end
      err_msg = "There is no VAT rate for date #{date.strftime(Settings.date_format)}"
      raise VatRate::MissingVatRateError, err_msg if result.nil?
      result.rate_base_points
    end
  end
end