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).
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):After this, each item's
AllocatedCostalready 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).allocatedAmazonOrderonly overridesGetItems(), soGetTax()andGetSubtotal()still return the original order's values.Splitter.CreateSplitsthen adds proportional tax to each category group's total a second time (splitter.go#L147-L155):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.
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:
With tax at 0,
taxRateis 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 currentmainit 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
allocatedAmazonOrderare older and predate the allocator).