Money decides the status — not a dropdown
Every watch's status, everywhere you look, is worked out from three simple facts. Nobody picks a status by hand that could disagree with the money. The invoice is where things actually happen (a payment, a return, a void, a trade); those actions move the ledger; the ledger then sets the status on the watch and the deal. One direction of truth.
1 · Is it reserved?
A watch is being held for a specific buyer — but no money has come in yet.
2 · Has any money been paid?
Add up the payments against the sale. Even one dollar changes everything.
3 · Is it out on memo?
The watch has been loaned out to a known buyer for consideration.
Two rules we never break
Inventory status, Deal status, and Invoice status are three views of the same sale. They are recalculated together, in a single step, every time money changes. It is impossible for the watch to read "Sold" while its deal still says "Reserved."
Reserving a watch or sending it on memo requires a buyer to be attached — no anonymous holds. The same contact then shows on the inventory card, the deal card, and the invoice. In Stock is the only status with no contact.
The same sale, shown three ways
There is one set of money records (the ledger). The Inventory page, the Deals pipeline, and the Invoice are simply three windows onto it. Change the money once, and all three update at the same time.
payment records · agreed price · reserve & memo intent"]:::ledger L --> I["📦 INVENTORY VIEW
In Stock · Reserved · Sold · On Memo"]:::view L --> D["🤝 DEAL VIEW
Reserved · Partially Paid · Paid"]:::view L --> V["🧾 INVOICE VIEW
Draft · Sent · Partially Paid · Paid in Full · Returned · Void"]:::view classDef ledger fill:#000,stroke:#c9a96e,stroke-width:2px,color:#fff; classDef view fill:#fff,stroke:#c9a96e,stroke-width:1.5px,color:#15130f;
The status words, finalized
📦 Inventory · 4
In Stock Reserved Sold On Memo
🤝 Deal · 3
Reserved Partially Paid Paid
🧾 Invoice · display
Draft Sent Partially Paid Paid in Full Returned Void
Retired words: Inventory Listed / Consigned / Incoming are gone (Consigned becomes an attribute on the item; the rest become In Stock). Deal Inquiry / Negotiating / Deposit Received / Shipped / Closed / Cancelled are gone — deals are now commitment-only.
Every situation, side by side
This is the master spec. Pick the situation on the left, and read across to see exactly what each view shows.
| Situation | 📦 Inventory | 🤝 Deal | 🧾 Invoice |
|---|---|---|---|
| Uncommitted | In Stock | none | — |
| Held, $0 paid | Reserved | Reserved | none — no invoice, no prompt |
| Any payment, less than full | Sold | Partially Paid | Partially Paid |
| Paid in full | Sold | Paid | Paid in Full |
| Out on memo | On Memo | none | Memo invoice (optional) |
| Returned | In Stock (restock) | demoted / closed | Returned |
| Voided (before any payment) | In Stock | removed | Void |
The journey of one watch
A single watch moves between just four inventory states. The arrows show every move that's allowed, and what triggers it.
What each state can do
- In Stock — reserve, send on memo, mark sold, adjust price
- Reserved — take payment (becomes Sold), release, adjust price. No memo.
- Sold — return, refund, or void via the invoice only. No reserve/memo.
- On Memo — convert to a sale, or return to stock. No reserve.
The contact gate
Both Reserve and Send on memo require a buyer to be attached first. If none is chosen, WatchFlow opens a contact picker — there is no "skip" option. That same buyer then appears identically on the inventory card, the deal card, and any invoice.
Real scenarios, step by step
Three common situations, traced through all three views so you can see them stay in sync.
- Watch sits as In Stock — no buyer, no deal, no invoice.
- You reserve it for a buyer. → Inventory Reserved, Deal Reserved, still no invoice.
- Buyer pays a $20k deposit. → Inventory flips to Sold, Deal becomes Partially Paid, an invoice appears as Partially Paid.
- Buyer pays the remaining $80k. → Deal Paid, Invoice Paid in Full. Inventory stays Sold.
- You send the watch on memo to a known buyer (buyer required). → Inventory On Memo, no deal. Optionally create a memo invoice.
- Buyer decides to keep it. You choose "Sell this memo piece." → the memo invoice becomes a sales invoice and the normal payment flow opens.
- Payment is recorded. → Inventory On Memo becomes Sold; a deal is created at Partially Paid or Paid.
- On a $100k invoice, the buyer pays $50k cash. → Deal Partially Paid, Inventory Sold.
- You record a trade-in: the traded watch's name and an agreed value of $50k (required). → a trade payment of $50k is logged, and a visible trade-in line is added to the invoice.
- $50k cash + $50k trade = $100k. → Invoice Paid in Full, Deal Paid.
- Optionally tick "Add to inventory now" to create the traded watch as a new In Stock item — or add it later. Either way the sale is never blocked.
What happens to existing data
This is a relabeling pass only. No payment, invoice, or money record is ever changed or deleted — payments are the truth. Old status words are simply remapped to the new ones, then everything is reconciled against the ledger.
📦 Inventory remap
- Listed → In Stock
- Incoming → In Stock
- Consigned → In Stock + acquisition type "consignment"
🤝 Deal remap
- Deposit Received → Partially Paid
- Shipped / Closed → Paid
- Any stage with a payment → derived from the money
- Inquiry / Negotiating with a watch + $0 → Reserved
- Empty leads (Inquiry/Negotiating, $0, no watch, no payments) → deleted
How it ships — five phases
Each phase is its own commit, tested and verified before the next. Server first, then the screens, then the special flows.
Server truth
Collapse deal stages to 3 and inventory to 4, flip the "any payment = Sold" rule, write the migration and reconcile pass. No UI yet.
Web rendering
Inventory's 4-status UI, the 3-column deals pipeline, and the new invoice display labels — pure presentation against the new server truth.
Memo lifecycle
Create-a-memo-invoice on send, and the "Sell this memo piece" path that converts a memo into a sale.
Trade-in
The capture box (name + value required), the visible trade-in line on the invoice, and add-now / add-later inventory creation.
Verification
Walk every row of the scenario matrix against the new model, fix any drift, and lock the status columns.
Scope of this pass: server + web only. iOS is deliberately deferred until the web model is frozen, because the app reads these exact status words. Reports wiring is a separate follow-up.