A payments desk for a platform: what came in, what is waiting to go out, what we spent on our own cards, and how much of the balance is actually ours to move today. Looking at it should settle whether a number on screen can be checked.
Preview interactive design
One person in treasury operations, on a rolling 30-day window rather than a calendar month — a monthly limit reads empty on the first and makes every card meter lie about the same data on different days.
01The screens →Money arrives as card, ACH, wire or wallet, and how it arrived is what it costs. Net volume is settled payments less refunds, and a charge with no outcome yet sits outside both.
a pending charge is not a failure02ReleasePayouts leave the balance, so nothing leaves without an approval. A payout held by another team keeps its row, its badge, its clock and its reason, and loses only its button.
never disabled to avoid deciding03ReviewWhether a receipt is required is policy rather than a fact about the expense. The rule lives in one object the settings screen edits, and saving that form recounts the sidebar.
the threshold is passed in, never inlinedThirty registered routes, eleven of them top-level. Two destinations deliberately have no record screen — a payment and a payout are only ever read on the list that holds them, so a notification about one lands on that list rather than on a route with nothing behind it.
02The status set →The dashboard promises an approvable figure; this screen owes an answer for it. Three payouts are waiting on us and one can be released: another team holds the second for a dispute running on a different screen, and the third is above the operator’s own approval limit. The queue hides neither and offers neither.

Our own money going out. Three expenses can be approved now; two more are waiting on a receipt and are recessed with the name of the person who owes it. Approve exists on those rows and is disabled with its reason, because the precondition is visible — not omitted, and not a sentence beside a live button.

A meter rather than a row, because the question is how much of the limit is left. One card is past its limit and another is near it — and “near” is the policy’s 80% share rather than a number inside the component. The card’s whole ledger sits under the chart, so the meter is checkable against the rows that filled it.

Three open disputes hold $9,650.10 out of the balance. Two need evidence from us and one is under review, where the clock belongs to the network — so that record is offered no action at all, and the screen says who is being waited on instead.

The three-part answer, and the end of the argument the other four screens started. Available is the only stored money figure in the product; committed is the payouts that have not landed and reserved is the open disputes, and both are summed from the two tables printed directly below them.

The value everybody looks for in the payout enum is blocked, and it is not there: a held payout is awaiting_approval with a blocking record attached, and the block is computed at render. Late is absent for the same reason, from this field and from payments.
03The awkward cases →All three are entries in the fixture rather than hypotheticals, and each one is why a rule in the product exists.
04The audit →There is no audit view and there should not be one — the audit is a design-time discipline. It found this: every payout row and the team screen printed an approval limit per person, and no payout predicate read either one. Approvability asked only whether the payout was held, so one at $61,480.00 counted as approvable for everybody.
05Back to the top →
Reckon
Available plus committed plus reserved is arithmetic any product can borrow. Which team is being waited on, and what the screen says instead of a button, is the part you have to decide.