Class: Spree::TaxRate

Inherits:
ActiveRecord::Base
  • Object
show all
Includes:
Core::CalculatedAdjustments
Defined in:
app/models/spree/tax_rate.rb

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Core::CalculatedAdjustments

included

Class Method Details

.adjust(order, items) ⇒ Object



51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'app/models/spree/tax_rate.rb', line 51

def self.adjust(order, items)
  rates = self.match(order)
  tax_categories = rates.map(&:tax_category)
  relevant_items = items.select { |item| tax_categories.include?(item.tax_category) }
  relevant_items.each do |item|
    item.adjustments.tax.delete_all
    relevant_rates = rates.select { |rate| rate.tax_category == item.tax_category }
    store_pre_tax_amount(item, relevant_rates)
    relevant_rates.each do |rate|
      rate.adjust(order, item)
    end
  end
end

.defaultObject

For Vat the default rate is the rate that is configured for the default category It is needed for every price calculation (as all customer facing prices include vat ) The function returns the actual amount, which may be 0 in case of wrong setup, but is never nil



68
69
70
71
72
73
74
75
76
# File 'app/models/spree/tax_rate.rb', line 68

def self.default
  category = TaxCategory.includes(:tax_rates).where(is_default: true).first
  return 0 unless category

  address ||= Address.new(country_id: Spree::Config[:default_country_id])
  rate = category.tax_rates.detect { |rate| rate.zone.include? address }.try(:amount)

  rate || 0
end

.match(order) ⇒ Object

Gets the array of TaxRates appropriate for the specified order



27
28
29
30
31
32
33
# File 'app/models/spree/tax_rate.rb', line 27

def self.match(order)
  return [] unless order.tax_zone
  all.select do |rate|
    (!rate.included_in_price && (rate.zone == order.tax_zone || rate.zone.contains?(order.tax_zone) || (order.tax_address.nil? && rate.zone.default_tax))) ||
    rate.included_in_price
  end
end

.store_pre_tax_amount(item, rates) ⇒ Object

Pre-tax amounts must be stored so that we can calculate correct rate amounts in the future. For example: github.com/spree/spree/issues/4318#issuecomment-34723428



38
39
40
41
42
43
44
45
46
47
48
49
# File 'app/models/spree/tax_rate.rb', line 38

def self.store_pre_tax_amount(item, rates)
  if rates.any? { |r| r.included_in_price }
    case item
    when Spree::LineItem
      item_amount = item.discounted_amount
    when Spree::Shipment
      item_amount = item.discounted_cost
    end
    pre_tax_amount = item_amount / (1 + rates.map(&:amount).sum)
    item.update_column(:pre_tax_amount, pre_tax_amount)
  end
end

Instance Method Details

#adjust(order, item) ⇒ Object

Creates necessary tax adjustments for the order.



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'app/models/spree/tax_rate.rb', line 79

def adjust(order, item)
  amount = calculator.compute(item)
  return if amount == 0

  included = included_in_price &&
             Zone.default_tax.contains?(item.order.tax_zone)

  if amount < 0
    label = Spree.t(:refund) + ' ' + create_label
  end

  self.adjustments.create!({
    :adjustable => item,
    :amount => amount,
    :order => order,
    :label => label || create_label,
    :included => included
  })
end

#compute_amount(item) ⇒ Object

This method is used by Adjustment#update to recalculate the cost.



100
101
102
103
104
105
106
107
108
109
110
111
# File 'app/models/spree/tax_rate.rb', line 100

def compute_amount(item)
  if included_in_price
    if Zone.default_tax.contains? item.order.tax_zone
      calculator.compute(item)
    else
      # In this case, it's a refund.
      calculator.compute(item) * - 1
    end
  else
    calculator.compute(item)
  end
end