---
id: CAP-ACC-REC-013
title: Reverse an approved explanation and prepare its replacement
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-007
source_sha:
  services-accounting: f47cb263875bbc0c5640fba7dae6785ec32695f8
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
intent_sources:
  - 'services-accounting:docs/milestones/plans/ACCT-M8-plan.md#D1'
  - 'services-accounting:docs/milestones/plans/ACCT-M8-plan.md#D6 (architecture §3.4 U8)'
  - >-
    services-accounting:docs/milestones/plans/ACCT-M8-plan.md#D10 (§4: the architecture §6 invariants hold;
    INV-08, INV-16)
purpose: Approvers need an accountable way to correct finalized reconciliation work.
outcomes:
  - Correction preserves the earlier approved record.
  - Closed-period reversal retains independent approval.
  - The replacement becomes the payout’s current explanation.
concepts:
  - CON-ACC-REC-003
actors:
  - ACT-ACC-018
surfaces:
  - console
  - api
preconditions: []
postconditions: []
permissions:
  - key: accounting.reconciliation-batches.reverse
    where_checked: api
    scope: tenant
  - key: accounting.reconciliation-batches.reverse
    where_checked: console
    scope: tenant
rules:
  - id: BR-CAP-ACC-REC-013-01
    proved_by: [ATS-ACC-REC-013-01, TST-ACC-REC-036, TST-ACC-REC-095]
    statement: Correction of a finalized reconciliation uses reversal rather than reopening or editing.
    kind: policy
    enforced_at:
      - service
      - database
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/reconciliation/tests/integration/db/reconciliation-batches.table.integration.spec.js#refuses
      to reopen a finalized batch;
      services-accounting:modules/reconciliation/tests/unit/rules/transitions.spec.js#refuses open as
      batch-reopen-not-offered
    origin: 'services-accounting:docs/milestones/plans/ACCT-M8-plan.md#D1'
  - id: BR-CAP-ACC-REC-013-02
    proved_by: [ATS-ACC-REC-013-02, TST-ACC-REC-023, TST-ACC-REC-052]
    statement: >-
      Reversal requires a reason, key and current version of a finalized record, and another fresh-key
      reversal fails after completion.
    kind: validation
    enforced_at:
      - api
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/reverse-batch.integration.spec.js#refuses
      a second reversal under another key, naming the state (DEF-ACT-0596);
      services-accounting:modules/reconciliation/tests/e2e/batch-lifecycle.e2e.spec.js#refuses a reversal
      without an Idempotency-Key with 400;
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/reverse-batch.integration.spec.js#refuses
      an open batch;
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/reverse-batch.integration.spec.js#records
      the refusal as batch.reverse-refused
    origin: 'services-accounting:docs/milestones/plans/ACCT-M8-plan.md#D1'
  - id: BR-CAP-ACC-REC-013-03
    proved_by: [ATS-ACC-REC-012-08, ATS-ACC-REC-013-03, ATS-ACC-REC-014-12, TST-ACC-REC-028, TST-ACC-REC-052, TST-ACC-REC-091]
    statement: >-
      In an open period, reversal immediately mirrors the outstanding original requests with debit and credit
      swapped in the selected operational batch, marks the reconciliation reversed and releases its holdings
      with the reason.
    kind: lifecycle
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/reverse-batch.integration.spec.js#asks
      for the mirrors of the transfer and the fee, debits and credits swapped, in the unit’s batch on its
      date;
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/reverse-batch.integration.spec.js#answers
      the reversed batch whole;
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/reverse-batch.integration.spec.js#releases
      its claims and payout link with the reason;
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/reverse-batch.integration.spec.js#records
      batch.reversed with its dates, batch and mirrors;
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/reverse-batch.integration.spec.js#reads
      the reversal on the reversed batch itself: reason, requester, approver and time (DEF-ACT-0594);
      services-accounting:modules/reconciliation/tests/unit/rules/posting-plans.spec.js#swaps every line’s
      debit and credit under the transfer’s reverse key;
      services-accounting:modules/reconciliation/tests/e2e/reconciliation-scenario.e2e.spec.js#step 13:
      mirrors every posting of the finalize, debits and credits swapped
    origin: 'services-accounting:docs/milestones/plans/ACCT-M8-plan.md#D1'
  - id: BR-CAP-ACC-REC-013-04
    proved_by: [ATS-ACC-REC-013-04, ATS-ACC-REC-013-11, ATS-ACC-REC-020-12, TST-ACC-REC-036, TST-ACC-REC-052]
    statement: >-
      In a closed period, reversal first records a pending request while preserving finalized state and
      creates no mirrors; a duplicate pending request fails.
    kind: policy
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/reverse-batch.integration.spec.js#records
      the request and leaves the batch finalized, awaiting a second approval;
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/reverse-batch.integration.spec.js#asks
      for no mirror yet;
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/reverse-batch.integration.spec.js#records
      batch.reversal-requested;
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/reverse-batch.integration.spec.js#refuses
      a second request while one awaits approval;
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/reverse-batch.integration.spec.js#refuses
      the requester’s own approval;
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/reverse-batch.integration.spec.js#refuses
      an approval at a stale version;
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/reverse-batch.integration.spec.js#refuses
      the approval: the batch its mirrors would ride in is in a closed period;
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/reverse-batch.integration.spec.js#leaves
      the reversal awaiting approval;
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/reverse-batch.integration.spec.js#answers
      the reversed batch with its approver;
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/reverse-batch.integration.spec.js#dates
      the mirrors on the November batch’s date, the original date their document date;
      services-accounting:modules/reconciliation/tests/integration/db/reconciliation-batches.table.integration.spec.js#refuses
      a reversal approved by the person who requested it
    origin: >-
      services-accounting:docs/milestones/plans/ACCT-M8-plan.md#D1 (a second approver when the month is
      closed)
  - id: BR-CAP-ACC-REC-013-05
    proved_by: [ATS-ACC-REC-013-04, ATS-ACC-REC-013-11, ATS-ACC-REC-020-12, TST-ACC-REC-036, TST-ACC-REC-052]
    statement: >-
      The reversal requester cannot approve, stale approval fails, and missing operational capacity in an open
      period leaves approval pending.
    kind: permission
    enforced_at:
      - service
      - database
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/reverse-batch.integration.spec.js#refuses
      the requester’s own approval;
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/reverse-batch.integration.spec.js#records
      the request and leaves the batch finalized, awaiting a second approval;
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/reverse-batch.integration.spec.js#asks
      for no mirror yet;
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/reverse-batch.integration.spec.js#records
      batch.reversal-requested;
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/reverse-batch.integration.spec.js#refuses
      a second request while one awaits approval;
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/reverse-batch.integration.spec.js#refuses
      an approval at a stale version;
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/reverse-batch.integration.spec.js#refuses
      the approval: the batch its mirrors would ride in is in a closed period;
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/reverse-batch.integration.spec.js#leaves
      the reversal awaiting approval;
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/reverse-batch.integration.spec.js#answers
      the reversed batch with its approver;
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/reverse-batch.integration.spec.js#dates
      the mirrors on the November batch’s date, the original date their document date;
      services-accounting:modules/reconciliation/tests/integration/db/reconciliation-batches.table.integration.spec.js#refuses
      a reversal approved by the person who requested it
    origin: 'services-accounting:docs/milestones/plans/ACCT-M8-plan.md#D1'
  - id: BR-CAP-ACC-REC-013-06
    proved_by: [ATS-ACC-REC-013-04, ATS-ACC-REC-013-11, ATS-ACC-REC-020-12, TST-ACC-REC-036, TST-ACC-REC-052]
    statement: >-
      Approved mirrors use the default-selected operational batch’s open-period date and retain the original
      effect day as document date.
    kind: calculation
    enforced_at:
      - service
    must_prove: true
    provenance: observed
    source: 'services-accounting:modules/reconciliation/services/batch-lifecycle/reverse-batch.ts:completeReversal'
    origin: >-
      services-accounting:docs/milestones/plans/ACCT-M8-plan.md#D10 (§4: the architecture §6 invariants hold;
      INV-16)
  - id: BR-CAP-ACC-REC-013-07
    proved_by: [ATS-ACC-REC-013-05, ATS-ACC-REC-013-10, TST-ACC-REC-028, TST-ACC-REC-052, TST-ACC-REC-091]
    statement: >-
      Released payouts and items can be reconciled again; retained manual entries can receive a subsequent
      numbered recognition after their earlier one was reversed.
    kind: calculation
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/reverse-batch.integration.spec.js#recognises
      the fee under its second key when a new batch reconciles it again;
      services-accounting:modules/reconciliation/tests/unit/rules/posting-plans.spec.js#numbers a second
      recognition after a reversal;
      services-accounting:modules/reconciliation/tests/e2e/reconciliation-scenario.e2e.spec.js#step 13:
      releases the claims, so batch 1042’s captures are outstanding again
    origin: 'services-accounting:docs/milestones/plans/ACCT-M8-plan.md#D1'
  - id: BR-CAP-ACC-REC-013-08
    proved_by: [ATS-ACC-REC-012-08, ATS-ACC-REC-013-03, ATS-ACC-REC-014-12, TST-ACC-REC-028, TST-ACC-REC-052, TST-ACC-REC-091]
    statement: 'The reversed record displays the reason, requester, approval identity and completion time.'
    kind: invariant
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/reverse-batch.integration.spec.js#reads
      the reversal on the reversed batch itself: reason, requester, approver and time (DEF-ACT-0594);
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/reverse-batch.integration.spec.js#answers
      the reversed batch whole;
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/reverse-batch.integration.spec.js#asks
      for the mirrors of the transfer and the fee, debits and credits swapped, in the unit’s batch on its
      date;
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/reverse-batch.integration.spec.js#releases
      its claims and payout link with the reason;
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/reverse-batch.integration.spec.js#records
      batch.reversed with its dates, batch and mirrors;
      services-accounting:modules/reconciliation/tests/unit/rules/posting-plans.spec.js#swaps every line’s
      debit and credit under the transfer’s reverse key;
      services-accounting:modules/reconciliation/tests/e2e/reconciliation-scenario.e2e.spec.js#step 13:
      mirrors every posting of the finalize, debits and credits swapped
    origin: none
  - id: BR-CAP-ACC-REC-013-09
    proved_by: [ATS-ACC-REC-013-06, TST-ACC-REC-052]
    statement: >-
      A reversal without an accepting open batch rolls back completely, retaining finalized state, version and
      holdings with no mirror or refusal event.
    kind: invariant
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/reverse-batch.integration.spec.js#writes
      nothing: the batch finalized at its version, its claims held, no mirror, no event;
      services-accounting:modules/reconciliation/tests/integration/services/batch-lifecycle/reverse-batch.integration.spec.js#refuses
      the reversal: no open batch takes its mirrors
    origin: none
  - id: BR-CAP-ACC-REC-013-10
    proved_by: [ATS-ACC-REC-013-07, TST-ACC-REC-023, TST-ACC-REC-028]
    statement: The sensitive reverse permission controls both the request and its second-person approval.
    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.reverse with 403;
      services-accounting:modules/reconciliation/tests/e2e/reconciliation-scenario.e2e.spec.js#step 13:
      refuses the reverse to a user without accounting.reconciliation-batches.reverse with 403
    origin: 'services-accounting:docs/milestones/plans/ACCT-M8-plan.md#D10 (§2: permissions)'
  - id: BR-CAP-ACC-REC-013-11
    proved_by: []
    statement: >-
      Console reversal asks for a reason, shows pending approval, offers approval and lets staff start another
      reconciliation after reversal.
    kind: policy
    enforced_at:
      - console
    must_prove: false
    provenance: observed
    source: 'react-console:components/accounting/reconciliation/workspace/workspace.tsx:ReconWorkspace'
    origin: 'services-accounting:docs/milestones/plans/ACCT-M8-plan.md#D6 (architecture §3.4 U8)'
scenarios:
  - id: SC-CAP-ACC-REC-013-01
    given: An approved explanation has the wrong reserve amount in an open period.
    when: Reverse and prepare the deposit’s corrected explanation.
    then: Mirrored accounting releases the original holdings and permits the replacement to finalize.
    provenance: test
    source: >-
      services-accounting:modules/reconciliation/tests/e2e/reconciliation-scenario.e2e.spec.js#step 13:
      reconciles PX-1083 again in a new batch and finalizes it
  - id: SC-CAP-ACC-REC-013-02
    given: The original explanation belongs to a closed period.
    when: Request reversal and obtain independent approval with an accepting November batch.
    then: Mirrors wait for approval and then use November accounting dates.
    provenance: test
    source: >-
      services-accounting:modules/reconciliation/tests/e2e/batch-lifecycle.e2e.spec.js#answers 200 with the
      reversed batch to another person’s approval once the unit has a November batch
edge_cases:
  - id: SC-CAP-ACC-REC-013-03
    given: The caller lacks reversal authority.
    when: Submit reversal.
    then: Authorization refuses it.
    provenance: test
    source: >-
      services-accounting:modules/reconciliation/tests/e2e/reconciliation-scenario.e2e.spec.js#step 13:
      refuses the reverse to a user without accounting.reconciliation-batches.reverse with 403
constraints: []
depends_on:
  - CAP-ACC-REC-011
  - CAP-ACC-REC-014
related:
  - CAP-ACC-REC-008
  - CAP-ACC-REC-018
journeys:
  - JNY-ACC-REC-003
open_questions: []
evidence:
  - >-
    Examined supporting service material: batch-lifecycle.routes.ts (reverseReconciliationBatch,
    approveReconciliationBatchReversal), services/batch-lifecycle/reverse-batch.ts,
    persistence/reconciliation-batch-lifecycles.ts, rules/posting-plans.ts (mirrors and keys),
    rules/transitions.ts; tests integration reverse-batch.integration.spec.js, finalize-posts-to-subledger
    (reversal in the same batch), db reconciliation-batches table spec, unit posting-plans and transitions,
    e2e batch-lifecycle and scenario steps 13.
  - >-
    Examined supporting console material: components/accounting/reconciliation/workspace/workspace.tsx;
    lib/accounting/reconciliation/store.tsx (reverseRecon, approveReversal, startNewRecon); acceptance
    journeys ACT-ACC-0600, ACT-ACC-0601.
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-005, TC-AZ-006, TC-TEN-001, TC-TEN-002, TC-TEN-003, TC-DAT-001, TC-LOG-001, 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-02, FAS-ACC-REC-03-03, FAS-ACC-REC-03-04, FAS-ACC-REC-03-05, FAS-ACC-REC-07-02, FAS-ACC-REC-07-03]
suites: [TST-ACC-REC-023, TST-ACC-REC-028, TST-ACC-REC-036, TST-ACC-REC-052, TST-ACC-REC-091, TST-ACC-REC-095]
---

# Reverse an approved explanation and prepare its replacement

## Purpose

Approvers need an accountable way to correct finalized reconciliation work.

## How It Works

The approver records why the approved explanation is wrong. Rhythm evaluates the period and either completes reversal or records a request for independent approval. Accounting mirrors preserve the original effect while undoing its requested consequence. Released money can then be explained in another reconciliation. Missing operational capacity leaves the old explanation or pending request intact.

## Relationships

Finalization creates the protected record, ledger requests carry its mirrors and readiness reports unfinished reversal approval.
