Class: TaxRate
- Inherits:
-
ApplicationRecord
- Object
- ActiveRecord::Base
- ApplicationRecord
- TaxRate
- Includes:
- Models::Auditable
- Defined in:
- app/models/tax_rate.rb
Overview
== Schema Information
Table name: tax_rates
Database name: primary
id :integer not null, primary key
country_iso :string not null
description :string(255)
effective_date :date not null
expiration_date :date
goods :decimal(6, 4)
services :decimal(6, 4)
shipping :decimal(6, 4)
short_name :string(255)
state_code :string
tax_type :string(3) not null
use_food :decimal(6, 4)
use_merch :decimal(6, 4)
sales_tax_credit_account_id :integer
sales_tax_payable_account_id :integer
use_tax_account_id :integer
Constant Summary
Constants included from Models::Auditable
Models::Auditable::ALWAYS_IGNORED
Belongs to collapse
- #country ⇒ Country
- #sales_tax_credit_account ⇒ LedgerDetailAccount
- #sales_tax_payable_account ⇒ LedgerDetailAccount
- #state ⇒ State
- #use_tax_account ⇒ LedgerDetailAccount
Methods included from Models::Auditable
Has many collapse
- #resource_tax_rates ⇒ ActiveRecord::Relation<ResourceTaxRate>
- #voucher_items ⇒ ActiveRecord::Relation<VoucherItem>
Class Method Summary collapse
- .description_for(tax_type, destination_country: nil) ⇒ Object
-
.effective_now ⇒ ActiveRecord::Relation<TaxRate>
A relation of TaxRates that are effective now.
-
.effective_on ⇒ ActiveRecord::Relation<TaxRate>
A relation of TaxRates that are effective on.
- .ransackable_scopes(_auth_object = nil) ⇒ Object
- .rates_for_voucher_entry ⇒ Object
-
.sales_tax ⇒ ActiveRecord::Relation<TaxRate>
A relation of TaxRates that are sales tax.
-
.sales_tax_credit ⇒ ActiveRecord::Relation<TaxRate>
A relation of TaxRates that are sales tax credit.
- .tax_types_for_select ⇒ Object
-
.taxjar_summary_rates(country_code: nil) ⇒ Object
Returns an array of tax rate for a specific country, this is designed for single tax rate regardless of origin/destination, such as in canada { :country_code => "CA", :country => "Canada", :region_code => "NB", :region => "New Brunswick", :minimum_rate => { :label => "GST", :rate => 0.05 }, :average_rate => { :label => "HST", :rate => 0.15 } }.
-
.use_internal_rates ⇒ ActiveRecord::Relation<TaxRate>
A relation of TaxRates that are use internal rates.
-
.use_tax ⇒ ActiveRecord::Relation<TaxRate>
A relation of TaxRates that are use tax.
Instance Method Summary collapse
- #active? ⇒ Boolean
- #expiration_date_after_effective_date ⇒ Object protected
- #has_overlapping_tax_rates ⇒ Object protected
- #tax_explanation ⇒ Object
- #tax_type_available_in_state ⇒ Object protected
Methods included from Models::Auditable
#all_skipped_columns, #audit_reference_data, #should_not_save_version, #stamp_record
Methods inherited from ApplicationRecord
ransackable_associations, ransackable_attributes, ransortable_attributes, #to_relation
Methods included from Models::EventPublishable
Class Method Details
.description_for(tax_type, destination_country: nil) ⇒ Object
121 122 123 124 125 126 127 128 |
# File 'app/models/tax_rate.rb', line 121 def self.description_for(tax_type, destination_country: nil) d = TAXABLE_STATES.detect {|k,v| v[:tax_type] == tax_type}.try(:[], 1).try(:[], :description) if d.nil? && tax_type == 'vat' d = +"VAT" d << " #{destination_country.name}" if destination_country end d ||= 'Sales Tax' end |
.effective_now ⇒ ActiveRecord::Relation<TaxRate>
A relation of TaxRates that are effective now. Active Record Scope
60 |
# File 'app/models/tax_rate.rb', line 60 scope :effective_now, -> { effective_on(Date.current) } |
.effective_on ⇒ ActiveRecord::Relation<TaxRate>
A relation of TaxRates that are effective on. Active Record Scope
59 |
# File 'app/models/tax_rate.rb', line 59 scope :effective_on, ->(date) { where("effective_date <= :date and (expiration_date IS NULL OR expiration_date >= :date)", date: date) } |
.ransackable_scopes(_auth_object = nil) ⇒ Object
113 114 115 |
# File 'app/models/tax_rate.rb', line 113 def self.ransackable_scopes(_auth_object = nil) %i[effective_on] end |
.rates_for_voucher_entry ⇒ Object
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'app/models/tax_rate.rb', line 80 def self.rates_for_voucher_entry rates = [] TaxRate.effective_on(Date.current).each do |tr| ["goods", "services", "shipping"].each do |rate_type| if tr.send(rate_type).present? and tr.send(rate_type) != 0 if tr.state_code.present? rates << {"label" => "#{tr.tax_type.upcase} #{rate_type} #{tr.state_code}", "value" => "#{tr.tax_type.upcase}_#{rate_type}_#{tr.state_code}", "rate" => tr.send(rate_type)*100, "id" => tr.id, "tax_type" => "V"} else rates << {"label" => "#{tr.tax_type.upcase} #{rate_type} #{tr.country_iso}", "value" => "#{tr.tax_type.upcase}_#{rate_type}_#{tr.country_iso}", "rate" => tr.send(rate_type)*100, "id" => tr.id, "tax_type" => "V"} end end end ["use_food", "use_merch"].each do |rate_type| if tr.send(rate_type).present? and tr.send(rate_type) != 0 if tr.state_code.present? rates << {"label" => "#{tr.tax_type.upcase} #{rate_type} #{tr.state_code}", "value" => "#{tr.tax_type.upcase}_#{rate_type}_#{tr.state_code}", "rate" => tr.send(rate_type)*100, "id" => tr.id, "tax_type" => "U"} else rates << {"label" => "#{tr.tax_type.upcase} #{rate_type} #{tr.country_iso}", "value" => "#{tr.tax_type.upcase}_#{rate_type}_#{tr.country_iso}", "rate" => tr.send(rate_type)*100, "id" => tr.id, "tax_type" => "U"} end end end end return rates end |
.sales_tax ⇒ ActiveRecord::Relation<TaxRate>
A relation of TaxRates that are sales tax. Active Record Scope
63 |
# File 'app/models/tax_rate.rb', line 63 scope :sales_tax, -> { where("sales_tax_payable_account_id is not null") } |
.sales_tax_credit ⇒ ActiveRecord::Relation<TaxRate>
A relation of TaxRates that are sales tax credit. Active Record Scope
61 |
# File 'app/models/tax_rate.rb', line 61 scope :sales_tax_credit, -> { where("sales_tax_credit_account_id is not null") } |
.tax_types_for_select ⇒ Object
117 118 119 |
# File 'app/models/tax_rate.rb', line 117 def self.tax_types_for_select TAXABLE_STATES.collect { |_k, v| v[:tax_type].to_s }.uniq + ['vat'] end |
.taxjar_summary_rates(country_code: nil) ⇒ Object
Returns an array of tax rate for a specific country, this is designed for single tax rate
regardless of origin/destination, such as in canada
{
:country_code => "CA",
:country => "Canada",
:region_code => "NB",
:region => "New Brunswick",
:minimum_rate => {
:label => "GST",
:rate => 0.05
},
:average_rate => {
:label => "HST",
:rate => 0.15
}
}
147 148 149 150 151 152 153 |
# File 'app/models/tax_rate.rb', line 147 def self.taxjar_summary_rates(country_code: nil) rates = Api::Taxjar.client.summary_rates if country_code rates = rates.select{|h| h[:country_code] == country_code} end rates end |
.use_internal_rates ⇒ ActiveRecord::Relation<TaxRate>
A relation of TaxRates that are use internal rates. Active Record Scope
64 |
# File 'app/models/tax_rate.rb', line 64 scope :use_internal_rates, -> (states) { where(state_code: states) } |
.use_tax ⇒ ActiveRecord::Relation<TaxRate>
A relation of TaxRates that are use tax. Active Record Scope
62 |
# File 'app/models/tax_rate.rb', line 62 scope :use_tax, -> { where("use_tax_account_id is not null") } |
Instance Method Details
#active? ⇒ Boolean
76 77 78 |
# File 'app/models/tax_rate.rb', line 76 def active? effective_date <= Date.current and expiration_date > Date.current end |
#country ⇒ Country
54 |
# File 'app/models/tax_rate.rb', line 54 belongs_to :country, foreign_key: 'country_iso', primary_key: 'iso', optional: true |
#expiration_date_after_effective_date ⇒ Object (protected)
161 162 163 |
# File 'app/models/tax_rate.rb', line 161 def expiration_date_after_effective_date errors.add(:expiration_date, "cannot be before effective date") if expiration_date and effective_date and expiration_date < effective_date end |
#has_overlapping_tax_rates ⇒ Object (protected)
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 |
# File 'app/models/tax_rate.rb', line 165 def has_overlapping_tax_rates return unless effective_date && tax_type # Overlap requires the same country + state + tax_type. Without the # country_iso filter, different-country rates that share an empty # state_code (e.g. EU VAT) were wrongly flagged as conflicts. scope = TaxRate.where(country_iso: country_iso, state_code: state_code, tax_type: tax_type) scope = scope.where.not(id: id) if persisted? # Two date ranges overlap when each starts on or before the other ends. # A NULL expiration_date means "open-ended" / no upper bound, so both the # stored rate and the record being validated may be unbounded on the right. # overlap ⇔ r.effective_date <= new.expiration AND new.effective_date <= r.expiration_date scope = scope.where('tax_rates.effective_date <= ?', expiration_date) if expiration_date scope = scope.where('tax_rates.expiration_date IS NULL OR tax_rates.expiration_date >= ?', effective_date) conflicting_ids = scope.pluck(:id) return if conflicting_ids.empty? errors.add(:base, "Existing tax rates with id: #{conflicting_ids.join(',')} in place for these values and with the same date coverage. Cannot save an overlapping tax rate.") end |
#resource_tax_rates ⇒ ActiveRecord::Relation<ResourceTaxRate>
57 |
# File 'app/models/tax_rate.rb', line 57 has_many :resource_tax_rates |
#sales_tax_credit_account ⇒ LedgerDetailAccount
52 |
# File 'app/models/tax_rate.rb', line 52 belongs_to :sales_tax_credit_account, class_name: "LedgerDetailAccount", optional: true |
#sales_tax_payable_account ⇒ LedgerDetailAccount
53 |
# File 'app/models/tax_rate.rb', line 53 belongs_to :sales_tax_payable_account, class_name: "LedgerDetailAccount", optional: true |
#state ⇒ State
50 |
# File 'app/models/tax_rate.rb', line 50 belongs_to :state, foreign_key: 'state_code', primary_key: 'code', optional: true |
#tax_explanation ⇒ Object
105 106 107 108 109 110 111 |
# File 'app/models/tax_rate.rb', line 105 def tax_explanation if use_tax_account_id != nil "U" else "V" end end |
#tax_type_available_in_state ⇒ Object (protected)
157 158 159 |
# File 'app/models/tax_rate.rb', line 157 def tax_type_available_in_state errors.add(:tax_type, "Tax Type is not available in this state") if state_code != 'IL' and tax_type == 'il' end |
#use_tax_account ⇒ LedgerDetailAccount
51 |
# File 'app/models/tax_rate.rb', line 51 belongs_to :use_tax_account, class_name: "LedgerDetailAccount", optional: true |
#voucher_items ⇒ ActiveRecord::Relation<VoucherItem>
56 |
# File 'app/models/tax_rate.rb', line 56 has_many :voucher_items |