fix(taxes): skip zero-amount fees in the Anrok tax payload - #6289
Open
annvelents wants to merge 1 commit into
Open
fix(taxes): skip zero-amount fees in the Anrok tax payload#6289annvelents wants to merge 1 commit into
annvelents wants to merge 1 commit into
Conversation
annvelents
force-pushed
the
fix/anrok-skip-zero-amount-fees
branch
from
September 4, 2026 14:34
5b5f5c6 to
3b977b8
Compare
Contributor
|
Automated pre-review (advisory, not a required check) — verdict: HOLD · CI green HOLD: |
## Context Anrok and Avalara reject tax payloads above 1200 line items, so an invoice carrying many zero-amount charge fees fails tax computation outright. A fee with no amount incurs no tax, yet still counts toward that limit. PR #5609 fixed this for current usage only, in Invoices::CustomerUsageService. Six other call sites still sent every fee: invoice finalization and draft refresh through PullTaxesAndApplyService, the invoice preview, the tax-report job, standalone pay-in-advance fees, and the one-off invoice tax preview. ## Description The filter now lives in Integrations::Aggregator::Taxes::Invoices:: BaseService, the constructor every invoice tax call already passes through, so one place covers all callers and both providers. It reuses the Fee#taxable? predicate introduced by #5609; the DraftFee stand-ins built by the FetchDraftInvoiceTaxes mutation gain the same predicate, read off the sub-total they carry, since they expose no amount. When no fee is taxable the request would carry an empty line-item array, which both providers reject, so CreateService and CreateDraftService skip the provider and report an empty fee-tax list. Empty rather than nil matters: every consumer keeps taking its provider branch and arrives at zero taxes on its own, without a guard per call site. VoidService and NegateService are untouched, as their payloads carry only the invoice id and must still reach the provider for an invoice reported before this change. Fees::ApplyProviderTaxesService returns early when a fee has no entry in the response. Five callers iterate every invoice fee and look the response up by item_id/item_key, so an unreported fee would otherwise raise NoMethodError inside the Sidekiq job. Invoice tax totals are unchanged: an excluded fee has a zero taxable base, so it contributed nothing to the invoice's tax amount or rate. Side effect on rates: a zero-amount fee no longer gets a Fee::AppliedTax row carrying the real jurisdiction rate, so its rate reads as 0 on the PDF, in the ERP sync and in the data pipeline. An invoice whose fees are all zero now gets no Invoice::AppliedTax row either, and its taxes_rate reads 0 rather than the jurisdiction rate applied to a zero base. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
annvelents
force-pushed
the
fix/anrok-skip-zero-amount-fees
branch
from
September 4, 2026 15:49
3b977b8 to
663ceee
Compare
Contributor
|
Automated pre-review (advisory, not a required check) — verdict: HOLD · CI green HOLD —
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Context
Anrok and Avalara reject tax payloads above 1200 line items, so an invoice carrying many zero-amount charge fees fails tax computation outright. A fee with no amount incurs no tax, yet still counts toward that limit.
#5609 fixed this for current usage only, in
Invoices::CustomerUsageService. Six other call sites still sent every fee: finalization and draft refresh viaPullTaxesAndApplyService,PreviewService,Taxes::Invoices::CreateJob,ApplyProviderTaxesToStandaloneFeesService, and theFetchDraftInvoiceTaxesmutation.Changes
Taxes::Invoices::BaseService— the constructor every invoice tax call already goes through — so one place covers all seven call sites and both providers. It reusesFee#taxable?from fix(tax-providers): Filter out zero amount fees from tax provider calls #5609 rather than adding a second definition of "taxable";DraftFeegains the same predicate off the sub-total it carries, since it exposes no amount by design.CreateServiceandCreateDraftServiceskip the provider entirely when nothing is taxable, reportingresult.fees = []. Empty rather thannilis deliberate: each consumer keeps taking its provider branch and reaches zero taxes on its own, so no call site needs its own guard.VoidService/NegateServiceare untouched — their payloads carry only the invoice id and must still reach the provider for invoices reported before this change.Fees::ApplyProviderTaxesServicereturns early when a fee has no entry in the response, since five callers loop over every invoice fee and match byitem_id/item_key.This also means
pro_rated_taxes_rate's count-based branch can no longer be reached by an all-zero invoice — there are no applicable taxes to prorate — so #5609'ssub_total_excluding_taxes_amount_centspre-set remains the answer for the usage path and nothing needs changing here.Side effect worth reviewing
Amounts are unchanged everywhere; excluded fees had a zero taxable base. Rates read differently in two cases:
Fee::AppliedTaxrow, so its rate shows as0.0%on the PDF,taxrate0 in the Netsuite/Xero sync, and nofees_taxesrow in the data pipeline.Invoice::AppliedTaxrow andtaxes_rate: 0, where it previously carried the jurisdiction rate against a zero base.Tests
Zero-fee exclusion and the all-zero skip on
CreateService(Anrok and Avalara contexts) andCreateDraftService, asserted against the exact request body; the same two cases on the GraphQL mutation; the nil-fee_taxesguard; and inPullTaxesAndApplyService, an end-to-end case where the zero fee is absent from the request and ends untaxed while invoice totals hold, plus an all-zero invoice that finalizes with zero taxes and no provider call.🤖 Generated with Claude Code