---
id: WF-ACC-TRX-012
title: Record and void a remittance
trigger: >-
  Staff use the API to record or cancel a remitter’s offline collection for
  multiple customers.
product_area: accounting
module: transactions
revision: 1
status: draft
design_intent: confirmed
origin: >-
  Andrew’s §2.11 D-09 (remittances in release 1, manual lines, no import),
  services-accounting:docs/architecture/accounting-2.0/02-decisions.md#2.11 The
  payment methods, deferred payment and order collection decisions (Andrew,
  2026-10-18 evening)
implementation_evidence: observed
inference: []
source_sha:
  services-accounting: f47cb263875bbc0c5640fba7dae6785ec32695f8
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
implements:
  - CAP-ACC-TRX-010
moves:
  - STATE-ACC-TRX-009
  - STATE-ACC-TRX-006
  - STATE-ACC-TRX-001
crosses:
  - SVC-ACC-TRX-transactions
hops:
  - 'n': 1
    actor_or_service: Remittance rules
    action: >-
      Validate that total collection reconciles to member amounts and the
      explicit remainder.
    anchor: >-
      services-accounting:modules/transactions/services/remittances/remittance-rules.ts
    seam: sync
    on_failure: Reject totals that do not reconcile.
    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/services/remittances/remittance-rules.ts;
      services-accounting:modules/transactions/tests/integration/services/remittances/remittance-refusals.integration.spec.js#it
      refuses a remainder left unstated: the total of 200.00 over a line of
      180.00 is a mismatch, not an inferred remainder
  - 'n': 2
    actor_or_service: Remittance commands
    action: >-
      Check the offline method and accounting scope, then lock each customer
      invoice in identity order.
    anchor: >-
      services-accounting:modules/transactions/services/remittances/remittance-commands.ts:recordRemittance
    seam: sync
    on_failure: Reject the command and undo its 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/remittances/remittance-commands.ts:recordRemittance;
      services-accounting:modules/transactions/tests/integration/services/remittances/remittance-refusals.integration.spec.js#it
      refuses a line whose stated bill-to is not its invoice’s:
      business_unit_mismatch
  - 'n': 3
    actor_or_service: Payment receive (nested)
    action: >-
      Create keyed member receipts with their intended allocations and retain
      any remainder on a remitter receipt.
    anchor: >-
      services-accounting:modules/transactions/services/payments/payment-receive.ts:receivePayment
    seam: sync
    on_failure: A member refusal undoes the whole set of receipts.
    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/payments/payment-receive.ts:receivePayment;
      services-accounting:modules/transactions/tests/integration/services/remittances/record-remittance.integration.spec.js#it
      allocates each member’s payment wholly to that member’s invoice, and
      leaves the remainder unapplied on Metro Transit
  - 'n': 4
    actor_or_service: Remittance void
    action: >-
      Check every receipt's posting and subsequent use before cancelling the
      group and its associated live receipts together.
    anchor: >-
      services-accounting:modules/transactions/services/remittances/remittance-commands.ts:voidRemittance
    seam: sync
    on_failure: >-
      Reject whole-group cancellation; individual receipt cancellation remains a
      separate action subject to its own guards.
    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/remittances/remittance-commands.ts:voidRemittance;
      services-accounting:modules/transactions/tests/integration/services/remittances/void-remittance.integration.spec.js#it
      voids every payment it made, taking their allocations back and returning
      the remainder
idempotency: >-
  Derived member keys supplement the parent result so repeated delivery does not
  record additional money.
concurrency: >-
  The command retains identity-ordered invoice locks through creation of all
  member receipts.
branches: []
waits: []
evidence:
  - >-
    services-accounting at f47cb263:
    services/remittances/remittance-commands.ts, remittance-rules.ts;
    db/expected-remittances.view.ts.
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-004, TC-LOG-005, TC-PI-001, TC-PI-002, TC-PI-003, TC-PI-005, TC-PRV-001, TC-PRV-002]
---
# Record and void a remittance

## What It Does

Group collection is represented by individual customer receipts beneath a remittance record. Whole-group correction remains available only while those receipts retain their original eligible use.

## The Flow

```mermaid
flowchart TD
  h0["Remittance rules"]
  h1["Remittance commands"]
  h0 --> h1
  h2["Payment receive (nested)"]
  h1 --> h2
  h3["Remittance void"]
  h2 --> h3
```

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

The unresolved matters are recorded in the module findings; this workflow does not establish additional product approval.
