fix(refunds): stopgap — only auto-reverse commissions on a full refund - #67
Open
keithfawcett wants to merge 2 commits into
Open
fix(refunds): stopgap — only auto-reverse commissions on a full refund#67keithfawcett wants to merge 2 commits into
keithfawcett wants to merge 2 commits into
Conversation
charge.refunded reversed 100% of an invoice's accrued/approved commissions on ANY refund, and charge.amount_refunded is cumulative — so a $1 refund on a $100 order wiped the entire commission, and successive partials mis-stated the reversal. Codex-recommended safe stopgap: only auto-reverse when the refund is full (amount_refunded >= amount). Partial refunds are still recorded as a corrective 'refund' event and flagged with partialRefundReversalSkipped for manual handling. This is a stopgap, not the end state: proportional clawback (incremental refund deltas + immutable CommissionAdjustment rows) is the real fix and a separate ledger change. The stopgap strictly prevents the current partner-harming over-clawback. Tests: existing full-refund cases now carry charge.amount (so they remain full and still reverse); new case asserts a partial refund leaves commissions accrued and sets the skip flag. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The stopgap compared amount_refunded to charge.amount (the INTENDED amount), but Stripe's amount_captured is what was actually collected and can be smaller after a partial capture. A $100 auth captured for $60 then fully refunded ($60) has amount_refunded=6000 < amount=10000, so it was wrongly classified partial → commissions left payable on a fully-refunded sale. Base the full-refund test on amount_captured (fallback to amount when absent). Test: a partially-captured ($60 of $100) charge, fully refunded, now reverses commissions (fullRefund=true). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.
Problem
charge.refundedinvoked invoice-wide commission reversal on any refund: every accrued/approved commission for the invoice flipped toreversed. Combined withcharge.amount_refundedbeing cumulative, a $1 refund on a $100 order wiped 100% of the partner's commission, and successive partial refunds mis-stated the amounts. (Audit item #9, Codex-confirmed.)Fix (stopgap)
Only auto-reverse when the refund is full (
amount_refunded >= amount). A partial refund is still recorded as a correctiverefundevent (for the audit trail) and flagged withpartialRefundReversalSkipped: trueso ops can handle it manually.fullRefundandchargeAmountare added to the event metadata.This is deliberately a stopgap, not the end state — it strictly removes the partner-harming over-clawback. The real fix is proportional clawback (incremental refund deltas + immutable
CommissionAdjustmentrows), which is a separate ledger change worth its own design.Tests
The two existing full-refund tests now carry
charge.amount(so they stay full refunds and still reverse — proving the full path is unchanged). A new test drives a $1 refund on a $100 charge and asserts commissions stayaccrued,reversedCommissions: 0, andpartialRefundReversalSkipped: true. Typecheck clean.🤖 Generated with Claude Code