Module: Models::TaxjarSubmittable

Extended by:
ActiveSupport::Concern
Included in:
CreditMemo, Invoice, ReceiptDetail
Defined in:
app/concerns/models/taxjar_submittable.rb

Overview

Mixin shared by Invoice, CreditMemo and ReceiptDetail that
owns the taxjar_state state machine and routes submissions through
the appropriate SubmitToTaxjar service. Sales tax in
TaxJar-administered states must be reported in TaxJar's reporting
API as well as our own ledger; this concern keeps those two
in-sync.

Instance Method Summary collapse

Instance Method Details

#customer_sync_instanceCustomer::SyncWithTaxjar, ...

Builds the right customer-sync service when this document needs
to push exemption certificates / customer addresses to TaxJar
ahead of submission — Customer::SyncWithTaxjar for exempt
billers and Customer::SyncAddressWithTaxjar for e-commerce-misc
marketplace billers. Nil when no sync is needed.



77
78
79
80
81
82
83
84
# File 'app/concerns/models/taxjar_submittable.rb', line 77

def customer_sync_instance
  if billing_entity.tax_exemptions.effective_on(effective_date).where(state_code: shipping_address.state_code).any?
    Customer::SyncWithTaxjar.new(billing_entity, { effective_date: })
  elsif tax_exempt? && billing_entity.is_e_commerce_misc?
    # used for invoices/credit memos sold through etailers where the receiving customer is tax exempt
    Customer::SyncAddressWithTaxjar.new(billing_entity, shipping_address, { effective_date: })
  end
end

#delete_from_taxjarString, true

Deletes the document's transaction from TaxJar (e.g. when an
invoice is voided). Marks the document :exempt on success.

Returns:

  • (String, true)


121
122
123
124
125
126
127
128
# File 'app/concerns/models/taxjar_submittable.rb', line 121

def delete_from_taxjar
  res = taxjar_submission_instance.delete
  if res.success?
    exempt_from_taxjar
  else
    res.message
  end
end

#evaluate_taxjar_submissionString?

Decides whether to submit the document to TaxJar. Production
invoices are queued via SubmitInvoiceToTaxjarWorker on a 30s
delay (so the AR transaction commits first); CI invoices are
always exempt because the marketplace remits tax. Non-submittable
rows go straight to :exempt.

Returns:

  • (String, nil)

    returns 'already submitted' when not pending



40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'app/concerns/models/taxjar_submittable.rb', line 40

def evaluate_taxjar_submission
  return 'already submitted' unless pending_submission?

  if 
    if is_a?(Invoice) && Rails.env.production? && !(try(:invoice_type) == 'CI')
      # Queue worker after transaction commits to ensure invoice exists
      after_commit { SubmitInvoiceToTaxjarWorker.perform_in(30.seconds, id) }
    else
      submit_to_taxjar
    end
  else
    exempt_from_taxjar
  end
end

#record_already_exists_on_taxjar?Boolean

Returns:

  • (Boolean)


156
157
158
# File 'app/concerns/models/taxjar_submittable.rb', line 156

def record_already_exists_on_taxjar?
  taxjar_submission_instance.existing_record?
end

#resubmit_to_taxjarString, true

Updates an already-submitted TaxJar transaction (fires after
invoice edits, credit-memo offsets, etc.). Returns true on
success or the error message on failure.

Returns:

  • (String, true)


107
108
109
110
111
112
113
114
115
# File 'app/concerns/models/taxjar_submittable.rb', line 107

def resubmit_to_taxjar
  sync_customer_with_taxjar
  res = taxjar_submission_instance.update
  if res.success?
    
  else
    res.message
  end
end

#should_be_submitted_to_taxjar?Boolean

Returns:

  • (Boolean)


160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# File 'app/concerns/models/taxjar_submittable.rb', line 160

def 
  return false if shipping_address.nil? || shipping_address.state_code.nil? || !shipping_address.country_iso.in?(%w[US CA])

  if is_a?(ReceiptDetail)
    .present? &&
      TAXABLE_STATES.detect do |state, v|
        state == shipping_address.state_code.to_sym &&
          v[:source] == :taxjar &&
          v[:account] == ..number
      end
  else
    TAXABLE_STATES.detect do |state, v|
      state == shipping_address.state_code.to_sym &&
        v[:source] == :taxjar &&
        (v[:effective].nil? || Date.parse(v[:effective]) <= effective_date)
    end
  end
end

#should_sync_customer_with_taxjar?Boolean

Returns:

  • (Boolean)


179
180
181
182
183
184
# File 'app/concerns/models/taxjar_submittable.rb', line 179

def should_sync_customer_with_taxjar?
  return false if billing_entity.nil?

  billing_entity.tax_exemptions.effective_on(effective_date).where(state_code: shipping_address.state_code).any? ||
    (tax_exempt? && billing_entity.is_e_commerce_misc?)
end

#submit_to_taxjarString, true

Pushes the document to TaxJar for the first time — syncs the
customer / exemption first, then submits the transaction.
Advances the state machine to :submitted on success, or returns
the failure message string.

Returns:

  • (String, true)


92
93
94
95
96
97
98
99
100
# File 'app/concerns/models/taxjar_submittable.rb', line 92

def submit_to_taxjar
  sync_customer_with_taxjar
  res = taxjar_submission_instance.submit
  if res.success?
    
  else
    res.message
  end
end

#sync_customer_with_taxjarvoid

This method returns an undefined value.

Pushes the customer / exempt-address record to TaxJar so the
submission API has the right party on file. No-op outside
production and when no sync is required.



135
136
137
138
139
# File 'app/concerns/models/taxjar_submittable.rb', line 135

def sync_customer_with_taxjar
  return true unless Rails.env.production?

  customer_sync_instance.sync if should_sync_customer_with_taxjar?
end

#taxjar_customer_idString?

TaxJar's customer id corresponding to this document's billing
entity — returns the synced id when an exemption is on file,
otherwise the unscoped customer id.

Returns:

  • (String, nil)


146
147
148
149
150
151
152
153
154
# File 'app/concerns/models/taxjar_submittable.rb', line 146

def taxjar_customer_id
  return nil if billing_entity.nil?

  if should_sync_customer_with_taxjar?
    customer_sync_instance.taxjar_id
  else
    Customer::SyncWithTaxjar.new(billing_entity).taxjar_id
  end
end

#taxjar_submission_instanceObject?

Builds the right TaxJar-submission service for the host class —
one of Invoicing::SubmitToTaxjar, CreditMemo::SubmitToTaxjar,
or Receipt::SubmitToTaxjar.

Returns:

  • (Object, nil)


60
61
62
63
64
65
66
67
68
# File 'app/concerns/models/taxjar_submittable.rb', line 60

def taxjar_submission_instance
  if is_a?(Invoice)
    Invoicing::SubmitToTaxjar.new(self)
  elsif is_a?(CreditMemo)
    CreditMemo::SubmitToTaxjar.new(self)
  elsif is_a?(ReceiptDetail)
    Receipt::SubmitToTaxjar.new(self)
  end
end