Module: SpreeAvatax::SalesShared

Defined in:
app/models/spree_avatax/sales_shared.rb

Defined Under Namespace

Classes: InvalidApiResponse

Constant Summary collapse

DESTINATION_CODE =
"1"
SHIPPING_TAX_CODE =
'FR020100'
SHIPPING_DESCRIPTION =
'Shipping Charge'

Class Method Summary collapse

Class Method Details

.avatax_id(record) ⇒ Object

sometimes we have to store different types of things in a single array (like line items and shipments). this allows us to provide a unique identifier to each record.



90
91
92
# File 'app/models/spree_avatax/sales_shared.rb', line 90

def avatax_id(record)
  "#{record.class.name}-#{record.id}"
end

.build_tax_line_data(order, avatax_result) ⇒ Object

returns an array like: [

{tax_line: {...}, record: #<Spree::LineItem id=111>},
{tax_line: {...}, record: #<Spree::LineItem id=222>},
{tax_line: {...}, record: #<Spree::Shipment id=111>},

]



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'app/models/spree_avatax/sales_shared.rb', line 62

def build_tax_line_data(order, avatax_result)
  # Array.wrap is required because the XML engine the Avatax gem uses turns child nodes into
  #   {...} instead of [{...}] when there is only one child.
  tax_lines = Array.wrap(avatax_result[:tax_lines][:tax_line])

  # builds a hash like: {"L-111": {record: #<Spree::LineItem ...>}, ...}
  data = (order.line_items + order.shipments).map { |r| [avatax_id(r), {record: r}] }.to_h

  # adds :tax_line to each entry in the data
  tax_lines.each do |tax_line|
    avatax_id = tax_line[:no]
    if data[avatax_id]
      data[avatax_id][:tax_line] = tax_line
    else
      raise InvalidApiResponse.new("Couldn't find #{avatax_id.inspect} from avatax response in known ids #{data.keys.inspect}")
    end
  end

  missing = data.select { |avatax_id, data| data[:tax_line].nil? }
  if missing.any?
    raise InvalidApiResponse.new("missing tax data for #{missing.keys}")
  end

  data.values
end

.get_tax(order, doc_type) ⇒ Object

Queries Avatax for taxes on a specific order using the specified doc_type. SalesOrder doc types are not persisted on Avatax. SalesInvoice doc types do persist an uncommitted record on Avatax.



15
16
17
18
19
20
21
22
23
24
25
26
# File 'app/models/spree_avatax/sales_shared.rb', line 15

def get_tax(order, doc_type)
  params = gettax_params(order, doc_type)

  logger.info "[avatax] gettax order=#{order.id} doc_type=#{doc_type}"
  logger.debug { "[avatax] params: #{params.to_json}" }

  response = SpreeAvatax::Shared.get_tax(params)

  SpreeAvatax::Shared.require_success!(response)

  response
end

.reset_tax_attributes(order) ⇒ Object

Clears previously-set tax attributes from an order, if any, unless the order has already been completed.

Parameters:

  • order (Spree::Order)

    the order



99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'app/models/spree_avatax/sales_shared.rb', line 99

def reset_tax_attributes(order)
  return if order.completed?

  # Delete the avatax_sales_invoice to avoid accidentally committing it
  # later.
  if invoice = order.avatax_sales_invoice
    if invoice.committed_at
      raise SpreeAvatax::SalesInvoice::AlreadyCommittedError.new(
        "Tried to clear tax attributes for already-committed order #{order.number}"
      )
    else
      invoice.destroy!
    end
  end

  destroyed_adjustments = order.all_adjustments.tax.destroy_all
  return if destroyed_adjustments.empty?

  taxable_records = order.line_items + order.shipments
  taxable_records.each do |taxable_record|
    taxable_record.update_attributes!({
      additional_tax_total: 0,
      adjustment_total: 0,
      pre_tax_amount: taxable_record.discounted_amount.round(2),
      included_tax_total: 0,
    })

    Spree::ItemAdjustments.new(taxable_record).update
    taxable_record.save!
  end

  order.update_attributes!({
    additional_tax_total: 0,
    adjustment_total: 0,
    included_tax_total: 0,
  })

  order.update!
  order.save!
end

.update_taxes(order, tax_line_data) ⇒ Object



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'app/models/spree_avatax/sales_shared.rb', line 28

def update_taxes(order, tax_line_data)
  reset_tax_attributes(order)

  tax_line_data.each do |data|
    record, tax_line = data[:record], data[:tax_line]

    record.update_column(:pre_tax_amount, record.discounted_amount.round(2))

    tax = BigDecimal.new(tax_line[:tax]).abs

    record.adjustments.tax.create!({
      adjustable: record,
      amount:     tax,
      order:      order,
      label:      Spree.t(:avatax_label),
      included:   false, # would be true for VAT
      source:     Spree::TaxRate.avatax_the_one_rate,
      finalized:  true, # this tells spree not to automatically recalculate avatax tax adjustments
    })

    Spree::ItemAdjustments.new(record).update
    record.save!
  end

  Spree::OrderUpdater.new(order).update
  order.save!
end