Skip to main content

Cart & Orders — Reference

Lookup tables for the cart lifecycle, statuses, and payment branches. For the concept, read Cart & Checkout — the cart that mirrors the vendor.

Verified against flex-v3-backend code (src/modules/cart/), 2026-06-10.

Cart endpoints (the fan lifecycle)

EndpointDoesVendor interaction
POST /cart/initializecreates the cart + events (pre-hold)none — DB only; exists for abandoned-cart analytics
GET /cart/:cartIdread the cart (cached)none
PATCH /cart/:cartId/eventsadd/remove eventsnone
PATCH /cart/:cartId/bindattach an anonymous cart to a logged-in usernone
POST /cart/:cartId/managehold seats / suites / add-onsvendor holds (see retry ladder below)
POST /cart/:cartId/auto-assignasync seat-matching across events (202 + poll GET …/auto-assign/:jobId)delegates to manage
POST /cart/:cartId/validatepre-checkout check: holds alive, prices matchHost: expiry check · Archtics: shopping_cart verify
POST /cart/:cartId/checkoutpayment + vendor commit + order insertsee payment branches
DELETE /cart/:cartId[/events/:id|/items/:id]cancel all / one event / one itemreleases vendor holds

The hold retry ladder (4 attempts in manage)

  1. Exact seats requested.
  2. Best-available — same section + price code.
  3. Best-available — same price code, any section.
  4. Best-available — ticket types only.

Hold expiry: TM Host = vendor-provided hold_time · TM Archtics = fixed constant (ARCHTICS_DEFAULT_HOLD_SECONDS). If persisting a hold fails, the vendor hold is released immediately.

Statuses

Cart (tbl_carts.cartStatus)Meaning
activeinitialized, fan shopping
processingatomic lock during checkout (race guard, always reset)
paidorder created successfully
failed / cancelled / expiredself-explanatory
Order (tbl_orders.orderStatus)Meaning
completedall items purchased
refunded / partially_refundedset by the refund flow, not checkout

The order row is inserted only after payment succeeds; then the cart flips to paid.

Operational notes: tbl_ticket_sales is written at checkout and read by GET /transaction/orders to serve order/ticket history. There is no hold-cancelling cron — Archtics cancels holds by seat block, not cart ID, so a cleanup job could release another fan's seats; the vendor's ~30-min hold expiry + the ~20-min full inventory rebuild self-heal instead. (A separate daily job snapshots abandoned carts into tbl_abandoned_carts for analytics.) Response caching is disabled in production (TTL = 0); the cache layer exists for high-traffic events. TM Host is not in production yet (no final key).

Cart & order table schema (row level)

The cart is a 3-level hierarchy that mirrors the vendor: tbl_cartstbl_cart_eventstbl_cart_itemstbl_cart_seats. Orders carry extra key/value fields in tbl_order_additional_details.

tbl_cart_events — events the cart spans

Created at /cart/initialize and /cart/:id/events (DB-only, no vendor call yet).

ColumnNotes
cartEventIdPK
cartIdFK to tbl_carts
eventCodethe event this row covers
cartEventStatuspending · assigned · failed · removed

tbl_cart_items — one line per held suite / seat-block / add-on

The heart of "the cart mirrors the vendor" — each item tracks its own vendor hold + state.

ColumnNotes
cartItemIdPK
cartId / cartEventIdparents (which cart, which event)
itemTypewhat this line is (seat block / suite / add-on)
addonOptionIdset when the item is an add-on (FK to the chosen add-on option)
eventCodeevent the item belongs to
cartItemStatusper-item lifecycle (held / committed / released / failed …)
seatCountseats represented by this item
subtotal / serviceFee / totalAmountmoney for this line
holdExpiresAtwhen the vendor hold lapses
retryCountattempts used by the hold retry ladder
saleTypesale path (e.g. seat-level vs suite)
checkoutPhasewhere this item is in the checkout state machine
vendorCartId · vendorEtag · vendorInvoiceReference · vendorShippingId · vendorOrderNumber · vendorOrderToken · vendorRedemptionUrl · vendorAppUrlvendor handles returned during hold/commit
vendorRawResponsefull raw vendor payload (debugging / audit)

tbl_cart_seats — per-seat detail under an item

ColumnNotes
cartSeatIdPK
cartItemIdFK to the parent item
sectionName / rowName / firstSeat / lastSeat / seatCountthe seat block
suiteIdset for suite inventory
priceCode / ticketTypeCodethe price combination that resolved
inventoryTypeseat-level vs suite-level
basePrice / serviceFee / allInPrice / totalPriceper-seat money breakdown
vendorOrderLineItem / vendorOfferId / vendorSeatIdsvendor references for the held seats

tbl_order_additional_details — extra fields on a completed order

ColumnNotes
detailIdPK
orderIdFK to tbl_orders
fieldKeymachine key
displayLabelhuman label shown on the order
valuethe value

Payment branches at checkout

VendorMechanism
TM HostStripe PaymentIntent (idempotency-keyed), manual capture after all vendor commits — capture failure queues refunds
TM Archticsnative payment_request with a MOP (method-of-payment) array — no Stripe
Payment plan (Archtics)charge installment 1 only; rows 2..N inserted pending in tbl_payment_plan_installments, charged against a TM invoice by a recurring job; card is force-saved. ⚠️ Not live yet — charging code still in testing
Account credit⚠️ designed (credit first, card remainder) but not yet implemented in code — upcoming "bank of credit" work

Partial multi-event commit failure (Host): already-committed events are queued in tbl_checkout_refunds and refunded by cron (~30 min).

Saved cards (tbl_user_card_details)

  • Vendor tokens only, never raw card data: Stripe pm_… (Host) · cc_seq_num via cc_update (Archtics).
  • Scoped per user per team schema — the same fan on two teams has two separate card rows.
  • Archtics card lists are cross-checked against the live vendor (cc_query); stale cards are filtered out.