---
id: WF-COM-ORD-008
title: Keep the order's money position current
trigger: 'Financial actions, received Accounting facts and an eligible stale-mirror pass request refresh.'
product_area: commerce
module: orders
revision: 1
status: draft
design_intent: proposed
implementation_evidence: observed
inference: []
source_sha:
  services-commerce: c8b66a98e2490617aec38ba5c8165dd9bd0a8f9b
implements:
  - CAP-COM-ORD-010
  - CAP-COM-ORD-006
  - CAP-COM-ORD-007
  - CAP-COM-ORD-014
crosses:
  - SVC-COM-ORD-orders
  - SVC-ACC-TRX-transactions
idempotency: >-
  Refresh derives a replacement financial projection, while recurring disagreements reuse open exceptions.
  Fact receipt identity prevents repeating a completed event handling run.
concurrency: >-
  Position reads precede a separate mirror-write transaction. Last writer wins with no freshness comparison,
  allowing an older refresh to overwrite newer facts.
hops:
  - 'n': 1
    actor_or_service: Orders
    action: Read Accounting's financial positions for the billed order lines.
    anchor: 'services-commerce:modules/orders/services/persistence/financial-positions.ts'
    seam: sync
    on_failure: Callers log failed reads and allow their committed domain action to stand.
    left_inconsistent: The existing projection remains older than Accounting.
    observer: Observed through the function records the outcome in its log.
    provenance: observed
    source: 'services-commerce:modules/orders/services/mirror/refresh-money-mirror.ts:refreshMoneyMirrorOf'
  - 'n': 2
    actor_or_service: Orders
    action: >-
      Derive invoicing, applied money, credits, refunds, write-offs and balance, persisting the result even
      when missing positions, currency or totals disagree.
    anchor: 'services-commerce:modules/orders/services/mirror/money-mirror.ts:deriveMoneyMirror'
    seam: sync
    on_failure: Failed persistence leaves the previous projection.
    left_inconsistent: Displayed financial facts remain stale.
    observer: Observed through observed through order 360 and the Orders list balance.
    provenance: test
    source: >-
      services-commerce:modules/orders/tests/e2e/billing-and-tender.e2e.spec.js#mirrors Accounting’s position:
      invoiced and paid in full, nothing due
  - 'n': 3
    actor_or_service: Orders
    action: Record each detected disagreement as an order or line exception.
    anchor: 'services-commerce:modules/orders/services/mirror/refresh-money-mirror.ts:refreshMoneyMirrorOf'
    seam: sync
    on_failure: Failure is logged by the invoking recovery boundary.
    left_inconsistent: The disagreement can lack a visible operational exception.
    observer: 'Observed through the operational exception list (mirror mismatch, accepted without invoice line).'
    provenance: observed
    source: 'services-commerce:modules/orders/services/mirror/refresh-money-mirror.ts'
  - 'n': 4
    actor_or_service: Financial-facts receiver (fulfilment module)
    action: >-
      Handle received Accounting facts by finding lines, recording history, resuming adjustments, evaluating
      gates and refreshing the mirror before recording receipt.
    anchor: 'services-commerce:modules/fulfillment/services/facts/financial-facts-handler.ts'
    seam: event
    on_failure: Failed handling leaves the event eligible for redelivery; mirror failure is logged separately.
    left_inconsistent: 'Without incoming facts, background refresh supplies eventual updates.'
    observer: Observed through sale history; recorded operational exceptions.
    provenance: observed
    source: 'services-commerce:modules/fulfillment/services/facts/financial-facts-handler.ts'
  - 'n': 5
    actor_or_service: Mirror sweep
    action: >-
      Refresh a bounded oldest-first set of accepted orders with hour-old mirrors, synchronizing schedules for
      installment orders.
    anchor: 'services-commerce:modules/orders/services/orders/financial-sweeps.ts:sweepFinancials'
    seam: schedule
    on_failure: Per-order failures permit continued processing; no Accounting transport skips the pass.
    left_inconsistent: Backlog and failures extend the age of displayed money facts.
    observer: Observed through recovery-pass log; mirror-mismatch exceptions.
    provenance: observed
    source: 'services-commerce:modules/orders/services/orders/financial-sweeps.ts:sweepFinancials'
branches:
  - No invoiced line produces a zero financial projection without a discrepancy.
  - Installment purchases allow partial invoicing and flag only invoicing beyond the purchase total.
waits: []
evidence:
  - >-
    services-commerce at c8b66a98: modules/orders/services/mirror/*.ts;
    services/persistence/financial-positions.ts; services/orders/financial-sweeps.ts;
    modules/fulfillment/services/facts/financial-facts-handler.ts.
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-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]
---

# Keep the order's money position current

## What It Does

The financial projection makes Accounting's latest known position available to local order reads. Disagreement produces exceptions rather than Commerce editing Accounting's ledger.

## The Flow

```mermaid
sequenceDiagram
  participant T as Trigger (payment, acceptance, cancellation, fact, sweep)
  participant O as Orders
  participant V as Accounting position view
  participant E as Exceptions
  T->>O: refresh mirror
  O->>V: read positions of billed lines
  O->>O: derive figures and mismatches
  O->>O: write mirror
  O->>E: raise mismatches
```

## When Something Fails

Failed refresh leaves the prior mirror. Exceptions can also fail after the new mirror is stored. Event redelivery and bounded scheduled refresh provide recovery, but no age guard prevents a delayed older derivation from overwriting a newer one.

## Open Design Questions

Event wiring and live Accounting position proof remain dependencies. Concurrent refresh needs a freshness boundary.
