Bubble tea stored-value card ledger tool (single-file) - opening plus sales minus redemptions minus refunds equals closing, and the day the chain breaks is the day that gets flagged
You are a coding agent building a tool for a bubble
tea shop. Build a single-file HTML tool (HTML/CSS/JS
all inline, no external dependencies, no network
requests, opens by double-click) for the cash office
to reconcile the stored-value and punch-card ledger.
Pinned notice at the top of the UI:
"Stored-value cash is a liability, not revenue -
revenue is recognized at redemption."
Core reconciliation logic:
- Rolling identity: opening balance + sales and
top-ups − redemptions − refunds = closing
balance
- Rolled daily: the balance is verified once per
day, and a broken day is flagged red on that
day - never report month totals only; a month
that totals clean but broke mid-way is still
a broken ledger
- Three sources entered separately: sales
(register and card campaigns), redemptions
(POS, daily), refunds (customer service or
manager approval). Gaps between sources land
in their own "source difference" column,
never absorbed into redemptions
Input section:
- Opening data, two start modes: full per-card
detail / liability total only
- Daily redemption totals (bulk paste: date
plus amount per line)
- Sales and top-up records for the period:
date, channel, amount
- Refund records: date, card or ticket number,
amount, approver
Output section:
- Monthly rolling table: date / opening /
sales / redemptions / refunds / closing /
verdict (green balanced, red broken)
- Broken-day detail: click through to the four
numbers of that day side by side with their
sources
- Per-card lookup (detail mode): enter a card
number, get that card's balance history
- Pending-cards register: cards that will not
reconcile are parked with a reason and a
discovery date, to be digested one by one
- "Export liability movement": plain text,
monthly four numbers - sales / redemptions /
refunds / closing - pasteable straight into
the stored-value line of the month-end close
checklist
Constraints:
- A day with missing data is marked "missing"
and the rolling identity stops at the break,
listing which days are absent - never filled
with the prior day or an average; a ledger
tool that has quietly balanced the books once
can never again catch a real difference
- No network, no accounts; data in browser
localStorage with full export and a clear
button
- The tool generates no "promo suggestions" and
no "card-sales targets" - a reconciliation
tool moonlighting as a sales dashboard does
both jobs badly
Why it is written this way
Rolling daily instead of totaling monthly addresses the signature shape of stored-value failures: all four monthly totals balance and some day in the middle was quietly moved. A monthly redemption total can be correct while individual redemptions landed in the wrong places - advances, borrowed cards, offsets all hide inside a clean month and cannot hide inside a daily chain. Flagging breaks to the day gives a difference time-and-place coordinates; investigations start at breaks, and that is the tool's core value.
The source-difference column stays separate from redemptions because the three systems have natural seams: sales at the register, redemptions in the POS, refunds at customer service - and every shop answers "does a campaign bonus count as a top-up" and "does a refund go back to the original payment or to card balance" differently. Absorb the seam into redemptions and it disappears under a flat surface forever; print it separately and it gets looked at once a year, which is once a year more than never.
The pinned "liability, not revenue" line is not decoration: it forces a conceptual recalibration every single time the tool opens - the bigger the sales column on this sheet, the bigger the liability. That is not performance; it is debt. Interface wording standing guard over an accounting principle outlasts any single training session.
Missing data stops the roll rather than padding it - the shared honesty floor of every reconciliation tool: the entire value of a ledger tool rests on "when it says balanced, it is balanced," and every silent fill spends that trust. A tool that has quietly balanced the books once cannot catch the real difference the second time.
Variables
| Variable | Notes |
|---|---|
| Start mode | Per-card detail on hand, or liability total only - the total-only mode cannot do per-card lookups; export the detail from the card-sales system first, then switch |
| Bonus-money convention | Whether campaign bonuses count as top-ups, and whether they refund on card cancellation - fix one convention per your campaign rules; a floating convention means the source difference never closes |