generation partial refund reconciliation: Calculate historical differences without promising a new API
A generation partial refund reconciliation compares the total amount that should have been returned with the matching refunds already recorded for one job. It is an accounting investigation, not an invitation to call an undocumented public partial-refund endpoint. The current job service normally settles failure or cancellation to zero consumption.
Define the target carefully
Start with one job and a justified target refund. Confirm the held credits and the event supporting that target. Distinguish a failed submission, a canceled job, and a successful job that a reviewer dislikes. Those situations do not have the same service-level refund behavior.
The refund helper accepts a target credit amount and checks positive REFUND transactions whose descriptions match the job with failed, canceled, or partial reasons. It totals matching historical amounts. If that total already reaches the requested target, it returns without adding another refund.
Otherwise, the intended new credit is the target minus the historical total. This is a difference against a total target, not an instruction to add the target again every time the operation is repeated.
Work through a fictional legacy case
Imagine an old job whose justified refund target is thirty credits. Its matching historical refund entries total twelve. The remaining difference is eighteen. This arithmetic is an illustrative fixture and says nothing about an actual account.
The helper attempts to insert that difference using its deterministic per-job refund identifier. If that identifier already exists, it checks whether the stored transaction belongs to the same user, has the expected amount, and is a REFUND. A mismatch is a conflict, not permission to append arbitrary correction rows.
This matters when a deterministic refund already exists and someone later changes the intended target. The implementation is not a general incremental refund API supporting every sequence of increasing targets. Inspect the existing entry and the full evidence before proposing a correction.
Avoid false equivalence
A description containing a job-like string is not enough by itself. The query also scopes the user, transaction type, positive amount, and recognized reason descriptions. A diagnostic report should use the same matching boundaries rather than a loose text search that accidentally includes unrelated transactions.
Keep the held amount, target amount, historical matched total, deterministic entry, and computed difference in separate columns. If the difference is negative, treat the case as potentially over-refunded and investigate; do not produce a negative refund call.
Acceptance and operations
Review fixtures for no prior refund, a legacy partial amount, a full historical refund, an existing matching deterministic entry, and a conflicting entry. The report should explain which cases need no action and which require authorized accounting review.
Do not automatically rewrite balances or promise that all historical jobs will be swept and refunded. Continue with refund receipts, ledger reconciliation, and reservation lifecycle when assembling the evidence for an individual case.
Continue with costs and billing
Where these facts come from
- codebase: src/ai/api/credits.ts
- codebase: src/credits/credits.ts
- codebase: src/ai/jobs/service.ts
- codebase: src/ai/jobs/db.ts
- Editorial keyword hypothesis; search volume not measured