Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help


id: reservation.order kind: intent statement: “WHEN a customer submits an order THE reservation service SHALL hold stock for every line item and accept the order, or reject it with nothing held and nothing charged.”

Reservation & Order

A small order pipeline: submitting an order holds stock for every line item or rejects the order outright; accepted orders are charged exactly once, fulfilled, or released by cancellation or expiry. The subject of this spec is the reservation service itself — nothing here constrains or mentions any checking tool.

Constraints

idkindexprtraces_toobserves
all_or_nothinginvariantthe order is accepted only if every line item's requested quantity is available; otherwise no unit is held and nothing is charged[[reservation.order]]
held_or_convertedinvariantevery unit held for an accepted order is either converted to a fulfillment or released; no held unit outlives both[[reservation.order]]
release_is_totalinvariantwhen a hold is released, no unit remains held for that order; releasing an already-released hold changes nothing[[reservation.order]]
charge_iff_fulfilledinvariantthe customer is charged if and only if the order reaches fulfilled[[reservation.order]]
cancel_refunds_exactly_chargedinvariantIF a charged order is cancelled, THEN the refund equals exactly the amount charged — never more, never less[[reservation.order]]
expiry_releases_holdsinvariantan unfulfilled reservation expires after its TTL; expiry releases the hold without charging the customer[[reservation.order]]
stock_exhaustedeffectreservation.order.stock_exhausted(detail)[[reservation.order]]
reject_reason_surfacedinvariantevery rejection reaches the caller with the exhausted line items named[[reservation.order]][[reservation.order.stock_exhausted]]

Model

States

  • submitted
  • reserved
  • charged
  • fulfilled
  • cancelled
  • released
  • reserve_failed (emits: [[reservation.order.stock_exhausted]])

Transitions

idfromtoguard
acceptsubmittedreserved[[reservation.order.all_or_nothing]]
reject_ordersubmittedreserve_failed¬[[reservation.order.all_or_nothing]]
chargereservedchargedpayment authorized ∧ [[reservation.order.charge_iff_fulfilled]]
fulfillchargedfulfilledpayment settled ∧ [[reservation.order.charge_iff_fulfilled]]
cancel_paidchargedcancelledcustomer cancelled ∧ ¬payment settled ∧ [[reservation.order.cancel_refunds_exactly_charged]]
cancel_unpaidreservedcancelledcustomer cancelled ∧ [[reservation.order.held_or_converted]]
expirereservedreleasedreservation TTL elapsed ∧ [[reservation.order.expiry_releases_holds]]

Properties

idkindderives_fromgeneratorpredicate
no_charge_on_rejectionunit[[reservation.order.all_or_nothing]]orders_with_mixed_availability()nothing is charged for any rejected order
holds_all_convertedunit[[reservation.order.held_or_converted]]arbitrary_closed_orders()every held unit is converted or released when the order closes
double_release_noopunit[[reservation.order.release_is_total]]order_released_twice()the second release changes nothing
fulfilled_implies_chargedunit[[reservation.order.charge_iff_fulfilled]]arbitrary_accepted_orders()charged(order) == (outcome(order) == fulfilled)
refund_boundedunit[[reservation.order.cancel_refunds_exactly_charged]]charged_orders_cancelled_before_settlement()refund(order) == amount_charged(order)
expiry_freeunit[[reservation.order.expiry_releases_holds]]orders_past_ttl()nothing is charged and no unit remains held after expiry
rejection_labels_emittedunit[[reservation.order.reject_reason_surfaced]]orders_with_exhausted_items()the rejection message names exactly the exhausted line items
stock_exhausted_emittedunit[[reservation.order.stock_exhausted]]rejections_over_sold_out_items()the rejection carries the stock_exhausted label with the item detail