ByteBite Docs
Architecture

Kitchen status

Operator kitchen flow: accepted → preparing → ready → completed.

Kitchen status

The sixth product slice is Kitchen → Status. After accept, the restaurant cooks the pickup order. The operator advances it one step at a time: preparing, then ready, then completed. The guest sees the new status on confirmation. Payment stays cash / unpaid. There is no payment provider.

Checkout still creates the pending order. Accept/reject and the 10-minute timeout are Slice 5: Accept, reject & timeout.

Transitions (ADR-015)

Only these writes exist in this slice:

FromToHow
acceptedpreparingDashboard preparing
preparingreadyDashboard ready
readycompletedDashboard complete

Forward, one step. Skip (accepted → ready, accepted → completed) is 409. Reverse (ready → preparing) is 409. Pending stays Slice 5 only: pending → preparing is 409. Already completed or cancelled → any kitchen write is 409. Double-prepare / double-ready / double-complete is 409.

No cancel after accept. customer_cancelled and kitchen-cancel are out of scope. Existing reject/timeout paths are unchanged.

Columns

No new tables. No new required fields. order_status already includes preparing / ready / completed. eta_minutes stays the accept-time value. cancellation_reason stays null unless Slice 5 cancelled the order. Payment stays unpaid / cash.

Dashboard API

Requires a staff session. Restaurant context is the path, not the storefront hostname (ADR-021). Query/body restaurantId is ignored.

MethodPathBody
POST/dashboard/restaurants/:restaurantId/orders/:orderId/preparingempty or ignored optional restaurantId
POST/dashboard/restaurants/:restaurantId/orders/:orderId/readyempty or ignored optional restaurantId
POST/dashboard/restaurants/:restaurantId/orders/:orderId/completeempty or ignored optional restaurantId
GET/dashboard/restaurants/:restaurantId/orders—
GET/dashboard/restaurants/:restaurantId/orders/:orderId—

Each write is one transactional UPDATE … WHERE restaurant_id = :path AND id = :orderId AND order_status = '<expected>'. 0 rows → 409, or 404 when the order does not belong to that restaurant.

GETs return the real status, including kitchen values. List is newest first. Accept/reject and the countdown stay pending-only.

A Luigi orderId under Mario's restaurantId is 404 and is not written.

Storefront

GET /storefront/orders/:orderId returns the same fields. Confirmation shows pending, accepted (with ETA), preparing, ready, completed, or cancelled (rejected vs timeout). The page polls the existing GET until completed or cancelled. A Luigi orderId on Mario's host is 404 / OrderUnavailable.

preparing → ready sends one transactional SMS (“order is ready for pickup”). /preparing and /complete do not send. Skip/illegal 409 and Mario-path 404 do not notify. See Transactional notifications.

Isolation

Seeds still create no orders. Isolation is proven by real checkouts, then accept, then kitchen writes.

  • Luigi checkout → Luigi accept etaMinutes: 30 → preparing → ready → complete → completed. Snapshot prices unchanged. ETA 30 remains. Payment unpaid / cash.
  • Same Luigi orderId under Mario's dashboard path for /preparing (and ready/complete) → 404, status unchanged.
  • preparing on pending or cancelled → 409.
  • ready on accepted (skip) → 409.
  • Second /complete on the same order → 409.
  • Storefront: Luigi sees preparing / ready / completed; Mario host → 404 for that orderId.
  • Body restaurantId does not change the tenant.

Not in this slice

BitePay/Stripe, card_at_door, capture/refund/void, delivery, address, minimum order, delivery fee, customer accounts, variants/extras/allergens, cancel after accept, customer cancel, e-mail, kitchen pushes except Ready SMS, sound/PWA, production deploy. Closed checkout 409: Opening hours. Dashboard session: Staff authentication. Ready SMS: Transactional notifications.

On this page