Kaizen
Browse modulesCheckoutcheckout/serverClasses

Class: OrderService

Defined in: server/checkout/order-service.ts:173

Extends

  • BaseCheckoutService

Constructors

Constructor

new OrderService(deps: CheckoutFeatureDeps): OrderService;

Defined in: server/checkout/base-checkout-service.ts:43

Parameters

ParameterType
depsCheckoutFeatureDeps

Returns

OrderService

Inherited from

BaseCheckoutService.constructor

Properties

deps

protected readonly deps: CheckoutFeatureDeps;

Defined in: server/checkout/base-checkout-service.ts:43

Inherited from

BaseCheckoutService.deps

Accessors

actorId

Get Signature

get protected actorId(): string | null;

Defined in: server/checkout/base-checkout-service.ts:45

Returns

string | null

Inherited from

BaseCheckoutService.actorId

Methods

cancelOrder()

cancelOrder(orderId: string): Promise<BigIntsAsNumbers<{
  anomalyAt: Date | null;
  applicationFeeTotalCents: bigint | null;
  authorizedTotalCents: bigint;
  authorizeStatus: OrderAuthorizeStatus;
  capturedTotalCents: bigint;
  cartId: string | null;
  chargeStatus: OrderChargeStatus;
  closedAt: Date | null;
  code: string;
  createdAt: Date;
  createdBy: string | null;
  currencyCode: string;
  customerEmail: string | null;
  customerId: string | null;
  customerTotalCents: bigint;
  disputedTotalCents: bigint;
  externalRef: string | null;
  id: string;
  idempotencyKey: string | null;
  metadata: JsonValue;
  notes: string | null;
  operatorId: string | null;
  organizationId: string;
  orgBorneTotalCents: bigint;
  origin: string;
  placedAt: Date | null;
  platformBorneTotalCents: bigint;
  processingFeeTotalCents: bigint | null;
  refundedTotalCents: bigint;
  requestHash: string | null;
  status: OrderStatus;
  statusUpdatedAt: Date;
  statusUpdatedBy: string | null;
  subtotalCents: bigint;
  updatedAt: Date;
  updatedBy: string | null;
}>>;

Defined in: server/checkout/order-service.ts:487

Imperative cancellation of a pending order — the one exception to derive-from-facts (proposal §Derived status: there is no ledger fact for abandonment; §Tender cancellation & abandonment: cancelOrder "also voids any uncaptured auth, emitting a void txn"). There is no canceledBy column; the actor lands in statusUpdatedBy and the order.canceled payload.

The status gate runs FIRST: only pending orders are ever cancelable, so a non-pending order gets OrderNotCancelableError regardless of its tenders.

  • Phase 1 — NO ambient transaction. Every live tender (see isLiveTender) is canceled through PaymentService.cancelTender, each running its own two-phase op (a provider void for an uncaptured auth happens with no lock held — the two-phase discipline is why this phase must sit OUTSIDE any transaction; callers must not wrap cancelOrder in their own ambient transaction). When at least one live tender exists, an ambient-transaction guard throws immediately (before any provider I/O) to prevent row-lock escalation. A pre-flight pass then folds every live tender's ledger and throws TenderNotCancelableError BEFORE voiding any of them if one already carries a success capture (money moved — the order should not be pending; surface loudly rather than swallow). Checking up front keeps the common stale-projection case all-or-nothing: no tender is voided at the provider only to have a later uncancelable tender abort the loop.
  • Phase 2 — one transaction. Lock the order; re-verify the status is still pending (a regression in the phase-1 window — e.g. a late capture paying the order off mid-cancel — throws OrderNotCancelableError with the regressed status); assert no NEW live tender appeared (operators racing tender creation against cancellation is a consumer wiring bug, not a domain condition — plain Error naming the tender); then the canceled write + order.canceled event (writeCanceled, shared with the tenderless path, which skips straight here).

Parameters

ParameterType
orderIdstring

Returns

Promise<BigIntsAsNumbers<{ anomalyAt: Date | null; applicationFeeTotalCents: bigint | null; authorizedTotalCents: bigint; authorizeStatus: OrderAuthorizeStatus; capturedTotalCents: bigint; cartId: string | null; chargeStatus: OrderChargeStatus; closedAt: Date | null; code: string; createdAt: Date; createdBy: string | null; currencyCode: string; customerEmail: string | null; customerId: string | null; customerTotalCents: bigint; disputedTotalCents: bigint; externalRef: string | null; id: string; idempotencyKey: string | null; metadata: JsonValue; notes: string | null; operatorId: string | null; organizationId: string; orgBorneTotalCents: bigint; origin: string; placedAt: Date | null; platformBorneTotalCents: bigint; processingFeeTotalCents: bigint | null; refundedTotalCents: bigint; requestHash: string | null; status: OrderStatus; statusUpdatedAt: Date; statusUpdatedBy: string | null; subtotalCents: bigint; updatedAt: Date; updatedBy: string | null; }>>


createOrder()

createOrder(priced: PricedCart, opts: CreateOrderOptions): Promise<BigIntsAsNumbers<{
  anomalyAt: Date | null;
  applicationFeeTotalCents: bigint | null;
  authorizedTotalCents: bigint;
  authorizeStatus: OrderAuthorizeStatus;
  capturedTotalCents: bigint;
  cartId: string | null;
  chargeStatus: OrderChargeStatus;
  closedAt: Date | null;
  code: string;
  createdAt: Date;
  createdBy: string | null;
  currencyCode: string;
  customerEmail: string | null;
  customerId: string | null;
  customerTotalCents: bigint;
  disputedTotalCents: bigint;
  externalRef: string | null;
  id: string;
  idempotencyKey: string | null;
  metadata: JsonValue;
  notes: string | null;
  operatorId: string | null;
  organizationId: string;
  orgBorneTotalCents: bigint;
  origin: string;
  placedAt: Date | null;
  platformBorneTotalCents: bigint;
  processingFeeTotalCents: bigint | null;
  refundedTotalCents: bigint;
  requestHash: string | null;
  status: OrderStatus;
  statusUpdatedAt: Date;
  statusUpdatedBy: string | null;
  subtotalCents: bigint;
  updatedAt: Date;
  updatedBy: string | null;
}>>;

Defined in: server/checkout/order-service.ts:190

Create an order from a PricedCart snapshot (proposal §finalize step 4 + §Idempotency & errors + §Order code). In one transaction: insert the order (pending, placedAt = clock()), the line items and adjustments, project paid immediately when the customer total is 0, and append the order.placed (+ order.paid) domain events.

Code-collision retry only operates when createOrder OWNS the transaction. When a caller invokes it inside an ambient repos.transaction(...), TransactionManager.startOrUseTransaction JOINS that transaction, so a P2002 poisons the caller's PG transaction — re-running the inserts would execute on an aborted transaction. In that case the create runs exactly once and any P2002 propagates; ambient callers must wrap their own retry around their whole transaction (stage-7 finalize does exactly that).

Parameters

ParameterType
pricedPricedCart
optsCreateOrderOptions

Returns

Promise<BigIntsAsNumbers<{ anomalyAt: Date | null; applicationFeeTotalCents: bigint | null; authorizedTotalCents: bigint; authorizeStatus: OrderAuthorizeStatus; capturedTotalCents: bigint; cartId: string | null; chargeStatus: OrderChargeStatus; closedAt: Date | null; code: string; createdAt: Date; createdBy: string | null; currencyCode: string; customerEmail: string | null; customerId: string | null; customerTotalCents: bigint; disputedTotalCents: bigint; externalRef: string | null; id: string; idempotencyKey: string | null; metadata: JsonValue; notes: string | null; operatorId: string | null; organizationId: string; orgBorneTotalCents: bigint; origin: string; placedAt: Date | null; platformBorneTotalCents: bigint; processingFeeTotalCents: bigint | null; refundedTotalCents: bigint; requestHash: string | null; status: OrderStatus; statusUpdatedAt: Date; statusUpdatedBy: string | null; subtotalCents: bigint; updatedAt: Date; updatedBy: string | null; }>>


get()

get(orderId: string): Promise<BigIntsAsNumbers<{
  anomalyAt: Date | null;
  applicationFeeTotalCents: bigint | null;
  authorizedTotalCents: bigint;
  authorizeStatus: OrderAuthorizeStatus;
  capturedTotalCents: bigint;
  cartId: string | null;
  chargeStatus: OrderChargeStatus;
  closedAt: Date | null;
  code: string;
  createdAt: Date;
  createdBy: string | null;
  currencyCode: string;
  customerEmail: string | null;
  customerId: string | null;
  customerTotalCents: bigint;
  disputedTotalCents: bigint;
  externalRef: string | null;
  id: string;
  idempotencyKey: string | null;
  metadata: JsonValue;
  notes: string | null;
  operatorId: string | null;
  organizationId: string;
  orgBorneTotalCents: bigint;
  origin: string;
  placedAt: Date | null;
  platformBorneTotalCents: bigint;
  processingFeeTotalCents: bigint | null;
  refundedTotalCents: bigint;
  requestHash: string | null;
  status: OrderStatus;
  statusUpdatedAt: Date;
  statusUpdatedBy: string | null;
  subtotalCents: bigint;
  updatedAt: Date;
  updatedBy: string | null;
}>>;

Defined in: server/checkout/order-service.ts:252

Fetch by id; missing → CheckoutNotFoundError.

Parameters

ParameterType
orderIdstring

Returns

Promise<BigIntsAsNumbers<{ anomalyAt: Date | null; applicationFeeTotalCents: bigint | null; authorizedTotalCents: bigint; authorizeStatus: OrderAuthorizeStatus; capturedTotalCents: bigint; cartId: string | null; chargeStatus: OrderChargeStatus; closedAt: Date | null; code: string; createdAt: Date; createdBy: string | null; currencyCode: string; customerEmail: string | null; customerId: string | null; customerTotalCents: bigint; disputedTotalCents: bigint; externalRef: string | null; id: string; idempotencyKey: string | null; metadata: JsonValue; notes: string | null; operatorId: string | null; organizationId: string; orgBorneTotalCents: bigint; origin: string; placedAt: Date | null; platformBorneTotalCents: bigint; processingFeeTotalCents: bigint | null; refundedTotalCents: bigint; requestHash: string | null; status: OrderStatus; statusUpdatedAt: Date; statusUpdatedBy: string | null; subtotalCents: bigint; updatedAt: Date; updatedBy: string | null; }>>


getByCode()

getByCode(organizationId: string, code: string): Promise<BigIntsAsNumbers<{
  anomalyAt: Date | null;
  applicationFeeTotalCents: bigint | null;
  authorizedTotalCents: bigint;
  authorizeStatus: OrderAuthorizeStatus;
  capturedTotalCents: bigint;
  cartId: string | null;
  chargeStatus: OrderChargeStatus;
  closedAt: Date | null;
  code: string;
  createdAt: Date;
  createdBy: string | null;
  currencyCode: string;
  customerEmail: string | null;
  customerId: string | null;
  customerTotalCents: bigint;
  disputedTotalCents: bigint;
  externalRef: string | null;
  id: string;
  idempotencyKey: string | null;
  metadata: JsonValue;
  notes: string | null;
  operatorId: string | null;
  organizationId: string;
  orgBorneTotalCents: bigint;
  origin: string;
  placedAt: Date | null;
  platformBorneTotalCents: bigint;
  processingFeeTotalCents: bigint | null;
  refundedTotalCents: bigint;
  requestHash: string | null;
  status: OrderStatus;
  statusUpdatedAt: Date;
  statusUpdatedBy: string | null;
  subtotalCents: bigint;
  updatedAt: Date;
  updatedBy: string | null;
}>>;

Defined in: server/checkout/order-service.ts:259

Human-readable reference lookup; missing → CheckoutNotFoundError.

Parameters

ParameterType
organizationIdstring
codestring

Returns

Promise<BigIntsAsNumbers<{ anomalyAt: Date | null; applicationFeeTotalCents: bigint | null; authorizedTotalCents: bigint; authorizeStatus: OrderAuthorizeStatus; capturedTotalCents: bigint; cartId: string | null; chargeStatus: OrderChargeStatus; closedAt: Date | null; code: string; createdAt: Date; createdBy: string | null; currencyCode: string; customerEmail: string | null; customerId: string | null; customerTotalCents: bigint; disputedTotalCents: bigint; externalRef: string | null; id: string; idempotencyKey: string | null; metadata: JsonValue; notes: string | null; operatorId: string | null; organizationId: string; orgBorneTotalCents: bigint; origin: string; placedAt: Date | null; platformBorneTotalCents: bigint; processingFeeTotalCents: bigint | null; refundedTotalCents: bigint; requestHash: string | null; status: OrderStatus; statusUpdatedAt: Date; statusUpdatedBy: string | null; subtotalCents: bigint; updatedAt: Date; updatedBy: string | null; }>>


list()

list(organizationId: string, filters?: OrderListFilters): Promise<BigIntsAsNumbers<{
  anomalyAt: Date | null;
  applicationFeeTotalCents: bigint | null;
  authorizedTotalCents: bigint;
  authorizeStatus: OrderAuthorizeStatus;
  capturedTotalCents: bigint;
  cartId: string | null;
  chargeStatus: OrderChargeStatus;
  closedAt: Date | null;
  code: string;
  createdAt: Date;
  createdBy: string | null;
  currencyCode: string;
  customerEmail: string | null;
  customerId: string | null;
  customerTotalCents: bigint;
  disputedTotalCents: bigint;
  externalRef: string | null;
  id: string;
  idempotencyKey: string | null;
  metadata: JsonValue;
  notes: string | null;
  operatorId: string | null;
  organizationId: string;
  orgBorneTotalCents: bigint;
  origin: string;
  placedAt: Date | null;
  platformBorneTotalCents: bigint;
  processingFeeTotalCents: bigint | null;
  refundedTotalCents: bigint;
  requestHash: string | null;
  status: OrderStatus;
  statusUpdatedAt: Date;
  statusUpdatedBy: string | null;
  subtotalCents: bigint;
  updatedAt: Date;
  updatedBy: string | null;
}>[]>;

Defined in: server/checkout/order-service.ts:269

Thin delegation to the repo — settledOnly ANDs the disputed overlay in (disputedTotalCents: 0) so consumers never hand-roll it.

Parameters

ParameterType
organizationIdstring
filters?OrderListFilters

Returns

Promise<BigIntsAsNumbers<{ anomalyAt: Date | null; applicationFeeTotalCents: bigint | null; authorizedTotalCents: bigint; authorizeStatus: OrderAuthorizeStatus; capturedTotalCents: bigint; cartId: string | null; chargeStatus: OrderChargeStatus; closedAt: Date | null; code: string; createdAt: Date; createdBy: string | null; currencyCode: string; customerEmail: string | null; customerId: string | null; customerTotalCents: bigint; disputedTotalCents: bigint; externalRef: string | null; id: string; idempotencyKey: string | null; metadata: JsonValue; notes: string | null; operatorId: string | null; organizationId: string; orgBorneTotalCents: bigint; origin: string; placedAt: Date | null; platformBorneTotalCents: bigint; processingFeeTotalCents: bigint | null; refundedTotalCents: bigint; requestHash: string | null; status: OrderStatus; statusUpdatedAt: Date; statusUpdatedBy: string | null; subtotalCents: bigint; updatedAt: Date; updatedBy: string | null; }>[]>


recompute()

recompute(orderId: string): Promise<BigIntsAsNumbers<{
  anomalyAt: Date | null;
  applicationFeeTotalCents: bigint | null;
  authorizedTotalCents: bigint;
  authorizeStatus: OrderAuthorizeStatus;
  capturedTotalCents: bigint;
  cartId: string | null;
  chargeStatus: OrderChargeStatus;
  closedAt: Date | null;
  code: string;
  createdAt: Date;
  createdBy: string | null;
  currencyCode: string;
  customerEmail: string | null;
  customerId: string | null;
  customerTotalCents: bigint;
  disputedTotalCents: bigint;
  externalRef: string | null;
  id: string;
  idempotencyKey: string | null;
  metadata: JsonValue;
  notes: string | null;
  operatorId: string | null;
  organizationId: string;
  orgBorneTotalCents: bigint;
  origin: string;
  placedAt: Date | null;
  platformBorneTotalCents: bigint;
  processingFeeTotalCents: bigint | null;
  refundedTotalCents: bigint;
  requestHash: string | null;
  status: OrderStatus;
  statusUpdatedAt: Date;
  statusUpdatedBy: string | null;
  subtotalCents: bigint;
  updatedAt: Date;
  updatedBy: string | null;
}>>;

Defined in: server/checkout/order-service.ts:296

THE single write path for the denormalized buckets (proposal §recompute — stage 5 reuses this verbatim). In one transaction: lock the order row, load the tender facts, run the shared pure fold (recomputeOrder), and persist:

  • the six buckets, always;
  • status/authorizeStatus/chargeStatus from the computation, with statusUpdatedAt/statusUpdatedBy touched only when the projection actually changed;
  • anomalyAt: set on the null→anomalous transition (never overwriting an existing timestamp), cleared when the anomaly resolves.

Events, same transaction: order.status_changed when the projection changed; one order.anomaly per cause in each anomaly cycle. Independent causes remain visible even when anomalyAt was set by another cause.

Deliberately NOT here (stage-5 call sites own them): closedAt, order.paid, and per-payment bucket persistence.

Parameters

ParameterType
orderIdstring

Returns

Promise<BigIntsAsNumbers<{ anomalyAt: Date | null; applicationFeeTotalCents: bigint | null; authorizedTotalCents: bigint; authorizeStatus: OrderAuthorizeStatus; capturedTotalCents: bigint; cartId: string | null; chargeStatus: OrderChargeStatus; closedAt: Date | null; code: string; createdAt: Date; createdBy: string | null; currencyCode: string; customerEmail: string | null; customerId: string | null; customerTotalCents: bigint; disputedTotalCents: bigint; externalRef: string | null; id: string; idempotencyKey: string | null; metadata: JsonValue; notes: string | null; operatorId: string | null; organizationId: string; orgBorneTotalCents: bigint; origin: string; placedAt: Date | null; platformBorneTotalCents: bigint; processingFeeTotalCents: bigint | null; refundedTotalCents: bigint; requestHash: string | null; status: OrderStatus; statusUpdatedAt: Date; statusUpdatedBy: string | null; subtotalCents: bigint; updatedAt: Date; updatedBy: string | null; }>>


recomputeTenderFromLedger()

protected recomputeTenderFromLedger(
   repos: CheckoutRepositories, 
   payment: PaymentRow, 
   overrides?: Partial<Pick<TenderFacts, "clientActionRequired" | "clientActionRequiredAt">>
): Promise<{
  fold: TenderComputation;
  patch: TenderBucketPatch;
}>;

Defined in: server/checkout/base-checkout-service.ts:94

Re-project a tender from its persisted ledger without writing it. Explicit clientActionRequiredAt: null clears the stored timestamp.

Parameters

ParameterType
reposCheckoutRepositories
paymentPaymentRow
overrides?Partial<Pick<TenderFacts, "clientActionRequired" | "clientActionRequiredAt">>

Returns

Promise<{ fold: TenderComputation; patch: TenderBucketPatch; }>

Inherited from

BaseCheckoutService.recomputeTenderFromLedger

reconcileClosedAt()

protected reconcileClosedAt(
   repos: CheckoutRepositories, 
   order: OrderRow, 
   now: Date
): Promise<void>;

Defined in: server/checkout/base-checkout-service.ts:121

Reconcile closedAt and the once-per-order order.paid event after a money write. The caller must hold the order lock in an ambient transaction.

Parameters

ParameterType
reposCheckoutRepositories
orderOrderRow
nowDate

Returns

Promise<void>

Inherited from

BaseCheckoutService.reconcileClosedAt

recordCanonicalTransactions()

protected recordCanonicalTransactions(
   repos: CheckoutRepositories, 
   context: RecordTxnContext, 
   transactions: CanonicalTxn[]
): Promise<RecordedCanonicalTxn[]>;

Defined in: server/checkout/base-checkout-service.ts:61

Record canonical transactions sequentially and identify both fresh inserts and pending rows resolved in place. Callers own the resulting side effects.

Parameters

ParameterType
reposCheckoutRepositories
contextRecordTxnContext
transactionsCanonicalTxn[]

Returns

Promise<RecordedCanonicalTxn[]>

Inherited from

BaseCheckoutService.recordCanonicalTransactions

redactContact()

redactContact(orderId: string): Promise<BigIntsAsNumbers<{
  anomalyAt: Date | null;
  applicationFeeTotalCents: bigint | null;
  authorizedTotalCents: bigint;
  authorizeStatus: OrderAuthorizeStatus;
  capturedTotalCents: bigint;
  cartId: string | null;
  chargeStatus: OrderChargeStatus;
  closedAt: Date | null;
  code: string;
  createdAt: Date;
  createdBy: string | null;
  currencyCode: string;
  customerEmail: string | null;
  customerId: string | null;
  customerTotalCents: bigint;
  disputedTotalCents: bigint;
  externalRef: string | null;
  id: string;
  idempotencyKey: string | null;
  metadata: JsonValue;
  notes: string | null;
  operatorId: string | null;
  organizationId: string;
  orgBorneTotalCents: bigint;
  origin: string;
  placedAt: Date | null;
  platformBorneTotalCents: bigint;
  processingFeeTotalCents: bigint | null;
  refundedTotalCents: bigint;
  requestHash: string | null;
  status: OrderStatus;
  statusUpdatedAt: Date;
  statusUpdatedBy: string | null;
  subtotalCents: bigint;
  updatedAt: Date;
  updatedBy: string | null;
}>>;

Defined in: server/checkout/order-service.ts:555

GDPR/CCPA redaction (proposal §Ledger of record): contact snapshots are recompute-irrelevant and redactable. Nulls customerEmail and nothing else; no events. Missing order → the repo's CheckoutNotFoundError (thrown by WriteRepository.update's existence check).

Parameters

ParameterType
orderIdstring

Returns

Promise<BigIntsAsNumbers<{ anomalyAt: Date | null; applicationFeeTotalCents: bigint | null; authorizedTotalCents: bigint; authorizeStatus: OrderAuthorizeStatus; capturedTotalCents: bigint; cartId: string | null; chargeStatus: OrderChargeStatus; closedAt: Date | null; code: string; createdAt: Date; createdBy: string | null; currencyCode: string; customerEmail: string | null; customerId: string | null; customerTotalCents: bigint; disputedTotalCents: bigint; externalRef: string | null; id: string; idempotencyKey: string | null; metadata: JsonValue; notes: string | null; operatorId: string | null; organizationId: string; orgBorneTotalCents: bigint; origin: string; placedAt: Date | null; platformBorneTotalCents: bigint; processingFeeTotalCents: bigint | null; refundedTotalCents: bigint; requestHash: string | null; status: OrderStatus; statusUpdatedAt: Date; statusUpdatedBy: string | null; subtotalCents: bigint; updatedAt: Date; updatedBy: string | null; }>>


transaction()

protected transaction<T>(fn: (deps: CheckoutFeatureDeps) => Promise<T>): Promise<T>;

Defined in: server/checkout/base-checkout-service.ts:49

Type Parameters

Type Parameter
T

Parameters

ParameterType
fn(deps: CheckoutFeatureDeps) => Promise<T>

Returns

Promise<T>

Inherited from

BaseCheckoutService.transaction

On this page