Skip to main content

Two derivations: deriveOrderMatchStatus(sizeVector) + a separate settlement-outcome capture

The order's user-facing state is produced by two separate, modular, pure functions — replacing the six scattered status mappers that decide it today (Betfair mapPlacementStatus / mapExecutionCompleteStatus / mapClearedSettlementOutcome, Bifrost mapBetStatusToOrderStatus, PinnacleMapper, betsApi.deriveStatus):

  1. deriveOrderMatchStatus(sizeVector) — pure, size-vector-only, read-time, zero provider branches. The single source of the match-axis display status: unmatched | partially_matched (+ lossless remainder breakdown) | matched | fully_lapsed | fully_cancelled. Adapters' only job is to normalize their wire payload into the Size Vector.
  2. deriveOrderOutcome(...) — the modular "rest": the settlement outcome (win | lose | void)
    • P&L. A separate axis from the match status.

settled is one status; the outcome is separate

Once an order settles, its status is the single value settled — never win/lose/void. It remains the stored DB lifecycle terminal (Order.status = 'settled') — already persisted, no new column. The win/lose/void result is the separate, already-stored Order.settlementOutcome (produced by function 2), never folded into the status. settled is added to the display-status list.

Composition for display

primary = (Order.status === 'settled')
? 'settled'
: deriveOrderMatchStatus(sizeVector);

The settlement outcome and the lossless match breakdown are shown alongside the primary — a settled winning bet displays "Settled · Won · ₹60 matched", losslessly (ADR-0003). This keeps deriveOrderMatchStatus purely size-vector-driven while settled stays the stored lifecycle terminal.

Scope note

This replaces the scattered display-status determination (the six mappers). The coarse DB lifecycle-status write-sites (orderService / orderSyncJob / settlement / Bifrost / Pinnacle) remain as infrastructure (ADR-0002) — unifying those is a separate follow-up, not this change.