---
id: CAP-ACC-TRX-005
title: Prepare and deliver invoice documents
feature: FEAT-ACC-TRX-01
product_area: accounting
module: transactions
revision: 1
status: draft
product_intent: proposed
implementation_evidence: partially-observed
supersedes:
  - CAP-ACC-INV-020
  - CAP-ACC-INV-021
source_sha:
  services-accounting: f47cb263875bbc0c5640fba7dae6785ec32695f8
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
intent_sources:
  - 'services-accounting:docs/architecture/accounting-2.0/02-decisions.md#A-10'
  - 'services-accounting:docs/architecture/accounting-2.0/02-decisions.md#A-11'
  - 'services-accounting:docs/architecture/accounting-2.0/02-decisions.md#M1-7'
purpose: Staff and Commerce give customers a readable account of their billed charges.
outcomes:
  - Staff and Commerce give customers a readable account of their billed charges.
  - >-
    A failed submission leaves no misleading delivery record. The product should expose document delivery on
    the staff invoice page.
concepts:
  - CON-ACC-TRX-001
actors:
  - ACT-ACC-012
  - ACT-ACC-002
  - ACT-ACC-021
surfaces:
  - api
permissions:
  - key: accounting.invoices.read
    where_checked: api
    scope: tenant
  - key: accounting.invoices.email
    where_checked: api
    scope: tenant
rules:
  - id: BR-CAP-ACC-TRX-005-01
    proved_by: [ATS-ACC-TRX-005-01, TST-ACC-TRX-060]
    statement: >-
      Rendering selects the invoice template, then the unit template, then the built-in design; a missing,
      inactive or inappropriate named template is refused.
    kind: policy
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/invoices/render-invoice.integration.spec.js#it
      is the invoice’s own template over its unit’s
    origin: 'services-accounting:docs/milestones/ACCT-M1-books-and-invoices.md#D12'
  - id: BR-CAP-ACC-TRX-005-02
    proved_by: [ATS-ACC-TRX-001-17, ATS-ACC-TRX-005-02, ATS-ACC-TRX-005-07, TST-ACC-TRX-007]
    statement: Each rendering produces fresh HTML from the invoice without retaining a rendered copy.
    kind: policy
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/e2e/invoice-documents.e2e.spec.js#it refuses a format
      other than html: 400
    origin: 'services-accounting:docs/architecture/accounting-2.0/02-decisions.md#A-10'
  - id: BR-CAP-ACC-TRX-005-03
    proved_by: [ATS-ACC-TRX-005-03, TST-ACC-TRX-051]
    statement: E-mail delivery rejects drafts and requires an invoice that has been issued.
    kind: validation
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/invoices/email-invoice.integration.spec.js#it
      refuses a draft: it has no number and no receivable
    origin: 'services-accounting:docs/architecture/accounting-2.0/02-decisions.md#M1-7'
  - id: BR-CAP-ACC-TRX-005-04
    proved_by: [ATS-ACC-TRX-005-03, ATS-ACC-TRX-005-08, TST-ACC-TRX-051]
    statement: >-
      Delivery uses the contact’s primary address unless the sender provides up to ten valid recipients;
      absent recipients prevent sending, including an organization with no explicit recipients.
    kind: validation
    enforced_at:
      - api
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/invoices/email-invoice.integration.spec.js#it
      refuses more than ten addresses: 400
    origin: 'services-accounting:docs/milestones/ACCT-M1-books-and-invoices.md#D12'
  - id: BR-CAP-ACC-TRX-005-05
    proved_by: [ATS-ACC-TRX-005-04, ATS-ACC-TRX-005-07, TST-ACC-TRX-051]
    statement: >-
      Sending requires a distinct retry key, repeats only once under that key and occurs separately from
      invoice creation.
    kind: policy
    enforced_at:
      - api
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/invoices/email-invoice.integration.spec.js#it
      refuses an e-mail without an idempotency key: 400 idempotency_key_required
    origin: 'services-accounting:docs/architecture/accounting-2.0/02-decisions.md#A-11'
  - id: BR-CAP-ACC-TRX-005-06
    proved_by: [ATS-ACC-TRX-001-17, ATS-ACC-TRX-005-05, ATS-ACC-TRX-005-07, TST-ACC-TRX-051]
    statement: >-
      The communication submission and delivery event commit together, with a failed submission leaving
      neither record.
    kind: invariant
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/invoices/email-invoice.integration.spec.js#it
      writes nothing, not even the event, when the sender’s statement fails: the command’s transaction rolls
      back
    origin: 'services-accounting:docs/architecture/accounting-2.0/02-decisions.md#M1-7'
  - id: BR-CAP-ACC-TRX-005-07
    proved_by: [ATS-ACC-TRX-005-06, TST-ACC-TRX-007]
    statement: 'Read authority permits document viewing, while e-mail authority is separately required for sending.'
    kind: permission
    enforced_at:
      - api
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/e2e/invoice-documents.e2e.spec.js#it refuses the e-mail
      to a principal holding only accounting.invoices.read: 403, submitting nothing
    origin: 'services-accounting:docs/milestones/ACCT-M1-books-and-invoices.md#D12'
scenarios:
  - id: SC-CAP-ACC-TRX-005-01
    given: A billed contact has a primary e-mail address.
    when: Send the issued invoice without explicit recipients.
    then: >-
      A communication is submitted for that address with template content and an attachment, and a delivery
      event is recorded.
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/invoices/email-invoice.integration.spec.js#it
      goes to the bill-to contact’s primary address, from the template, with the document attached, in the
      transaction
  - id: SC-CAP-ACC-TRX-005-02
    given: An amendment advanced the invoice to revision two.
    when: Send its e-mail document.
    then: The subject identifies the second revision.
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/e2e/invoices.e2e.spec.js#it amends an issued, unposted
      invoice (POST .../amend): a line added, the revision 2, the e-mail subject saying so
edge_cases: []
depends_on:
  - CAP-ACC-TRX-001
related:
  - CAP-ACC-TRX-002
journeys:
  - JNY-ACC-TRX-001
evidence:
  - >-
    services-accounting at f47cb263875bbc0c5640fba7dae6785ec32695f8:
    modules/transactions/aws/api/invoice-documents.routes.ts (renderInvoice, emailInvoice);
    services/invoices/invoice-rendering.ts, invoice-emails.ts, invoice-document-data.ts;
    services/ports/invoice-email-sender.ts; services/persistence/invoice-email-submissions.ts;
    docs/accounting/invoices.md, document-templates.md; tests e2e/invoice-documents.e2e.spec.js,
    integration/services/invoices/render-invoice, email-invoice.
  - >-
    react-console at baf6dae382d6f41dce976c7f848667ccc37e076f: components/accounting/invoices (no render or
    e-mail call found); journeys ACT-ACC-0201 and ACT-ACC-0808 (no Playwright spec).
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-PRV-001, TC-PRV-002]
exercised_by: [FAS-ACC-TRX-01-01, FAS-ACC-TRX-01-02, FAS-ACC-TRX-01-04]
suites: [TST-ACC-TRX-007, TST-ACC-TRX-051, TST-ACC-TRX-060]
---

# Prepare and deliver invoice documents

## Purpose

Staff and Commerce give customers a readable account of their billed charges.

## How It Works

A reader requests the rendered invoice using its applicable template. Accounting produces the current HTML document when requested. Sending is an explicit operation with its own authority and retry identity. Staff can select recipients when the bill-to contact’s primary address is unsuitable or unavailable. Communication submission and its event commit together. A failed submission leaves no misleading delivery record. The product should expose document delivery on the staff invoice page.

## Relationships

- Issue customer bills and numbered quotes supplies or continues the related financial work.
- Correct issued bills before posting supplies or continues the related financial work.
