Reverse a payment recorded in error

Back out a payment that was never really received — it stays listed, struck through, and the invoice balance and status are recalculated from what remains.

What it is

A reversal marks the payment row reversed with a reason and a name, excludes it from paid_amount, and re-derives the invoice's balance and status from the surviving rows. The row is never deleted — a deletion would make money silently vanish from a reconciled month.

Also called: entered the cheque twice · wrong payment amount · cheque bounced · undo a payment · payment on wrong invoice

See it
Void this invoice
Void this invoice

INV-2026-0041 — CO-3 Overhead Doors · $9,482.35

It keeps its number and stays on the record, struck through, and stops counting toward your revenue. Use this when the invoice was genuine but the work or the charge is cancelled.

Reason *
Cancelled — job did not proceedReplaced by a corrected invoiceBilled the wrong amountBilled to the wrong customer
Replaced by a corrected invoice — door count went from 2 to 3 after the site visit.
Saved with your name and the date. Only your team sees it — never the customer.
CancelVoid invoice
The payments list inside an invoice with one row struck through, labelled with its reversal reason, and the recalculated balance above. src/components/invoices/InvoiceViewer.tsx. The real screen, drawn from the product’s own design system. Sample data — no customer information appears here.
How it works
  1. 1The route checks the payment belongs to the caller's org before touching it, and refuses a second reversal.
  2. 2reversed_at, reversal_reason and reversed_by are stamped on the payment row.
  3. 3recomputeInvoiceTotals sums only non-reversed payments, writes paid_amount and balance, and lets the status fall.
  4. 4The open viewer re-reads both the invoice and the payment list rather than patching its local copy.
Why we built it

A single cheque was recorded twice against one invoice, eight seconds apart, leaving $20,410.12 paid on a $10,205.06 bill while the balance on screen still read zero. Voiding the invoice would not have touched the payment. A payment can now be reversed with a reason, and the invoice's paid total is rebuilt from the payments that still count rather than by subtracting the reversal — subtraction is correct exactly once, and the row that started all this held a figure no correct arithmetic ever produced.

The problem
  • Double-entered payments leaving an invoice permanently overpaid.
  • A bounced cheque leaving an invoice marked paid.
  • Stored totals that no arithmetic can reproduce.
Sound familiar?
What you get
The invoice's paid figure always equals the sum of its live payments.
The reversed payment stays visible as evidence rather than disappearing.
Status falls back to 'sent', not 'draft' — the invoice was really issued.

See it on your own jobs

Twenty minutes, your numbers, no slide deck. We’ll build one of your real buildings in front of you and send you the estimate link at the end — yours to keep either way.

or keep browsing features →