Skip to content

Amazon multi-category splits add tax twice; overage is taken out of the largest split #100

Description

@daslicious

Summary

For Amazon orders whose items land in more than one category, split amounts include sales tax twice. The splitter then pushes the whole overage onto the largest split to make the splits add up. The splits still add up to the charge, but every split except the largest is too high, and the largest is too low. The item prices in each split's notes are correct, so the notes and amounts disagree.

Cause

In AmazonHandler.itemizeTransaction, the charge is first allocated across the items (amazon.go#L356):

allocResult, err := allocator.Allocate(items, allocationTotal)

After this, each item's AllocatedCost already includes its share of tax, fees and discounts, and together they add up to the charge. The allocated order is then passed to the splitter (amazon.go#L370-L377). allocatedAmazonOrder only overrides GetItems(), so GetTax() and GetSubtotal() still return the original order's values.

Splitter.CreateSplits then adds proportional tax to each category group's total a second time (splitter.go#L147-L155):

taxRate = tax / subtotal
...
categoryTax := group.subtotal * taxRate   // group.subtotal is already tax-inclusive
categoryTotal := group.subtotal + categoryTax

The splits now add up to about charge × (1 + taxRate). The "rounding" adjustment (splitter.go#L215) subtracts the whole difference from the largest split, which hides the error.

Example (real order, anonymized)

Subtotal $141.44, tax $10.70, charge $148.84 (the order had a $3.30 discount). Five items: four clothing, one bedding.

Split Allocated item prices (shown in notes) Split amount written to Monarch
Home & Garden (sheet set, list $69.99) $73.65 $79.22 ($73.65 × 1.0757)
Clothing (4 items, list $71.45) $75.19 $69.62 (whatever is left of the charge)

A second order (charge $164.12, four categories) had the same problem: three splits were each about 7.7% too high, and the fourth absorbed the difference.

This hits every multi-category Amazon split, not only orders with a discount: tax always gets added twice. The size of the overage depends on the tax rate and on how big the non-largest splits are.

Suggested fix

Allocated prices are already final, so the splitter shouldn't add tax to them. The smallest change is on the wrapper:

// Allocated item prices already include tax, fees and discounts.
func (a *allocatedAmazonOrder) GetTax() float64 { return 0 }

With tax at 0, taxRate is 0, each split equals the sum of its items' allocated costs, and the largest-split adjustment goes back to only fixing rounding. Another option is to have the splitter skip tax when it's given allocated items.

A regression test (same numbers as above): allocate [32.99, 9.98, 13.49, 69.99, 14.99] to 148.84, put the 4th item in one category and the rest in another, then check that each split equals the sum of its allocated costs ($73.65 / $75.19) and that the splits add up to −148.84. On current main it fails with Home & Garden = 79.22.

I'm running the one-line fix above locally. The regression test passes with it, and the full go test ./... suite passes too.

Other branches: I checked every branch in the repo. None changes this code path (the branches that don't use allocatedAmazonOrder are older and predate the allocator).

Activity

  1. eshaffer321 commented on Oct 3, 2026

    @eshaffer321
    Owner

    Fixed in PR #101 and released as v0.3.3.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions