docs: add PRD for guest order history feature - #492
Merged
Merged
Conversation
Specifies a session-scoped order history page for apps/order-web so a
guest can order again while a previous order is still being prepared.
Covers GET /payments (session-scoped summaries), table-free order URLs
at /orders and /orders/{reference}, a header entry point with a
preparing-count badge, and the removal of the leave-confirmation guard
and the single-slot active-reference pointer that stood in for a history
page. Eight phases, one PR each.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JEKHz2dPugLQwGagXYiiTe
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Records the five open questions' answers. Three confirm the spec as written; two change it. History lists paid orders only (D14, superseding D5's pending clause): the cart is never cleared while a payment is pending and re-checkout returns the same QR, so a pending row duplicates a path the cart already offers. Names the pre-existing bug that answer leans on — items added after a QR is generated are lost on payment — as a follow-up rather than absorbing it. Makes the session last as long as a browser allows (D15, new Phase 3): resolveSession only issues Set-Cookie when minting, so a returning guest's cookie counts down from their first visit and dies at 365 days. The cookie becomes rolling and moves to the 400-day RFC 6265bis cap. Phase table renumbered to nine; no decision number moved. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JEKHz2dPugLQwGagXYiiTe
The first pass claimed a guest could edit the cart while a QRIS payment was awaiting, losing items added after the QR was generated. That is wrong. CartUsecase.ensureCartUnlocked rejects all five mutation paths with 400 "cart is locked by a pending payment" for as long as IsAwaitingPayment holds — specced in prd-order-checkout-qris-doku.md and covered by five cases in cart_handler_test.go. Corrects D14 in place, where the lock now clinches the argument rather than undermining it, and drops the Risks, Out of Scope and Open Question entries that rested on the bug. Adds D16 recording why no QR re-issue is built: with the cart immutable behind an awaiting payment there is no new total to re-issue for, DOKU exposes no void call, and a local void would have to keep applyQrisStatus honouring a late payment anyway. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JEKHz2dPugLQwGagXYiiTe
mnindrazaka
added a commit
that referenced
this pull request
Sep 16, 2026
* docs: add PRD for guest order history feature (#492) * docs: add PRD for guest order history in the order app Specifies a session-scoped order history page for apps/order-web so a guest can order again while a previous order is still being prepared. Covers GET /payments (session-scoped summaries), table-free order URLs at /orders and /orders/{reference}, a header entry point with a preparing-count badge, and the removal of the leave-confirmation guard and the single-slot active-reference pointer that stood in for a history page. Eight phases, one PR each. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JEKHz2dPugLQwGagXYiiTe * docs: settle order-history open questions in review Records the five open questions' answers. Three confirm the spec as written; two change it. History lists paid orders only (D14, superseding D5's pending clause): the cart is never cleared while a payment is pending and re-checkout returns the same QR, so a pending row duplicates a path the cart already offers. Names the pre-existing bug that answer leans on — items added after a QR is generated are lost on payment — as a follow-up rather than absorbing it. Makes the session last as long as a browser allows (D15, new Phase 3): resolveSession only issues Set-Cookie when minting, so a returning guest's cookie counts down from their first visit and dies at 365 days. The cookie becomes rolling and moves to the 400-day RFC 6265bis cap. Phase table renumbered to nine; no decision number moved. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JEKHz2dPugLQwGagXYiiTe * docs: correct order-history PRD — the cart is already locked The first pass claimed a guest could edit the cart while a QRIS payment was awaiting, losing items added after the QR was generated. That is wrong. CartUsecase.ensureCartUnlocked rejects all five mutation paths with 400 "cart is locked by a pending payment" for as long as IsAwaitingPayment holds — specced in prd-order-checkout-qris-doku.md and covered by five cases in cart_handler_test.go. Corrects D14 in place, where the lock now clinches the argument rather than undermining it, and drops the Risks, Out of Scope and Open Question entries that rested on the bug. Adds D16 recording why no QR re-issue is built: with the cart immutable behind an awaiting payment there is no new total to re-issue for, DOKU exposes no void call, and a local void would have to keep applyQrisStatus honouring a late payment anyway. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JEKHz2dPugLQwGagXYiiTe --------- Co-authored-by: Claude <noreply@anthropic.com> * feat(api): add GET /payments order history endpoint (#494) Implements phase 1 of docs/prd-order-history.md: a session-scoped GET /payments returning paid-order summaries (D14), plus createdAt on the existing Payment schema. Adds TransactionRepository.GetTransactionSummariesByIds (one joined/grouped query per D2/D3, not a per-row GetTransactionById preload chain) and PaymentRepository.GetPaymentsBySessionId(Total). Claude-Session: https://claude.ai/code/session_01A15ezMq7NJmTwXYhD2Fbqt Co-authored-by: Claude <noreply@anthropic.com> * feat(order-history): move orders to /orders/{reference} (#495) Phase 2 of docs/prd-order-history.md. Orders now live at their own table-free route so a row from a future history list can link straight to one. t/[code]/status redirects to /orders/{ref}, and OrderStatusScreen takes its header line from the order's own tableLabel instead of the currently scanned table. Claude-Session: https://claude.ai/code/session_013urc978xXLxgGnNzPSMDmr Co-authored-by: Claude <noreply@anthropic.com> * feat(order-history): roll session cookie forward and extend to 400 days (#493) resolveSession now returns Set-Cookie on every request, not only when minting a new session id, so a returning guest's cookie window keeps sliding forward instead of counting down from their first visit. SESSION_ID_COOKIE_MAX_AGE_SECONDS moves from 365 to 400 days, the RFC 6265bis ceiling Chrome and Firefox enforce. Phase 3 of docs/prd-order-history.md. Claude-Session: https://claude.ai/code/session_01GhvZeJSiuzTQ31chUhpW7J Co-authored-by: Claude <noreply@anthropic.com> * feat(order-history): add frontend payment slice for order history (#496) Phase 4 of docs/prd-order-history.md: PaymentSummary entity, toPaymentSummary transformer, fetchPayments on PaymentRepository (both ApiPaymentRepository and MockPaymentRepository), and OrderHistoryUsecase as an idle/loading/loaded/revalidating/error state machine seeded from SSR params, shaped like ticketList.ts. No screen or handler renders it yet (phase 5). Claude-Session: https://claude.ai/code/session_01URgdiYYDoc7JDEkbtEL7s7 Co-authored-by: Claude <noreply@anthropic.com> * feat(order-history): add order history screen and /orders page (#497) Phase 5 of docs/prd-order-history.md: OrderHistoryListItem, OrderHistoryScreen (loading/loaded/empty/error), OrderHistoryHandler wired to the existing OrderHistoryUsecase, the OrderHistory composition root, and the SSR-seeded /orders page. Claude-Session: https://claude.ai/code/session_01Rfg5HMSTLtokBX4Zq5rLFs Co-authored-by: Claude <noreply@anthropic.com> * feat(order-history): add history button to the order brand header (#498) OrderBrandHeader gains an optional onHistoryPress that renders a circular receipt-icon button, accessible as "Pesanan Saya". TableResolveScreen, MenuListScreen, CartScreen, OrderStatusScreen and OrderHistoryScreen thread the prop, and their handlers wire it to router.push('/orders'), per Phase 6 of docs/prd-order-history.md. Claude-Session: https://claude.ai/code/session_011M82Tz9KZ3JfXCM7iBsmKM Co-authored-by: Claude <noreply@anthropic.com> * feat(order-history): add preparing count badge to header button (#499) Menu and cart pages fetch payments alongside their existing SSR data and count paid orders with fulfillmentStatus === 'preparing', shown as a badge on OrderBrandHeader's history button (Phase 7). Claude-Session: https://claude.ai/code/session_01HnUXiPfoRtZ3jvo3zi6aQ2 Co-authored-by: Claude <noreply@anthropic.com> * feat(order-history): delete the leave guard, resume banner and active reference (#500) Phase 8 of docs/prd-order-history.md. The header history button (Phase 6) and preparing-count badge (Phase 7) already replace what these covered, so per D9 they are deleted outright rather than kept behind a flag: - useLeaveConfirmation (+ .native.ts) and OrderLeaveConfirmAlert, along with the four leave props threaded through OrderStatusScreen/Handler. - ResumeOrderBanner and its MenuListScreen prop / MenuListHandler call site. - The active-reference trio (get/set/clearActiveReference) off SessionRepository, CookieSessionRepository and MockSessionRepository, and ACTIVE_REFERENCE_STORAGE_KEY off constants.ts. docs/handlers.md's browser-lifecycle-guards example swaps to utils/queryParam.ts per D10. Claude-Session: https://claude.ai/code/session_01Sd2gNXkVAEbrUAzYdQTxR5 Co-authored-by: Claude <noreply@anthropic.com> * docs(order-history): add docs-site page and e2e coverage (#501) Phase 9 of docs/prd-order-history.md: publish docs-site/sales/order-history.md with its sidebar entry, cross-link it from table-ordering.md and order-checkout.md (and correct the latter's stale leave-guard mentions, already removed in phase 8), and add orderHistory.spec.ts covering two orders checked out back to back with no leave dialog, both showing up in /orders, and the first row opening to its items. Claude-Session: https://claude.ai/code/session_01QV2PmViBS9oUqtgsjr7mAS Co-authored-by: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
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.
Add comprehensive product requirements document for the guest order history feature, which replaces the current single-order model with a session-scoped list of orders.
Summary
This PRD defines a new order history feature that allows guests to view all their orders from a single session, removing the need for the current leave-confirmation guard and single-slot resume pointer. The feature introduces a
/ordersroute with a list view and moves individual order pages from/t/{code}/status?ref=Xto/orders/{reference}.Key Changes
GET /paymentswithPaymentSummaryschema/orders/{reference}with redirect from old URLpaymentsAPI resource vs.ordersUI), summary vs. full payment fetching, table-free URLs, expired order filtering, and removal of device-local stateImplementation Details
OrderStatusScreenas the detail view (no new detail screen)https://claude.ai/code/session_01JEKHz2dPugLQwGagXYiiTe