---
id: STATE-ACC-TRX-006
title: Payment lifecycle
object: DOM-ACC-TRX-003
product_area: accounting
module: transactions
revision: 1
status: draft
design_intent: proposed
implementation_evidence: observed
source_sha:
  services-accounting: f47cb263875bbc0c5640fba7dae6785ec32695f8
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
states:
  - name: not created
    meaning: The receipt has not been recorded.
  - name: succeeded
    meaning: Collected money is held or applied for the customer.
  - name: pending settlement
    meaning: An accepted bank debit is awaiting clearing.
  - name: partially refunded
    meaning: Some collected money has been returned by refund.
  - name: refunded
    meaning: Refunds have returned the receipt's full value.
  - name: voided
    meaning: Cancellation has removed the collected value.
  - name: returned
    meaning: A bank or check return has removed the collected value.
  - name: charged back
    meaning: A lost chargeback has removed the collected value.
transitions:
  - from: not created
    to: succeeded
    trigger: record received money
    guard: >-
      A positive amount, enabled currency, usable method, matching cash
      destination, eligible batch and open period are required.
    side_effects:
      - assign the receipt number
      - insert planned allocations
      - append financial facts and history
    who: >-
      Staff with payment-create permission, the Commerce tender function or a
      coordinated receipt command.
    provenance: observed
    source: >-
      services-accounting:modules/transactions/services/payments/payment-receive.ts;
      services-accounting:modules/transactions/services/payments/payment-reverse.ts;
      services-accounting:modules/transactions/services/refunds/refund-commands.ts;
      services-accounting:modules/transactions/db/payments.table.ts;
      services-accounting:modules/transactions/tests/integration/services/payments/receive-offline.integration.spec.js#it
      refuses a date in no open period (period_not_open)
  - from: not created
    to: pending settlement
    trigger: record an accepted bank debit
    guard: Electronic collection eligibility must hold.
    side_effects:
      - retain the receipt awaiting clearing
    who: Authorized staff or the Commerce tender function.
    provenance: observed
    source: >-
      services-accounting:modules/transactions/services/payments/payment-receive.ts;
      services-accounting:modules/transactions/services/payments/payment-reverse.ts;
      services-accounting:modules/transactions/services/refunds/refund-commands.ts;
      services-accounting:modules/transactions/db/payments.table.ts;
      services-accounting:modules/transactions/tests/integration/services/payments/payment-reversals.integration.spec.js#it
      settles the one the bank cleared: succeeded, settled_at, its capture item
      eligible, the settle event
  - from: pending settlement
    to: succeeded
    trigger: confirm bank clearing
    guard: The receipt must await settlement.
    side_effects:
      - record clearing time
      - make the capture eligible for reconciliation
    who: 'Integration events, scheduled recovery or the authorized system route.'
    provenance: observed
    source: >-
      services-accounting:modules/transactions/services/payments/payment-receive.ts;
      services-accounting:modules/transactions/services/payments/payment-reverse.ts;
      services-accounting:modules/transactions/services/refunds/refund-commands.ts;
      services-accounting:modules/transactions/db/payments.table.ts;
      services-accounting:modules/transactions/tests/integration/services/payments/payment-reversals.integration.spec.js#it
      settles the one the bank cleared: succeeded, settled_at, its capture item
      eligible, the settle event
  - from: pending settlement
    to: returned
    trigger: record an unsuccessful bank debit
    guard: The receipt must await settlement.
    side_effects:
      - create the bank-return reversal
      - release its allocations
    who: Processor event handling.
    provenance: observed
    source: >-
      services-accounting:modules/transactions/services/payments/payment-receive.ts;
      services-accounting:modules/transactions/services/payments/payment-reverse.ts;
      services-accounting:modules/transactions/services/refunds/refund-commands.ts;
      services-accounting:modules/transactions/db/payments.table.ts;
      services-accounting:modules/transactions/tests/integration/services/payments/payment-reversals.integration.spec.js#it
      settles the one the bank cleared: succeeded, settled_at, its capture item
      eligible, the settle event
  - from: succeeded
    to: partially refunded
    trigger: return part of the receipt
    guard: Executed refunds must total less than the receipt amount.
    side_effects:
      - derive refund status through database amount maintenance
    who: Staff with refund-execute permission.
    provenance: observed
    source: >-
      services-accounting:modules/transactions/services/payments/payment-receive.ts;
      services-accounting:modules/transactions/services/payments/payment-reverse.ts;
      services-accounting:modules/transactions/services/refunds/refund-commands.ts;
      services-accounting:modules/transactions/db/payments.table.ts;
      services-accounting:modules/transactions/tests/integration/services/refunds/refunds.integration.spec.js#it
      records it offline: executed, the payment partially_refunded with 1000
      refunded (FC-11, FC-14)
  - from: partially refunded
    to: refunded
    trigger: return the remaining receipt
    guard: Refunded value must reach the receipt amount.
    side_effects:
      - derive refund status through database amount maintenance
    who: Staff with refund-execute permission.
    provenance: observed
    source: >-
      services-accounting:modules/transactions/services/payments/payment-receive.ts;
      services-accounting:modules/transactions/services/payments/payment-reverse.ts;
      services-accounting:modules/transactions/services/refunds/refund-commands.ts;
      services-accounting:modules/transactions/db/payments.table.ts;
      services-accounting:modules/transactions/tests/integration/services/refunds/refunds.integration.spec.js#it
      records it offline: executed, the payment partially_refunded with 1000
      refunded (FC-11, FC-14)
  - from: succeeded
    to: refunded
    trigger: return the whole receipt
    guard: The executed refund must cover its amount.
    side_effects:
      - derive refund status through database amount maintenance
    who: Staff with refund-execute permission.
    provenance: observed
    source: >-
      services-accounting:modules/transactions/services/payments/payment-receive.ts;
      services-accounting:modules/transactions/services/payments/payment-reverse.ts;
      services-accounting:modules/transactions/services/refunds/refund-commands.ts;
      services-accounting:modules/transactions/db/payments.table.ts;
      services-accounting:modules/transactions/tests/integration/services/refunds/refunds.integration.spec.js#it
      records it offline: executed, the payment partially_refunded with 1000
      refunded (FC-11, FC-14)
  - from: succeeded
    to: voided
    trigger: cancel collected money
    guard: >-
      A reason and no live source credit are required; processor cancellation
      also requires an unsettled charge.
    side_effects:
      - release live allocations
      - restore invoice debt
    who: Staff with payment-void permission.
    provenance: observed
    source: >-
      services-accounting:modules/transactions/services/payments/payment-receive.ts;
      services-accounting:modules/transactions/services/payments/payment-reverse.ts;
      services-accounting:modules/transactions/services/refunds/refund-commands.ts;
      services-accounting:modules/transactions/db/payments.table.ts;
      services-accounting:modules/transactions/tests/integration/services/payments/payment-reversals.integration.spec.js#it
      reverses the live allocation so the line owes again, and the payment
      item’s facts sum to zero (FC-16)
  - from: succeeded
    to: returned
    trigger: record a check or bank return
    guard: >-
      The method behavior must allow the return kind and a reason must be
      supplied.
    side_effects:
      - release live allocations
      - restore invoice debt
    who: Staff with payment-reverse permission or processor event handling.
    provenance: observed
    source: >-
      services-accounting:modules/transactions/services/payments/payment-receive.ts;
      services-accounting:modules/transactions/services/payments/payment-reverse.ts;
      services-accounting:modules/transactions/services/refunds/refund-commands.ts;
      services-accounting:modules/transactions/db/payments.table.ts;
      services-accounting:modules/transactions/tests/integration/services/payments/payment-reversals.integration.spec.js#it
      refuses a kind the method does not allow (reversal_kind_mismatch): an ACH
      return of a check, a bounced check of a card
  - from: succeeded
    to: charged back
    trigger: record a lost chargeback
    guard: The chargeback dispute must close as lost.
    side_effects:
      - reverse the entire receipt
      - restore invoice debt
    who: Staff with dispute-update permission or processor event handling.
    provenance: observed
    source: >-
      services-accounting:modules/transactions/services/payments/payment-receive.ts;
      services-accounting:modules/transactions/services/payments/payment-reverse.ts;
      services-accounting:modules/transactions/services/refunds/refund-commands.ts;
      services-accounting:modules/transactions/db/payments.table.ts;
      services-accounting:modules/transactions/tests/integration/services/payments/dispute-inquiry-lost.integration.spec.js#it
      writes no payment reversal and leaves the payment succeeded, nothing
      reversed
invalid:
  - from: voided
    to: succeeded
    why: >-
      Cancelled, returned and charged-back receipts remain retained without
      revival.
  - from: charged back
    to: refunded
    why: A chargeback leaves no money available for a refund.
  - from: returned
    to: voided
    why: A second nonfailed reversal is prohibited on an already returned receipt.
concurrency: >-
  Database bounds coordinate allocations, refunds, credits and reversals against
  the receipt value. Final reversal requires its live allocations to have been
  removed.
invariants:
  - INV-DOM-ACC-TRX-003-04
  - INV-DOM-ACC-TRX-003-05
  - INV-DOM-ACC-TRX-003-11
  - INV-DOM-ACC-TRX-003-12
evidence:
  - >-
    services-accounting at f47cb263: services/payments/payment-receive.ts,
    payment-reverse.ts; services/refunds/refund-commands.ts;
    db/payments.table.ts, payment-vocabularies.ts;
    docs/architecture/accounting-2.0/05-lifecycles.md §2.
---
# Payment lifecycle

## The Lifecycle

Receipt status distinguishes collection and bank clearing from the use or return of received money. Refund statuses are database-derived, while explicit reversal commands establish return outcomes.

```mermaid
stateDiagram-v2
  direction LR
  state "not created" as s0
  state "succeeded" as s1
  state "pending settlement" as s2
  state "partially refunded" as s3
  state "refunded" as s4
  state "voided" as s5
  state "returned" as s6
  state "charged back" as s7
  s0 --> s1 : record received money
  s0 --> s2 : record an accepted bank debit
  s2 --> s1 : confirm bank clearing
  s2 --> s6 : record an unsuccessful bank debit
  s1 --> s3 : return part of the receipt
  s3 --> s4 : return the remaining receipt
  s1 --> s4 : return the whole receipt
  s1 --> s5 : cancel collected money
  s1 --> s6 : record a check or bank return
  s1 --> s7 : record a lost chargeback
```

## Transitions Explained

The transition rows identify the initiating action, eligibility checks, resulting records and responsible caller. They retain the pinned evidence for each path.

## What Cannot Happen

The invalid-transition rows describe final-state protection and unsupported paths; command eligibility remains distinct from the declared state vocabulary.

## Concurrency and Timing

Database bounds coordinate allocations, refunds, credits and reversals against the receipt value. Final reversal requires its live allocations to have been removed. Bank clearing may follow an integration event or scheduled lookup; offline receipts and card capture do not wait for that transition.
