A customer is told what happened, and never what might - #793
Merged
sridharkalaibala merged 2 commits intoSep 16, 2026
Merged
Conversation
Stage 5 of the print roadmap - "the customer knows". The thank-you page asked the shop one question, once, as it opened: is this paid yet. Everything that happened to the order after that - a person accepting it, a ticket coming out of a kitchen printer, the shop refusing it at 2am - happened behind the customer's back, and the only way to find out was to walk to the counter and ask. The stage's own warning is what shaped this: "Do not ship a stage nothing can move off. If Ready is unreachable because nobody presses anything, a frozen tracker is worse than none." Three of the four rungs everyone has seen on a delivery app are unreachable here. Nothing marks an order ready. Nothing says a cook started; we know a ticket PRINTED. And a shop on automatic never decides anything, so "Accepted" would describe a decision nobody made. So there is no ladder. There is a TRAIL: what has already happened, each with the moment it happened, newest last. A trail cannot freeze, because it never claims anything about what comes next - a shop whose kitchen printer is off simply has a shorter trail, not a stuck one. Placed, from created_date. Accepted, only where order_state_by names the person who worked the queue. In the kitchen, only where a till reported that a printer produced paper. Refused and cancelled as endings, drawn after the history rather than in place of it: a customer who cancelled two minutes late needs to know the kitchen had already started. The one thing named before it happens is a held order's acceptance, because order-approval.js allows pending to move nowhere else. It carries the shop's own recent answering speed, median over a fortnight, worded as a description of the past. No cooking time: nothing in the product knows when food is finished, and an invented ETA is the number a customer waits against and then comes to the counter about. Keys and times on the wire, words on the page, because /order carries its own Tamil dictionary keyed by the English sentence and a sentence built on the server arrives as English nothing can translate. The history page is fixed by the same shape: it called every accepted order "With the kitchen", including ones whose ticket never printed. The page polls with backoff and asks NOTHING while the phone is in a pocket, resuming the moment somebody looks.
The thank-you page resolved the shop through knownBranchId() and the order through rememberedOrders(). Both live in indexedDB.js. This page does not load indexedDB.js and never has. Both calls were written behind `typeof ... === "function"` guards, so nothing threw and nothing showed: the shop id came out empty, the function returned before its first request, and everything behind it - the bill when the shop marks the order paid, the offer to pay by UPI - has silently done nothing on that page since the day it was written. A guard that turns a missing dependency into a quiet nothing is how a shipped feature runs for months without ever running once, and the trail would have joined it. Loading indexedDB.js here is not the fix: it starts a timer that refetches the shop's whole menu every ten seconds, behind a page whose only job is to show a token. So the page answers from what it already holds. The order comes from ?order= on the way in from the history page, or from the sale id on the receipt this phone was handed at checkout. The shop comes from posnic_store, which indexedDB.js writes on every menu load. The two spellings of that key are pinned together, because a rename on one side would put this page straight back where it was.
sridharkalaibala
force-pushed
the
feat/a-customer-can-see-their-own-order
branch
from
September 16, 2026 04:43
8a51275 to
c6b2450
Compare
Contributor
|
Merged to Try it at https://develop.posnic.io, or run it yourself: git fetch origin develop && git checkout develop
npm install && npm --prefix api install
npm run dev # then http://localhost:3000When you have tested it, say what you did and what happened, and set Reporting that something is broken is as useful as fixing it. It is |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stage 5 of the print roadmap - "the customer knows".
The thank-you page asked the shop one question, once, as it opened: is this
paid yet. Everything that happened to the order afterwards - a person
accepting it, a ticket coming out of a kitchen printer, the shop refusing it
at 2am - happened behind the customer's back, and the only way to find out was
to walk to the counter and ask.
No ladder
The stage carries its own warning: "Do not ship a stage nothing can move off.
If
Readyis unreachable because nobody presses anything, a frozen tracker isworse than none."
Three of the four rungs everyone has seen on a delivery app are unreachable
here:
So there is no ladder. There is a trail: what has already happened, each
with the moment it happened, newest last. A trail cannot freeze, because it
never claims anything about what comes next - a shop whose kitchen printer is
off simply has a shorter trail, not a stuck one.
created_dateorder_state_bynames the person who worked the queuein place of it: a customer who cancelled two minutes late needs to know the
kitchen had already started
The one thing named before it happens is a held order's acceptance, because
order-approval.jsallows pending to move nowhere else. It carries the shop'sown recent answering speed - median over a fortnight, cached, bounded by an
_idrange so it is an index walk rather than an in-memory sort - worded as adescription of the past. No cooking time: nothing here knows when food is
finished, and an invented ETA is the number a customer waits against and then
comes to the counter about.
Keys and times on the wire, words on the page, because
/ordercarries its ownTamil dictionary keyed by the English sentence and a sentence built on the
server arrives as English nothing can translate.
Two bugs found on the way
The history page was making the claim this stage exists to stop. It called
every accepted order "With the kitchen", including ones whose ticket never
printed. Both customer screens are now drawn from the same trail, so they
cannot disagree.
The thank-you page could not reach the shop at all. It resolved the shop
through
knownBranchId()and the order throughrememberedOrders(), both ofwhich live in
indexedDB.js- which that page does not load and never has.Both calls sat behind
typeof ... === "function"guards, so nothing threw andnothing showed: the bill-when-paid button and the pay-by-UPI offer have
silently done nothing there since the day they were written. Loading
indexedDB.jsis not the fix; it starts a timer that refetches the whole menuevery ten seconds. The page now answers from the
?order=it arrives with orthe sale id on its own receipt, and from
posnic_store, whose two spellingsare pinned together by a test.
Cost
The page polls with backoff and asks nothing while the phone is in a
pocket, resuming the moment somebody looks. It stops for good at a settled
state or a payment, and after half an hour regardless. The shop's answering
speed is read only while an order is actually being waited on, once per page
of history rather than once per row, and cached for five minutes per branch.
Checks
api: 372 suites, 10,797 teststests/online-ordering-ux.test.js: 136npm run check: 7/7The new history-page test was run against the old code first and fails there,
naming every accepted order "With the kitchen".
Not in this PR
ready_byfrom #790 is drawn on the history page but not on the thank-youpage, because its helper lives in
indexedDB.jstoo. Now that the fetch works,that is a small follow-up - worth doing as a shared file rather than a second
copy.