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
-
#customer_sync_instance ⇒ Customer::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.
-
#delete_from_taxjar ⇒ String, true
Deletes the document's transaction from TaxJar (e.g. when an invoice is voided).
-
#evaluate_taxjar_submission ⇒ String?
Decides whether to submit the document to TaxJar.
- #record_already_exists_on_taxjar? ⇒ Boolean
-
#resubmit_to_taxjar ⇒ String, true
Updates an already-submitted TaxJar transaction (fires after invoice edits, credit-memo offsets, etc.).
- #should_be_submitted_to_taxjar? ⇒ Boolean
- #should_sync_customer_with_taxjar? ⇒ Boolean
-
#submit_to_taxjar ⇒ String, true
Pushes the document to TaxJar for the first time — syncs the customer / exemption first, then submits the transaction.
-
#sync_customer_with_taxjar ⇒ void
Pushes the customer / exempt-address record to TaxJar so the submission API has the right party on file.
-
#taxjar_customer_id ⇒ String?
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.
-
#taxjar_submission_instance ⇒ Object?
Builds the right TaxJar-submission service for the host class — one of Invoicing::SubmitToTaxjar, CreditMemo::SubmitToTaxjar, or Receipt::SubmitToTaxjar.
Instance Method Details
#customer_sync_instance ⇒ Customer::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_taxjar ⇒ String, true
Deletes the document's transaction from TaxJar (e.g. when an
invoice is voided). Marks the document :exempt on success.
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. end end |
#evaluate_taxjar_submission ⇒ String?
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.
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 should_be_submitted_to_taxjar? 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
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_taxjar ⇒ String, 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.
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? submitted_to_taxjar else res. end end |
#should_be_submitted_to_taxjar? ⇒ 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 should_be_submitted_to_taxjar? return false if shipping_address.nil? || shipping_address.state_code.nil? || !shipping_address.country_iso.in?(%w[US CA]) if is_a?(ReceiptDetail) ledger_company_account.present? && TAXABLE_STATES.detect do |state, v| state == shipping_address.state_code.to_sym && v[:source] == :taxjar && v[:account] == ledger_company_account.ledger_detail_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
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_taxjar ⇒ String, 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.
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? submitted_to_taxjar else res. end end |
#sync_customer_with_taxjar ⇒ void
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_id ⇒ String?
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.
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_instance ⇒ Object?
Builds the right TaxJar-submission service for the host class —
one of Invoicing::SubmitToTaxjar, CreditMemo::SubmitToTaxjar,
or Receipt::SubmitToTaxjar.
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 |