Approving, rejecting and part-payments
The owner decision that is the only thing able to mark an order paid, from WhatsApp or the dashboard.
This is the one decision the software will not make for you.
The rule
Nothing marks an order paid except you.
Not a confident receipt reading. Not six checks passing. Not an exact amount match with a unique reference into the right account. There is no confidence threshold that unlocks it, and no setting that turns it off.
Two doors
From WhatsApp
When a receipt lands, a card arrives on your phone with the amount, the customer, the order, and what the checks concluded.
| Command | What it does |
|---|---|
PAID FB-1204 | Approves the payment in full. Issues the invoice. |
PARTIAL FB-1204 500 | Records a part-payment of 500. |
REJECT FB-1204 | Rejects the receipt. Moves the order to review. |
EXTEND FB-1204 | Pushes the deadline out. |
CANCEL FB-1204 | Cancels the order and restores the stock. |
From the dashboard
Today holds the approval queue. Tapping a receipt opens it full-size beside the extracted values, the checks that ran, and three buttons: Approve, Reject, Partial.
The two doors call the same code. Neither can do something the other cannot, and neither can skip a guard the other applies.
Approving
Approving does all of this, in this order:
- Marks the payment approved and the order paid.
- Records the amount against the order.
- Reserves an invoice number and writes the invoice — inside the same transaction, so a failure consumes neither.
- After that has safely committed: renders the PDF, stores it, and sends it to the customer.
Step 4 is deliberately outside the transaction. A PDF renderer crashing, or WhatsApp refusing the upload, cannot un-approve a payment you approved.
Part-payments
PARTIAL FB-1204 500 adds exactly 500 to what has been paid against the order.
The order becomes paid only when the running total reaches the full amount —
and the invoice issues at that point, not before.
A part-payment that leaves a balance issues no invoice, because the order is not settled.
Rejecting
Rejecting moves the order to PAYMENT_REVIEW rather than leaving it awaiting
payment. That is not cosmetic: it is what prevents a rejected receipt being
approved later by accident, because approval is only legal from
PAYMENT_PENDING.
Only a fresh receipt from the customer moves the order back to awaiting payment.
The rejected receipt stays in the order's history. That history is the audit trail, and a rejected receipt vanishing would remove exactly the record you would want in a dispute.
Idempotency
If you tap Approve in the dashboard a second after tapping Paid in WhatsApp, the second one reports success rather than an error. It is the same outcome you asked for; treating it as a failure would just make you check whether it worked.
What is written down
Every approval, rejection and part-payment writes an audit record: what happened, to which order, when, and from which door. Those records are only ever created — there is no code path anywhere that updates or deletes one.

