---
id: WF-COM-ORD-005
title: Void an unaccepted order and give back what it held
trigger: A reasoned staff request or an elapsed payment deadline starts a placed-sale void.
product_area: commerce
module: orders
revision: 1
status: draft
design_intent: proposed
implementation_evidence: observed
inference: []
source_sha:
  services-commerce: c8b66a98e2490617aec38ba5c8165dd9bd0a8f9b
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
implements:
  - CAP-COM-ORD-008
  - CAP-COM-ORD-004
  - CAP-COM-ORD-015
moves:
  - STATE-COM-ORD-004
  - STATE-COM-ORD-003
  - STATE-COM-ORD-010
crosses:
  - SVC-COM-ORD-orders
  - SVC-COM-ORD-participants
  - SVC-ACC-TRX-transactions
  - SVC-PFM-OPS-audit
idempotency: >-
  The staff request ledger replays the original void. An independent later void is refused by sale status;
  adjustment and invoice-deletion keys preserve the same reversal requests.
concurrency: >-
  Void locks the sale and requires placed status. Acceptance winning first rejects void; uncertain payment
  prevents void rather than risking an unresolved capture.
hops:
  - 'n': 1
    actor_or_service: Orders route or tender-window sweep
    action: >-
      Authorize a reasoned staff void or discover overdue placed orders for a system void within their
      workspace.
    anchor: 'services-commerce:modules/orders/services/orders/tender-window-sweeper.ts:sweepTenderWindows'
    seam: schedule
    on_failure: >-
      Staff requests reject non-placed orders; the sweep skips changed orders and propagates unexpected
      failures.
    left_inconsistent: Overdue sales can retain their resources while processing is delayed.
    observer: >-
      Observed through observed through staff from the refusal; function logs and error alarm for the sweep;
      window-expired informational exception.
    provenance: test
    source: >-
      services-commerce:modules/checkout/tests/e2e/order-void.e2e.spec.js#refuses a second void, 409
      order_not_voidable, and a read answers the order voided
  - 'n': 2
    actor_or_service: Accounting (read)
    action: Read remote payments before the transaction to resolve mixed settlement and card legs.
    anchor: 'services-commerce:modules/orders/services/orders/void-refund.ts'
    seam: sync
    on_failure: An unanswered leg is escalated instead of guessed into a refund plan.
    left_inconsistent: Unresolved captured money requires operational recovery.
    observer: Observed through observed through adjustment-failed exception on the attempt.
    provenance: observed
    source: 'services-commerce:modules/orders/services/orders/void-refund.ts:voidRefundLegsOf'
  - 'n': 3
    actor_or_service: Void transaction
    action: >-
      In one transaction, release application claims and ledger, cancel pending work, return promotion uses,
      record void and refund plans, and restore original lines for a voided change order.
    anchor: 'services-commerce:modules/orders/services/orders/void-order.ts:voidOrder'
    seam: sync
    on_failure: Transaction failure preserves the placed sale and rolls back releases.
    left_inconsistent: No partial domain void commits.
    observer: 'Observed through sale history (claims released, promotion released, void refund planned, transitioned).'
    provenance: test
    source: >-
      services-commerce:modules/checkout/tests/e2e/order-void.e2e.spec.js#released the participant’s claim,
      the ledger and the obligations
  - 'n': 4
    actor_or_service: Accounting
    action: 'After void commits, request deletion of linked provisional invoices and record each response.'
    anchor: 'services-commerce:modules/orders/services/billing/billing-port.ts:voidProForma'
    seam: sync
    on_failure: >-
      Locked or converted invoices require attention; unanswered deletions are deferred without a retry
      caller.
    left_inconsistent: Accounting may retain a provisional invoice for the voided sale.
    observer: Observed through sale history (billing voided with each invoice's outcome).
    provenance: observed
    source: 'services-commerce:modules/orders/services/orders/void-order.ts:voidOrder'
  - 'n': 5
    actor_or_service: Adjustment worker (fulfilment module)
    action: 'Refund captured legs and then memo the sale invoice, retaining keyed steps and order history.'
    anchor: 'services-commerce:modules/fulfillment/services/adjustments/adjustment-worker.ts:executeAdjustment'
    seam: sync
    on_failure: Refusal raises an adjustment exception; stale work can be resumed by the reconciler or staff.
    left_inconsistent: Voided sales can still await returned money.
    observer: >-
      Observed through observed through adjustment exceptions; Order 360 Transactions after the mirror
      refreshes.
    provenance: test
    source: >-
      services-commerce:modules/orders/tests/e2e/billing-and-tender.e2e.spec.js#ran the plan through the
      adjustment worker: the card leg refunded under the void’s key, then the memo of the sale invoice
  - 'n': 6
    actor_or_service: Platform audit
    action: Send the staff intervention audit message after commit.
    anchor: 'services-commerce:modules/fulfillment/services/register/intervention-audit.ts:auditIntervention'
    seam: event
    on_failure: Audit failure is logged without reversing the void.
    left_inconsistent: The default fixture provider supplies no durable Platform audit record.
    observer: Observed through observed through commerce's intervention log; application logs.
    provenance: observed
    source: 'services-commerce:modules/fulfillment/services/register/intervention-audit.ts:auditIntervention'
branches:
  - 'Without captured money, void needs no refund plan.'
  - Voiding an amendment sale also voids the amendment and restores its source line.
waits:
  - >-
    Refund processing awaits Accounting, with uncertain outcomes resolved through financial facts or
    reconciliation.
evidence:
  - >-
    services-commerce at c8b66a98: modules/orders/services/orders/void-order.ts, void-refund.ts,
    tender-window-sweeper.ts; services/billing/billing-port.ts; aws/api/orders.routes.ts (voidOrder);
    modules/fulfillment/services/adjustments/adjustment-worker.ts; tests/e2e/order-void.e2e.spec.js.
  - 'react-console at baf6dae3: components/commerce/order-flows/void-order-dialog.tsx.'
controls: [TC-IAM-006, TC-AZ-001, TC-AZ-002, TC-AZ-003, TC-AZ-004, TC-AZ-005, TC-AZ-006, TC-TEN-001, TC-TEN-002, TC-TEN-003, TC-TEN-004, TC-CRY-001, TC-DAT-001, TC-DAT-002, TC-DAT-003, TC-DAT-004, TC-LOG-001, TC-LOG-002, TC-LOG-003, TC-LOG-004, TC-LOG-005, TC-AVL-004, TC-MON-001, TC-MON-002, TC-MON-004, TC-PI-001, TC-PI-002, TC-PI-003, TC-PI-004, TC-PI-005, TC-PRV-001, TC-PRV-002]
---

# Void an unaccepted order and give back what it held

## What It Does

Void ends a sale before acceptance. The transaction returns claimed resources and offer uses, cancels pending delivery and records any captured-money reversal plan, then requests provisional-invoice deletion.

## The Flow

```mermaid
sequenceDiagram
  participant S as Staff or window sweep
  participant O as Orders
  participant A as Selling application
  participant X as Accounting
  participant W as Adjustment worker
  S->>O: void (reason)
  O->>X: read payments (split settlement legs)
  O->>A: one transaction: release claims (application functions), ledger, obligations, redemptions, voided, refund plan
  O->>X: delete provisional invoices (after commit)
  O->>W: run the refund plan
  W->>X: refunds, then the memo
  O-->>S: the voided order
```

## When Something Fails

Domain releases share one transaction. After commit, invoice deletion and financial outcomes cannot undo the void. Deferred deletion has no automatic retry, while adjustments use worker recovery and exceptions. Unresolved mixed-payment legs need attention, and sweep failure can delay later passes.

## Open Design Questions

Deferred invoice deletion needs an operational recovery choice. Staff audit delivery still lacks a durable Platform writer.
