
Can an AI-written expense script handle duplicates and refunds?
“Add up my spending” leaves an important question unanswered: what counts as spending? Two identical coffee amounts can be two real purchases. A transfer can be money you still own. We made those distinctions explicit, then ran the code.
One repeated row and one confirmed transfer between your own accounts are excluded. Four uncertain rows remain on hold. USD 51 is therefore not a final total for all spending.
Define the question before calculating
Money leaving an account is not necessarily consumption. Moving money into savings changes your balance, but does not tell you what you spent on food or goods. A refund also needs a clear connection to the purchase it reverses.
Our question is: what is the sum of verified purchases and fees in this dataset, minus refunds linked to their original purchases? Transfers are excluded and unresolved records are kept visible. A different question—such as cash movement during a month—would require different rules.
What the AI actually did
An AI coding assistant wrote the classification rules and JavaScript. We executed that program and compared its output with an independently calculated control total. The interactive tool runs the same rules in your browser; it does not call an AI model when you visit.
This is synthetic data, not a real bank statement. We did not test bank connections, receipt recognition or automatic interpretation of transaction descriptions. Transaction types and ownership of transfer accounts are assumed to have been established in the input. This is not a measured comparison of ChatGPT, Gemini and Claude.
Four decisions that change the result
Keep both coffees. P2 and P3 each cost USD 5 but have different IDs. Both remain, contributing USD 10. The repeated P4 row has the same ID, type, amount and description, so only one copy is included. This assumes IDs are unique within one ledger; combining banks can break that assumption.
Exclude the transfer, include the fee. T1 is explicitly identified as a USD 100 transfer between your own accounts. F1 is a USD 1 fee and counts as spending. The code did not infer account ownership from a name. An unclassified bank transfer might be a purchase payment and needs investigation.
Subtract only a supported refund. R1 refunds USD 20 against the USD 50 purchase P4. R2 has no matching original purchase in the dataset, so its USD 3 remains on hold. It might be a valid refund for an earlier month; lack of a match is not proof that it is false.
Do not choose between conflicting amounts. Two P5 rows contain USD 8 and USD 9. Choosing the first or smaller amount would invent certainty. Both rows are held. Four review rows do not necessarily mean four separate real-world transactions.
Check both money and row counts
Purchases: 10 + 5 + 5 + 50 = USD 70.
Fees: +1. Linked refund: −20.
Confirmed net: USD 51.
All 12 source rows are accounted for: six included rows (including the refund), one duplicate, one transfer and four review rows. The held rows are one unknown type, one unmatched refund and two conflicting P5 records. Matching a total alone does not prove that no rows disappeared.
Adding every positive amount without checking its type gives USD 270. This is a deliberately naive arithmetic comparison, not an actual wrong answer produced by an AI. It includes refunds, transfers, duplicates and unresolved records that do not belong in the confirmed net.
Execution checks covered reversed row order (same USD 51), equal amounts with different IDs (both retained), conflicting IDs (both held), refunds exceeding the original purchase (held), and negative or fractional amounts (rejected). These checks do not establish accuracy for every bank, currency, installment or settlement timing.
Apply the method to your own records
1. Define whether you want withdrawals, cash flow or net purchases.
2. Preserve the source and work on a copy. Remove names and account numbers not needed for analysis, while keeping row identifiers.
3. Establish the meaning of each column, amount signs, currency and reporting period.
4. Review the inclusion rules and unresolved rows before accepting a total.
5. Execute the code and reconcile both amounts and row counts.
6. Check next month’s format before reusing the program.
A prepared JSON file is required here. This page does not import a bank CSV or Excel workbook, and it does not automatically convert an arbitrary statement. If an AI converts your data into this format, compare that conversion with the source too.
Where this approach helps—and where it stops
Repeatedly receiving the same well-defined format is a useful setting for reusable code. Once verified, the rules can be run again without sending every row to a language model. We did not measure time savings or cost reductions in this case.
Unexplained withdrawals, mixed accounts or currencies, and refunds crossing reporting periods need additional evidence and rules. The useful output can be a precise review list rather than a confident-looking total. A confirmed subtotal with unresolved refunds is not necessarily a lower bound on final spending.
Run the example and inspect each decision
| Row | ID | Original amount | Net amount | Reason |
|---|
A prompt you can adapt
Treat these records as one USD transaction ledger. Preserve source rows and IDs. Do not infer unknown transaction types. Exclude only exact repeated records with the same ID and main values. Hold all rows when one ID has conflicting values. Exclude confirmed transfers between my own accounts, but include fees. Validate the original purchase and cumulative refund amount before subtracting refunds. Explain inclusion, exclusion or review for every row. Separate confirmed spending from unresolved records. Provide executable code and independently reconcile the total and row counts. If column meanings or signs are unclear, identify the missing evidence first.
Input format
amount is a nonnegative whole number in US dollars (USD). This is a separate synthetic dollar example, not a currency conversion of the Korean example. Amounts use whole dollars to keep the rules simple; fractional amounts are not supported by this demo. A refund’s related field points to the purchase id. Supported types: purchase, fee, refund, transfer (confirmed own-account transfer), and unknown. IDs must be consistent within a single ledger.
[{"id":"P1","type":"purchase","amount":10},
{"id":"R1","type":"refund","amount":2,"related":"P1"}]