Skip to content

docs: add PRD for guest order history feature - #492

Merged
mnindrazaka merged 3 commits into
feat/order-historyfrom
claude/friendly-hamilton-k1migv
Sep 16, 2026
Merged

mnindrazaka merged 3 commits into
feat/order-historyfrom
claude/friendly-hamilton-k1migv

Conversation

@mnindrazaka

Copy link
Copy Markdown
Collaborator

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 /orders route with a list view and moves individual order pages from /t/{code}/status?ref=X to /orders/{reference}.

Key Changes

  • Problem statement: Documents how the current single-order model is fragile (order reachable only via query parameter, one-slot resume pointer, prohibition on re-ordering)
  • Proposed solution: Eight-phase implementation plan:
    • Phase 1: API endpoint GET /payments with PaymentSummary schema
    • Phase 2: Orders move to /orders/{reference} with redirect from old URL
    • Phases 3–7: Frontend implementation (use case, screen, header button, badge, cleanup)
    • Phase 8: Documentation and e2e tests
  • Design decisions: 13 numbered decisions covering naming (payments API resource vs. orders UI), summary vs. full payment fetching, table-free URLs, expired order filtering, and removal of device-local state
  • Risks and mitigations: Addresses storage loss, URL changes, guard removal, and field drift
  • Success criteria: Six measurable outcomes including multi-order checkout, no dialogs, cross-table history, and code deletion

Implementation Details

  • Reuses existing OrderStatusScreen as the detail view (no new detail screen)
  • Server-rendered badge count on header button (no polling)
  • Expired and failed payments excluded from history (D5)
  • Session-scoped list survives cleared storage as long as session cookie lives
  • Phases 1 and 2 can land in parallel; each phase leaves the product shippable

https://claude.ai/code/session_01JEKHz2dPugLQwGagXYiiTe

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
@vercel

vercel Bot commented Sep 15, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
gatherloop-order Ready Ready Preview Sep 16, 2026 12:21am UTC
gatherloop-pos Ready Ready Preview Sep 16, 2026 12:21am UTC
gatherloop-ui-storybook Ready Ready Preview Sep 16, 2026 12:21am UTC

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
mnindrazaka changed the base branch from main to feat/order-history September 16, 2026 00:31
@mnindrazaka
mnindrazaka merged commit 7cad292 into feat/order-history Sep 16, 2026
7 checks passed
@mnindrazaka
mnindrazaka deleted the claude/friendly-hamilton-k1migv branch September 16, 2026 00:31
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants