---
id: WF-ACC-TRX-002
title: 'Amend, re-date or void an issued invoice before posting'
trigger: >-
  Staff correct an issued invoice through amendment, date or detail changes, or
  cancellation.
product_area: accounting
module: transactions
revision: 1
status: draft
design_intent: confirmed
origin: >-
  Andrew’s A-14 and A-4 (2026-10-18),
  services-accounting:docs/architecture/accounting-2.0/02-decisions.md#2.8
  Andrew's acceptance decisions of 2026-10-18 (about 15:35 UTC)
implementation_evidence: observed
inference: []
source_sha:
  services-accounting: f47cb263875bbc0c5640fba7dae6785ec32695f8
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
implements:
  - CAP-ACC-TRX-002
  - CAP-ACC-TRX-015
moves:
  - STATE-ACC-TRX-001
crosses:
  - SVC-ACC-TRX-transactions
hops:
  - 'n': 1
    actor_or_service: Transactions API
    action: >-
      Authorize amendment, detail correction or cancellation under the
      corresponding invoice permission.
    anchor: >-
      services-accounting:modules/transactions/aws/api/invoices.routes.ts:amendInvoice
    seam: sync
    on_failure: Deny the request as unauthorized.
    left_inconsistent: The command has persisted no effects.
    observer: The API response reports the outcome and applicable refusal code.
    provenance: observed
    source: >-
      services-accounting:modules/transactions/aws/api/invoices.routes.ts:amendInvoice;
      services-accounting:modules/transactions/tests/e2e/invoices.e2e.spec.js#it
      is refused POST /invoices/{tenantId}/{id}/void without
      accounting.invoices.void (403)
  - 'n': 2
    actor_or_service: Invoice commands
    action: >-
      Check record protection and the specific edit guard, requiring unposted
      batching for amendment, cancellation and document or accounting dates.
    anchor: >-
      services-accounting:modules/transactions/services/invoices/invoice-commands.ts
    seam: sync
    on_failure: Reject the change with the applicable batch or record-protection reason.
    left_inconsistent: The complete transaction is undone.
    observer: The API response reports the outcome and applicable refusal code.
    provenance: observed
    source: >-
      services-accounting:modules/transactions/services/invoices/invoice-changes.ts:changeHeader
  - 'n': 3
    actor_or_service: Invoice amendment
    action: >-
      Change only eligible charges, recompute affected tax, advance revision and
      record the financial difference.
    anchor: >-
      services-accounting:modules/transactions/services/invoices/invoice-amendments.ts:amendInvoice
    seam: sync
    on_failure: Reject modification of the protected line and undo the transaction.
    left_inconsistent: The complete transaction is undone.
    observer: The API response reports the outcome and applicable refusal code.
    provenance: observed
    source: >-
      services-accounting:modules/transactions/services/invoices/invoice-amendments.ts:amendInvoice;
      services-accounting:modules/transactions/tests/integration/services/document-edits/reassign-and-edit.integration.spec.js#it
      writes the amended facts for the delta, the originals untouched, and the
      amend event with the delta
  - 'n': 4
    actor_or_service: Detail and date edits
    action: >-
      Apply validated detail and terms changes together, recording old-date
      offsets and new-date effects when the invoice date changes.
    anchor: >-
      services-accounting:modules/transactions/services/invoices/invoice-changes.ts:updateDetails
    seam: sync
    on_failure: Any invalid field rejects the complete edit.
    left_inconsistent: The complete transaction is undone.
    observer: The API response reports the outcome and applicable refusal code.
    provenance: observed
    source: >-
      services-accounting:modules/transactions/services/invoices/invoice-changes.ts:updateDetails;
      services-accounting:modules/transactions/tests/integration/services/invoices/details-terms-due-date.integration.spec.js#it
      leaves the memo, the terms, the due date and the version as they were
  - 'n': 5
    actor_or_service: Invoice void
    action: >-
      Cancel an unapplied invoice with a reason, retaining its amounts and
      offsetting recognised debt today.
    anchor: >-
      services-accounting:modules/transactions/services/invoices/invoice-changes.ts:voidInvoice
    seam: sync
    on_failure: Reject cancellation while an application or adjustment exists.
    left_inconsistent: The complete transaction is undone.
    observer: The API response reports the outcome and applicable refusal code.
    provenance: observed
    source: >-
      services-accounting:modules/transactions/services/invoices/invoice-changes.ts:voidInvoice;
      services-accounting:modules/transactions/tests/integration/services/invoices/void.integration.spec.js#it
      is refused invoice_has_money_applied, the invoice unchanged
idempotency: Each financial correction keeps a keyed response for matching retries.
concurrency: >-
  Invoice locking coordinates correction with financial applications to the same
  billed lines.
branches:
  - >-
    Posted batching prevents amendment, cancellation and accounting-date
    correction; text, terms and due dates retain their separate edit checks.
waits: []
evidence:
  - >-
    services-accounting at f47cb263: services/invoices/invoice-amendments.ts,
    invoice-changes.ts, invoice-commands.ts;
    services/document-edits/detail-edits.ts.
  - >-
    react-console at baf6dae3:
    components/accounting/invoices/adjust-invoice-screen.tsx;
    lib/accounting/transactions/http/http-service.ts (the adjustment calls not
    connected).
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-002, TC-DAT-003, TC-LOG-002, TC-LOG-003, TC-LOG-004, TC-LOG-005, TC-PI-001, TC-PI-002, TC-PI-003, TC-PI-005, TC-PRV-001, TC-PRV-002]
---
# Amend, re-date or void an issued invoice before posting

## What It Does

Correction separates amendments to unposted commercial content from descriptive changes and final cancellation. The console amendment route remains disconnected.

## The Flow

```mermaid
flowchart TD
  h0["Transactions API"]
  h1["Invoice commands"]
  h0 --> h1
  h2["Invoice amendment"]
  h1 --> h2
  h3["Detail and date edits"]
  h2 --> h3
  h4["Invoice void"]
  h3 --> h4
```

The numbered hops identify the participating services, synchronization boundary and evidence. Branch conditions in the frontmatter explain where preparation, completion and recovery diverge.

## When Something Fails

Each hop records its rollback, retry or compensation boundary and the result visible to callers or operators. External outcomes can remain unresolved after local preparation commits; the listed recovery behavior defines what remains pending.

## Open Design Questions

Andrew already permitted revision-based amendment; the outstanding question is how to deliver the staff surface, without re-deciding that approval.
