---
id: WF-ACC-TRX-001
title: Create and issue an invoice
trigger: >-
  Staff prepare customer billing, or Commerce requests an order invoice through
  its billing capability.
product_area: accounting
module: transactions
revision: 1
status: draft
design_intent: proposed
implementation_evidence: observed
inference: []
source_sha:
  services-accounting: f47cb263875bbc0c5640fba7dae6785ec32695f8
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
implements:
  - CAP-ACC-TRX-001
  - CAP-ACC-TRX-020
moves:
  - STATE-ACC-TRX-001
crosses:
  - SVC-ACC-TRX-transactions
hops:
  - 'n': 1
    actor_or_service: Transactions API
    action: >-
      Parse validation, retry context and caller metadata, converting requested
      amounts into minor units.
    anchor: >-
      services-accounting:modules/transactions/aws/api/invoices.routes.ts:createInvoiceDraft
    seam: sync
    on_failure: Return the collected validation problems with a bad-request response.
    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:createInvoiceDraft;
      services-accounting:modules/transactions/tests/integration/services/invoices/create-draft.integration.spec.js#it
      refuses an inactive product (product_not_sellable)
  - 'n': 2
    actor_or_service: Invoice drafts
    action: >-
      Save the prepared header and charges after product, currency and terms
      checks and select the fee policy.
    anchor: >-
      services-accounting:modules/transactions/services/invoices/invoice-drafts.ts:createDraft
    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/invoices/invoice-drafts.ts:createDraft;
      services-accounting:modules/transactions/tests/integration/services/invoices/customer-terms-precedence.integration.spec.js#it
      takes the bill-to’s default terms when the request names none, the due
      date 45 days after the invoice date
  - 'n': 3
    actor_or_service: Number allocation
    action: >-
      After issue validation has chosen tax and accounting context, allocate the
      invoice number in an independently committed short transaction, retrying a
      collision.
    anchor: >-
      services-accounting:modules/transactions/services/invoices/invoice-issue.ts:issueInvoice
    seam: sync
    on_failure: Reject invoice issuance.
    left_inconsistent: Independent sequence allocation may retain an unused number.
    observer: No operator action is required for a permitted sequence gap.
    provenance: observed
    source: >-
      services-accounting:modules/transactions/services/invoices/invoice-issue.ts:issueInvoice;
      services-accounting:modules/transactions/tests/integration/services/invoices/issue.integration.spec.js#it
      numbers the tenant’s first invoice 1,000,000
  - 'n': 4
    actor_or_service: Invoice issue
    action: >-
      Lock the preparation, resolve tax and mandatory service periods, select
      real-invoice accounting context and exchange rate, then number and
      recognise it.
    anchor: >-
      services-accounting:modules/transactions/services/invoices/invoice-issue.ts:issueInvoice
    seam: sync
    on_failure: >-
      Undo issuance and any draft created by the same request; sequence
      allocation can survive a later failure as a numbering gap.
    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-issue.ts:issueInvoice;
      services-accounting:modules/transactions/tests/integration/services/invoices/issue.integration.spec.js#it
      refuses the issue when the unit has no assignment rules (batch_required),
      the draft unchanged
  - 'n': 5
    actor_or_service: Receivable facts and history
    action: >-
      Record the line-level issued receivables and issue history with the
      financial transaction.
    anchor: >-
      services-accounting:modules/transactions/services/invoices/invoice-issue.ts:issueInvoice
    seam: sync
    on_failure: Undo the issuance 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-issue.ts:issueInvoice;
      services-accounting:modules/transactions/tests/integration/services/invoices/as-of.integration.spec.js#it
      answers, as of today and known now, exactly the live balance of every open
      invoice (FC-07)
  - 'n': 6
    actor_or_service: Change-event capture and dispatcher
    action: >-
      Capture inserted financial facts at commit and request subsequent
      change-event dispatch.
    anchor: >-
      services-accounting:aws/accounting.change-events.ts:accountingChangeEventStreams
    seam: event
    on_failure: Retain captured delivery work for the next dispatcher attempt.
    left_inconsistent: Commerce may not yet reflect the issued receivable.
    observer: Delivery diagnostics appear in change-event dispatch logs.
    provenance: documented
    source: 'services-accounting:docs/accounting/change-events.md#Change events'
idempotency: >-
  Separate creation and issue requests each use their own keyed result. Matching
  retries return the saved invoice; changed bodies are refused. Combined
  creation and issue uses a single transactional keyed command.
concurrency: >-
  Draft version checks protect replacement; row locking and lifecycle rechecks
  ensure competing issue requests cannot both issue the bill.
branches:
  - >-
    A quotation retains its number and tax determination without batch or
    recognition protection until conversion.
  - Zero billed value produces paid status on issue.
  - >-
    Taxable staff billing without the required address is rejected during
    validation.
waits: []
evidence:
  - >-
    services-accounting at f47cb263: aws/api/invoices.routes.ts;
    services/invoices/invoice-drafts.ts, invoice-issue.ts, invoice-tax.ts,
    invoice-service-periods.ts; services/batches-for-documents.ts;
    aws/accounting.service-functions.ts (billing).
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-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-AVL-001, TC-AVL-004, TC-MON-001, TC-MON-002, TC-MON-004, TC-PI-001, TC-PI-002, TC-PI-003, TC-PI-004, TC-PI-005, TC-PRV-001, TC-PRV-002]
---
# Create and issue an invoice

## What It Does

This flow turns prepared charges into a customer bill and publishes its financial effects. Independent numbering and asynchronous sharing have different failure boundaries.

## The Flow

```mermaid
flowchart TD
  h0["Transactions API"]
  h1["Invoice drafts"]
  h0 --> h1
  h2["Number allocation"]
  h1 --> h3
  h3["Invoice issue"]
  h3 --> h2
  h4["Receivable facts and history"]
  h2 --> h4
  h5["Change-event capture and dispatcher"]
  h4 --> h5
```

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

Resolve the staff-billing tax path and the precise protection expected for issued quotations before treating the design as approved.
