---
id: CAP-ACC-BAT-016
title: Unpost a batch for correction and replacement posting
feature: FEAT-ACC-BAT-03
product_area: accounting
module: batches
revision: 1
status: draft
product_intent: proposed
implementation_evidence: observed
supersedes:
- inventory CAP-ACC-BAT-010
- inventory RUL-ACC-BAT-027
source_sha:
  services-accounting: f47cb263875bbc0c5640fba7dae6785ec32695f8
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
intent_sources:
- services-accounting:docs/accounting/batches.md#Unposting deletes the entries (Andrew, Reporting D7, 2026-10-21)
- services-accounting:docs/architecture/accounting-2.0/02-decisions.md#A-4
purpose: Administrators reopen posted work for correction while retaining the record of the earlier posting.
outcomes:
- Eligible ordinary recovery removes the current ledger result while preserving posting history.
concepts:
- CON-ACC-BAT-003
- CON-ACC-BAT-004
actors:
- ACT-ACC-006
surfaces:
- console
- api
- job
permissions:
- key: accounting.batch-postings.unpost
  where_checked: api
  scope: tenant
rules:
- id: BR-CAP-ACC-BAT-016-01
  proved_by: [ATS-ACC-BAT-016-01, TST-ACC-BAT-027, TST-ACC-BAT-055, TST-ACC-BAT-057, TST-ACC-BAT-119]
  statement: Unposting needs the administrator unposting permission, which the ordinary posting staff tier does
    not grant.
  kind: permission
  enforced_at:
  - api
  - console
  must_prove: true
  provenance: test
  source: services-accounting:modules/batches/tests/e2e/batch-postings.e2e.spec.js#refuses an unposting without
    the unposting permission, 403, and leaves the batch posted
  origin: none
  note: The cited product record confirms a narrower policy; this full rule includes implementation details without
    a matching recorded decision and inherits proposed intent.
- id: BR-CAP-ACC-BAT-016-02
  proved_by: [ATS-ACC-BAT-016-01, ATS-ACC-BAT-016-15, TST-ACC-BAT-027, TST-ACC-BAT-055, TST-ACC-BAT-057, TST-ACC-BAT-096, TST-ACC-BAT-119]
  statement: Unpost admits Posted, Downloaded and posting work unchanged for more than one hour.
  kind: lifecycle
  enforced_at:
  - service
  must_prove: true
  provenance: test
  source: services-accounting:modules/batches/tests/e2e/batch-actions.e2e.spec.js#refuses unposting a batch that
    is not posted 409
  origin: none
- id: BR-CAP-ACC-BAT-016-03
  proved_by: [ATS-ACC-BAT-016-02, ATS-ACC-BAT-016-12, ATS-ACC-BAT-016-13, ATS-ACC-BAT-017-08, ATS-ACC-BAT-018-07, TST-ACC-BAT-017, TST-ACC-BAT-057, TST-ACC-BAT-076, TST-ACC-BAT-092, TST-ACC-BAT-094, TST-ACC-BAT-112]
  statement: Ordinary unposting deletes the current posting’s entries and lines without creating reversals or removing
    another batch’s entries.
  kind: lifecycle
  enforced_at:
  - service
  - database
  must_prove: true
  provenance: test
  source: services-accounting:modules/batches/tests/integration/services/posting/unpost-deletes-entries.integration.spec.js#deletes
    the batch’s entries and their lines, and tells how many entries
  origin: services-accounting:docs/accounting/batches.md#Unposting deletes the entries (Andrew, Reporting D7, 2026-10-21)
- id: BR-CAP-ACC-BAT-016-04
  proved_by: [ATS-ACC-BAT-016-02, TST-ACC-BAT-017, TST-ACC-BAT-057, TST-ACC-BAT-076, TST-ACC-BAT-092, TST-ACC-BAT-094, TST-ACC-BAT-112]
  statement: The posting remains marked reversed with the unposting time and job, and retained job history preserves
    who acted and when.
  kind: invariant
  enforced_at:
  - service
  must_prove: true
  provenance: test
  source: 'services-accounting:modules/batches/tests/integration/services/posting/unpost-deletes-entries.integration.spec.js#keeps
    the posting history: the first posting reversed, the second current'
  origin: services-accounting:docs/accounting/batches.md#Unposting deletes the entries (Andrew, Reporting D7, 2026-10-21)
- id: BR-CAP-ACC-BAT-016-05
  proved_by: [ATS-ACC-BAT-016-02, TST-ACC-BAT-017, TST-ACC-BAT-057, TST-ACC-BAT-076, TST-ACC-BAT-092, TST-ACC-BAT-094, TST-ACC-BAT-112]
  statement: Unposting voids the posting’s open revenue-recognition schedules.
  kind: lifecycle
  enforced_at:
  - service
  must_prove: true
  provenance: test
  source: services-accounting:modules/batches/tests/integration/services/persistence/revenue-recognition-schedules.queries.integration.spec.js#reads
    the current schedule by its id, and none once its posting is not the current one
  origin: services-accounting:docs/accounting/batches.md#Unposting deletes the entries (Andrew, Reporting D7, 2026-10-21)
- id: BR-CAP-ACC-BAT-016-06
  proved_by: [ATS-ACC-BAT-002-09, ATS-ACC-BAT-004-13, ATS-ACC-BAT-007-11, ATS-ACC-BAT-016-02, ATS-ACC-BAT-016-08, ATS-ACC-BAT-016-09, ATS-ACC-BAT-016-10, TST-ACC-BAT-017, TST-ACC-BAT-057, TST-ACC-BAT-076, TST-ACC-BAT-092, TST-ACC-BAT-094, TST-ACC-BAT-112]
  statement: The batch returns to Open with posting time, statistics and dependents cleared so its documents can
    be corrected or reassigned.
  kind: lifecycle
  enforced_at:
  - service
  must_prove: true
  provenance: test
  source: 'services-accounting:modules/batches/tests/e2e/batch-postings.e2e.spec.js#unposts a posted batch as a
    durable job: the batch is open again and its entries are deleted'
  origin: services-accounting:docs/accounting/batches.md#Unposting deletes the entries (Andrew, Reporting D7, 2026-10-21)
- id: BR-CAP-ACC-BAT-016-07
  proved_by: [ATS-ACC-BAT-016-03, TST-ACC-BAT-105]
  statement: A Posted or Downloaded dependent prevents unposting unless that dependent is included in the same unposting
    request.
  kind: invariant
  enforced_at:
  - service
  must_prove: true
  provenance: observed
  source: services-accounting:modules/batches/services/rules/batch-posting-rules.ts:ensureBatchesCanBeUnposted
  origin: services-accounting:docs/architecture/accounting-2.0/02-decisions.md#A-4
- id: BR-CAP-ACC-BAT-016-08
  proved_by: [ATS-ACC-BAT-016-04, ATS-ACC-BAT-016-14, ATS-ACC-BAT-020-09, TST-ACC-BAT-010, TST-ACC-BAT-070]
  statement: Unposting is refused outside an Open fiscal period.
  kind: validation
  enforced_at:
  - service
  must_prove: true
  provenance: test
  source: services-accounting:modules/batches/tests/integration/services/close/posting-period-guard.integration.spec.js#refuses
    the batch action `unpost` (`period_not_open`), submitting no job
  origin: services-accounting:docs/architecture/accounting-2.0/02-decisions.md#A-4
- id: BR-CAP-ACC-BAT-016-09
  proved_by: [ATS-ACC-BAT-013-24, ATS-ACC-BAT-016-05, ATS-ACC-BAT-016-11, TST-ACC-BAT-057, TST-ACC-BAT-105, TST-ACC-BAT-112]
  statement: Reposting creates a fresh current posting and entry set and writes fresh line snapshots.
  kind: lifecycle
  enforced_at:
  - service
  must_prove: true
  provenance: test
  source: services-accounting:modules/batches/tests/integration/services/posting/unpost-deletes-entries.integration.spec.js#writes
    one fresh set when the batch is posted again, equal in size to the first
  origin: services-accounting:docs/accounting/batches.md#Unposting deletes the entries (Andrew, Reporting D7, 2026-10-21)
- id: BR-CAP-ACC-BAT-016-10
  proved_by: [ATS-ACC-BAT-016-06, ATS-ACC-BAT-016-15, TST-ACC-BAT-096, TST-ACC-BAT-112, TST-ACC-BAT-113]
  statement: A refused guarded deletion preserves batch, posting and entries and fails the job, and rejects postings
    already reversed, containing reversal entries or belonging to another workspace.
  kind: invariant
  enforced_at:
  - service
  - database
  must_prove: true
  provenance: test
  source: services-accounting:modules/batches/tests/integration/services/posting/unpost-refusal.integration.spec.js#keeps
    the posting, its entries and the batch as they were, and fails the unposting step with the refusal
  origin: none
- id: BR-CAP-ACC-BAT-016-11
  proved_by: [ATS-ACC-BAT-016-07, TST-ACC-BAT-063, TST-ACC-BAT-074, TST-ACC-BAT-076]
  statement: Update-locked and system batches reject ordinary unposting through either actions or jobs.
  kind: policy
  enforced_at:
  - service
  must_prove: true
  provenance: test
  source: services-accounting:modules/batches/tests/e2e/system-batches.e2e.spec.js#answers an unposting naming the
    system batch with its job, and the job fails with the refusal
  origin: none
scenarios:
- id: SC-CAP-ACC-BAT-016-01
  given: A posted rehearsal batch contains an invoice assigned to the wrong stream.
  when: An administrator unposts, reassigns the invoice and posts the corrected batch.
  then: The ordinary entries disappear on unposting and one fresh set represents the later posting.
  provenance: documented
  source: services-accounting:docs/milestones/walkthroughs/ACCT-M3-handoff.md#Start here (steps 6 and 7)
- id: SC-CAP-ACC-BAT-016-02
  given: A staff caller has posting permission but no unposting permission.
  when: The caller inspects a Posted batch and requests Unpost.
  then: The console omits the unauthorized action and the API refusal preserves the posting.
  provenance: test
  source: react-console:acceptance/accounting/playwright/journeys/batches-posting/ACT-ACC-0540.spec.ts#ACT-ACC-0540
edge_cases: []
constraints:
- Fiscal reopening retains a separate system-batch reversal path.
depends_on:
- CAP-ACC-BAT-013
related:
- CAP-ACC-BAT-007
- CAP-ACC-BAT-017
- CAP-ACC-BAT-020
journeys:
- JNY-ACC-BAT-002
open_questions: []
evidence:
- 'Pinned services-accounting (f47cb263), examined sources: aws/api/batch-postings.routes.ts (unpostBatches), services/actions/batch-actions.ts
  (unpostBatch), services/engine/unpost-batches.ts, services/rules/batch-posting-rules.ts, services/persistence/ledger-records.ts
  (deleteBatchPostingEntries), services/persistence/batch-postings.ts; tests e2e/batch-postings.e2e.spec.js, integration/services/posting/unpost-deletes-entries.integration.spec.js,
  unpost-refusal.integration.spec.js, rebuilt-documents.integration.spec.js, concurrent-posting.integration.spec.js,
  integration/services/close/posting-period-guard.integration.spec.js, integration/services/jobs/batch-posting-record.integration.spec.js;
  docs/accounting/batches.md (Reporting D7).'
- 'Pinned react-console (baf6dae3), examined sources: components/accounting/batches/batch-detail-screen.tsx, batch-posting-panel.tsx,
  batch-entries-tab.tsx; journeys ACT-ACC-0527, 0540.'
controls: [TC-IAM-001, TC-IAM-002, TC-IAM-004, TC-IAM-005, 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-CRY-004, TC-DAT-001, TC-DAT-004, 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-BAT-03-03, FAS-ACC-BAT-03-04, FAS-ACC-BAT-03-05, FAS-ACC-BAT-04-03]
suites: [TST-ACC-BAT-010, TST-ACC-BAT-017, TST-ACC-BAT-027, TST-ACC-BAT-055, TST-ACC-BAT-057, TST-ACC-BAT-063, TST-ACC-BAT-070, TST-ACC-BAT-074, TST-ACC-BAT-076, TST-ACC-BAT-092, TST-ACC-BAT-094, TST-ACC-BAT-096, TST-ACC-BAT-105, TST-ACC-BAT-112, TST-ACC-BAT-113, TST-ACC-BAT-119]
---

# Unpost a batch for correction and replacement posting

## Purpose

Administrators reopen posted work for correction while retaining the record of the earlier posting.

## How It Works

An administrator chooses Unpost and confirms the accounting removal. The action or job checks the batch, fiscal period and dependent work. The current ordinary posting’s ledger entries are then removed within the transaction. Its posting record and job history remain available. Staff can correct or reassign the reopened documents before posting again. A guarded-deletion refusal leaves the prior accounting intact and fails the job.

## Relationships

- Prerequisite: Run and monitor a batch posting job, which addresses the connected batch work.
- Related outcome: Place documents in eligible batches and protect posted work, which addresses the connected batch work.
- Related outcome: Protect ledger balance, immutability and workspace isolation, which addresses the connected batch work.
- Related outcome: Post and reverse fiscal-close system batches, which addresses the connected batch work.
