Each bug fix entry should include:
- Date discovered
- Bug description
- Test case that reproduces the bug
- Fix applied
- Commit reference
Description:
itemize amazon -dry-run emitted WARN: Charge validation failed ... bank charges ($68.86) exceed expected ($61.87) by $6.99 and skipped the order. The $6.99 was a non-bank transaction entry (promotional credit / reward earned) that appears in Amazon's transaction list with no card digits but does NOT actually reduce the card charge. The validator subtracted it from the order total to compute expectedSum, making the real bank charge look like an overcharge.
Test Case:
// validator/charges_test.go: TestValidateCharges_BankMatchesOrderTotalWithNonBankEntry
// bankCharges=[68.86], orderTotal=68.86, nonBankAmount=6.99
// Expected: valid (bank charge equals full order total)
// Actual before fix: invalid ("bank charges exceed expected by $6.99")Root Cause:
ValidateCharges only checked bankSum ≈ orderTotal - nonBankAmount. When a non-bank entry doesn't reduce the card charge (e.g. rewards earned, promotional accounting), the formula underestimates what the bank should receive.
Fix Applied:
Added a secondary check in ValidateCharges: if bankSum ≈ orderTotal (within 2¢ tolerance), the validation passes regardless of the non-bank amount. The bank charged the full order total, which is a valid scenario.
Verification:
TestValidateCharges_BankMatchesOrderTotalWithNonBankEntrynow passes.- All existing validator tests continue to pass.
Description:
itemize amazon -dry-run emitted ERROR: Handler error order_id=112-4444156-8489869 error=failed to get bank charges: no bank charges found (order paid entirely with gift cards/points). Orders paid entirely with gift cards/points have no bank transaction in Monarch to match, so they should be silently skipped — not crash the handler.
Test Case:
// handlers/amazon_test.go: TestAmazonHandler_ProcessOrder_FullyGiftCardOrder
// GetFinalCharges() returns ErrGiftCardOrder
// Expected: result.Skipped=true, no error returned
// Actual before fix: returned a fatal error, logged as ERRORRoot Cause:
GetFinalCharges() returned a plain fmt.Errorf(...) for this case instead of a sentinel error. The handler only checked errors.Is(err, ErrPaymentPending) and treated everything else as a fatal error.
Fix Applied:
Introduced ErrGiftCardOrder sentinel in amazon/order.go and updated GetFinalCharges() to return it. The handler now checks errors.Is(err, ErrGiftCardOrder) and skips the order with reason "paid entirely with gift cards/points".
Verification:
TestAmazonHandler_ProcessOrder_FullyGiftCardOrdernow passes.TestOrder_GetFinalCharges_OnlyGiftCardupdated to useerrors.Is(err, ErrGiftCardOrder).- All existing tests continue to pass.
Description:
Some Costco receipt line items reference their parent via description (e.g. /AAA BATTERY) rather than item number (e.g. /1234567). The discount lookup only checked the item-number map, so these discounts were logged as "orphaned" and silently dropped, leaving the item price too high.
Test Case:
// provider_test.go: "discount references parent by description instead of item number"
// Discount item has ItemDescription01 = "/AAA BATTERY"; parent has ItemNumber "379938"
// Expected: discount of -$2.50 applied → price $12.49
// Actual before fix: price remained $14.99, WARN loggedRoot Cause:
convertReceipt built a single itemMap keyed by ItemNumber. GetParentItemNumber() strips the leading /, returning "AAA BATTERY" — a string that never matches a numeric key.
Fix Applied:
Added a parallel descMap keyed by uppercased ItemDescription01. When the item-number lookup misses, fall back to the description map before declaring the discount orphaned.
Verification:
- New test
discount references parent by description instead of item numberpasses. - All existing discount-netting tests continue to pass.
go test ./... -racegreen.
The project was developed using strict TDD methodology from the start, preventing bugs through test-first development.
Description: Brief description of the bug and its impact.
Test Case:
func TestBugScenario(t *testing.T) {
// Test that reproduces the bug
}Root Cause: Explanation of why the bug occurred.
Fix Applied:
// Code changes that fixed the bugVerification:
- Test now passes
- No regression in other tests
- Manual testing confirmed
Commit: commit-hash
- Always write tests first (TDD)
- Test edge cases and error conditions
- Use static analysis tools
- Code reviews before merging
- Integration testing for complex flows
- Monitor production for unexpected errors
- Missing validation
- Incorrect validation rules
- Type conversion errors
- Race conditions
- Deadlocks
- Incorrect mutex usage
- Unhandled errors
- Incorrect error types
- Missing error context
- API contract mismatches
- Timeout issues
- Retry logic failures
- Memory leaks
- Inefficient queries
- N+1 problems