---
id: CAP-ACC-REC-012
title: Abandon a draft and release its money
feature: FEAT-ACC-REC-03
product_area: accounting
module: reconciliation
revision: 2
status: draft
product_intent: confirmed
implementation_evidence: observed
supersedes:
  - react-console acceptance inventory CAP-ACC-REC-006
source_sha:
  services-accounting: f47cb263875bbc0c5640fba7dae6785ec32695f8
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
intent_sources:
  - >-
    services-accounting:docs/milestones/plans/ACCT-M8-plan.md#D10 (§2 scope; journey 0593: voiding the draft
    releases everything)
  - >-
    services-accounting:docs/milestones/plans/ACCT-M8-plan.md#D10 (§4: the architecture §6 invariants hold;
    INV-14)
purpose: Preparers need to cancel an incorrect explanation without leaving the payout or matched money stranded.
outcomes:
  - Abandoned explanations free their payout and matched money.
  - Terminal drafts retain their historical record.
concepts:
  - CON-ACC-REC-003
actors:
  - ACT-ACC-017
  - ACT-ACC-018
surfaces:
  - api
preconditions: []
postconditions: []
permissions:
  - key: accounting.reconciliation-batches.delete
    where_checked: api
    scope: tenant
rules:
  - id: BR-CAP-ACC-REC-012-01
    proved_by: [ATS-ACC-REC-012-01, TST-ACC-REC-023, TST-ACC-REC-053]
    statement: 'Only an open reconciliation can be voided, with a reason and its current version.'
    kind: validation
    enforced_at:
      - api
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/void-batch.integration.spec.js#refuses
      a finalized batch;
      services-accounting:modules/reconciliation/tests/e2e/batch-lifecycle.e2e.spec.js#refuses a void without
      a reason with 400;
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/void-batch.integration.spec.js#refuses
      a stale version;
      services-accounting:modules/reconciliation/tests/e2e/batch-lifecycle.e2e.spec.js#refuses a finalized
      batch with 409
    origin: >-
      services-accounting:docs/milestones/plans/ACCT-M8-plan.md#D10 (plan approved 2026-10-22 10:40 ET; §2
      scope)
  - id: BR-CAP-ACC-REC-012-02
    proved_by: [ATS-ACC-REC-008-14, ATS-ACC-REC-012-02, ATS-ACC-REC-012-08, TST-ACC-REC-053]
    statement: >-
      Void releases claims and payout links with the reason and withdraws its own manual entries, leaving
      matched settlement items unresolved and available.
    kind: lifecycle
    enforced_at:
      - service
      - database
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/void-batch.integration.spec.js#withdraws
      the manual fee and leaves the capture unresolved;
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/void-batch.integration.spec.js#releases
      every claim with the reason;
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/void-batch.integration.spec.js#releases
      the payout link with the reason;
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/void-batch.integration.spec.js#asks
      the ledger for nothing;
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/void-batch.integration.spec.js#records
      batch.voided with the reason and what it released;
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/void-batch.integration.spec.js#frees
      the payout to be linked by another batch
    origin: >-
      services-accounting:docs/milestones/plans/ACCT-M8-plan.md#D10 (plan approved 2026-10-22 10:40 ET; §2
      scope)
  - id: BR-CAP-ACC-REC-012-03
    proved_by: [ATS-ACC-REC-008-14, ATS-ACC-REC-012-02, ATS-ACC-REC-012-08, TST-ACC-REC-053]
    statement: Abandoning an open reconciliation generates no ledger request.
    kind: policy
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/void-batch.integration.spec.js#asks
      the ledger for nothing;
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/void-batch.integration.spec.js#releases
      every claim with the reason;
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/void-batch.integration.spec.js#releases
      the payout link with the reason;
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/void-batch.integration.spec.js#withdraws
      the manual fee and leaves the capture unresolved;
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/void-batch.integration.spec.js#records
      batch.voided with the reason and what it released;
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/void-batch.integration.spec.js#frees
      the payout to be linked by another batch
    origin: >-
      services-accounting:docs/milestones/plans/ACCT-M8-plan.md#D10 (plan approved 2026-10-22 10:40 ET; §2
      scope)
  - id: BR-CAP-ACC-REC-012-04
    proved_by: [ATS-ACC-REC-008-14, ATS-ACC-REC-012-02, ATS-ACC-REC-012-08, TST-ACC-REC-053]
    statement: The released payout can enter another reconciliation or be voided independently.
    kind: lifecycle
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/void-batch.integration.spec.js#frees
      the payout to be linked by another batch;
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/void-batch.integration.spec.js#releases
      every claim with the reason;
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/void-batch.integration.spec.js#releases
      the payout link with the reason;
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/void-batch.integration.spec.js#withdraws
      the manual fee and leaves the capture unresolved;
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/void-batch.integration.spec.js#asks
      the ledger for nothing;
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/void-batch.integration.spec.js#records
      batch.voided with the reason and what it released
    origin: >-
      services-accounting:docs/milestones/plans/ACCT-M8-plan.md#D10 (plan approved 2026-10-22 10:40 ET; §2
      scope); journey 0593
  - id: BR-CAP-ACC-REC-012-05
    proved_by: [ATS-ACC-REC-012-03, TST-ACC-REC-095]
    statement: >-
      The stored lifecycle permits open to finalized or voided and finalized to reversed; reversed and voided
      are terminal.
    kind: lifecycle
    enforced_at:
      - service
      - database
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/reconciliation/tests/unit/rules/transitions.spec.js#refuses voided as
      batch-not-open; services-accounting:modules/reconciliation/tests/unit/rules/transitions.spec.js#allows
      finalized; services-accounting:modules/reconciliation/tests/unit/rules/transitions.spec.js#allows
      voided; services-accounting:modules/reconciliation/tests/unit/rules/transitions.spec.js#allows reversed;
      services-accounting:modules/reconciliation/tests/unit/rules/transitions.spec.js#refuses open as
      batch-terminal; services-accounting:modules/reconciliation/tests/unit/rules/transitions.spec.js#refuses
      finalized as batch-terminal
    origin: 'services-accounting:docs/milestones/plans/ACCT-M8-plan.md#D1 (reverse and redo, never reopen)'
  - id: BR-CAP-ACC-REC-012-06
    proved_by: [ATS-ACC-REC-012-04, TST-ACC-REC-034, TST-ACC-REC-036, TST-ACC-REC-053]
    statement: A voided reconciliation is immutable and retains no active holdings.
    kind: invariant
    enforced_at:
      - database
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/void-batch.integration.spec.js#leaves
      the voided batch sealed (RHF30);
      services-accounting:modules/reconciliation/tests/integration/db/reconciliation-batches.table.integration.spec.js#refuses
      any change to a voided batch;
      services-accounting:modules/reconciliation/tests/integration/db/reconciliation-allocations.table.integration.spec.js#refuses
      a claim into a voided batch
    origin: >-
      services-accounting:docs/milestones/plans/ACCT-M8-plan.md#D10 (§4: the architecture §6 invariants hold;
      INV-08)
  - id: BR-CAP-ACC-REC-012-07
    proved_by: [ATS-ACC-REC-008-14, ATS-ACC-REC-012-02, ATS-ACC-REC-012-08, TST-ACC-REC-053]
    statement: The void event records its explanation and released records.
    kind: lifecycle
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/void-batch.integration.spec.js#records
      batch.voided with the reason and what it released;
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/void-batch.integration.spec.js#releases
      every claim with the reason;
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/void-batch.integration.spec.js#releases
      the payout link with the reason;
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/void-batch.integration.spec.js#withdraws
      the manual fee and leaves the capture unresolved;
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/void-batch.integration.spec.js#asks
      the ledger for nothing;
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/void-batch.integration.spec.js#frees
      the payout to be linked by another batch
    origin: none
  - id: BR-CAP-ACC-REC-012-08
    proved_by: [ATS-ACC-REC-012-05, TST-ACC-REC-023]
    statement: Reconciliation delete permission controls draft abandonment.
    kind: permission
    enforced_at:
      - api
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/reconciliation/tests/e2e/batch-lifecycle.e2e.spec.js#refuses a principal
      without accounting.reconciliation-batches.delete with 403
    origin: 'services-accounting:docs/milestones/plans/ACCT-M8-plan.md#D10 (§2: permissions)'
  - id: BR-CAP-ACC-REC-012-09
    proved_by: []
    statement: The console currently provides no draft-void command.
    kind: policy
    enforced_at:
      - console
    must_prove: false
    provenance: observed
    source: 'react-console:lib/accounting/reconciliation/client.ts:createReconciliationClient'
    origin: none
scenarios:
  - id: SC-CAP-ACC-REC-012-01
    given: 'The open draft holds a payout, capture and manual fee.'
    when: Abandon it with a written reason.
    then: 'Payout and capture are released, the fee is withdrawn and accounting is untouched.'
    provenance: test
    source: >-
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/void-batch.integration.spec.js#answers
      the voided batch whole, holding nothing
edge_cases:
  - id: SC-CAP-ACC-REC-012-02
    given: The explanation has already been finalized.
    when: Attempt void.
    then: Abandonment is refused and correction requires reversal.
    provenance: test
    source: >-
      services-accounting:modules/reconciliation/tests/e2e/batch-lifecycle.e2e.spec.js#refuses a finalized
      batch with 409
constraints: []
depends_on:
  - CAP-ACC-REC-008
related:
  - CAP-ACC-REC-002
  - CAP-ACC-REC-013
journeys:
  - JNY-ACC-REC-002
open_questions: []
evidence:
  - >-
    Examined supporting service material: batch-lifecycle.routes.ts (voidReconciliationBatch),
    services/batch-lifecycle/void-batch.ts, rules/transitions.ts; tests integration
    void-batch.integration.spec.js, db/reconciliation-batches.table.integration.spec.js,
    unit/rules/transitions.spec.js, e2e/batch-lifecycle.e2e.spec.js.
  - >-
    Examined supporting console material: lib/accounting/reconciliation/client.ts (no void call); acceptance
    journey ACT-ACC-0593.
controls: [TC-IAM-001, TC-IAM-002, TC-IAM-004, TC-IAM-005, TC-AZ-001, TC-AZ-002, TC-AZ-003, TC-AZ-004, TC-AZ-006, TC-TEN-001, TC-TEN-002, TC-TEN-003, TC-DAT-001, TC-DAT-004, TC-LOG-002, TC-LOG-003, TC-LOG-004, TC-LOG-005, TC-PI-001, TC-PI-003, TC-PI-005]
exercised_by: [FAS-ACC-REC-03-03, FAS-ACC-REC-03-04]
suites: [TST-ACC-REC-023, TST-ACC-REC-034, TST-ACC-REC-036, TST-ACC-REC-053, TST-ACC-REC-095]
---

# Abandon a draft and release its money

## Purpose

Preparers need to cancel an incorrect explanation without leaving the payout or matched money stranded.

## How It Works

The preparer selects an open draft and supplies the reason for abandonment. Rhythm checks the current version and releases its holdings. Manually introduced entries are withdrawn as part of cancelling that draft. Released payout and payment effects are available for another explanation. A finalized record requires reversal instead, and the current console lacks a draft-void action.

## Relationships

Draft creation supplies the record; payout void can follow release; approved explanations use reversal rather than abandonment.
