---
id: CAP-ACC-PRD-014
title: Configure a purchase confirmation message
feature: FEAT-ACC-PRD-03
product_area: accounting
module: products
revision: 5
status: draft
product_intent: proposed
implementation_evidence: partially-observed
supersedes:
  - react-console acceptance inventory CAP-ACC-PRD-013
  - react-console acceptance inventory RUL-ACC-PRD-029
source_sha:
  services-accounting: f47cb263875bbc0c5640fba7dae6785ec32695f8
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
intent_sources:
  - 'services-accounting:docs/milestones/ACCT-M1-books-and-invoices.md#R22'
purpose: An integrator chooses shared confirmation content or composes content owned by the product.
outcomes:
  - Confirmation choices remain consistent with product configuration.
concepts:
  - CON-ACC-PRD-001
actors:
  - ACT-ACC-006
  - ACT-ACC-011
surfaces:
  - api
permissions:
  - key: accounting.products.update
    where_checked: api
    scope: tenant
rules:
  - id: BR-CAP-ACC-PRD-014-01
    proved_by: [ATS-ACC-PRD-014-05]
    statement: >-
      Confirmation configuration selects either a product-owned template or a shared workspace template for
      product confirmations, with an empty setting disabling it.
    kind: policy
    enforced_at:
      - api
      - database
    must_prove: false
    provenance: test
    source: >-
      services-accounting:modules/products/tests/e2e/product-features.e2e.spec.js#switches to a shared
      template
    origin: none
  - id: BR-CAP-ACC-PRD-014-02
    proved_by: [ATS-ACC-PRD-014-01, TST-ACC-PRD-039]
    statement: >-
      A newly selected shared template must be active, belong to the workspace and confirmation purpose, and
      have no record owner.
    kind: validation
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/products/tests/integration/services/persistence/products.features.integration.spec.js#refuses
      a product’s OWN template named as a shared one
    origin: none
  - id: BR-CAP-ACC-PRD-014-03
    proved_by: [ATS-ACC-PRD-014-02, ATS-ACC-PRD-014-05, TST-ACC-PRD-039]
    statement: >-
      Platform stores product-owned content and validates its Liquid, allowed variables and required reply-to
      information.
    kind: validation
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/products/tests/integration/services/persistence/products.features.integration.spec.js#refuses
      content Platform refuses, naming the property, and writes nothing
    origin: none
  - id: BR-CAP-ACC-PRD-014-04
    proved_by: [ATS-ACC-PRD-014-02, ATS-ACC-PRD-014-06, TST-ACC-PRD-039]
    statement: >-
      Accounting requests template changes after its product writes but before committing, and a Platform
      failure rolls back those product writes.
    kind: invariant
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/products/tests/integration/services/persistence/products.features.integration.spec.js#rolls
      the product back when Platform cannot save the template
    origin: none
  - id: BR-CAP-ACC-PRD-014-05
    proved_by: [ATS-ACC-PRD-006-11, ATS-ACC-PRD-014-03, ATS-ACC-PRD-014-05, TST-ACC-PRD-039]
    statement: >-
      Disabling a product-owned confirmation or choosing a shared template clears the previously owned
      template.
    kind: lifecycle
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/products/tests/integration/services/persistence/products.features.integration.spec.js#clears
      the product’s own template when it switches to a shared one
    origin: none
  - id: BR-CAP-ACC-PRD-014-06
    proved_by: [ATS-ACC-PRD-014-04, ATS-ACC-PRD-014-07, TST-ACC-PRD-039]
    statement: >-
      Omitting confirmation configuration preserves both setting and template; supplied owned content merges
      retained fields and clears optional fields explicitly set empty.
    kind: policy
    enforced_at:
      - api
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/products/tests/integration/services/persistence/products.features.integration.spec.js#asks
      Platform for nothing
    origin: none
  - id: BR-CAP-ACC-PRD-014-07
    proved_by: []
    statement: >-
      The documented confirmation purpose provides product and unit details, line quantity and price, and
      customer name.
    kind: policy
    enforced_at: []
    must_prove: false
    provenance: documented
    source: 'services-accounting:docs/accounting/products.md#Features (2026-10-16)'
    origin: none
  - id: BR-CAP-ACC-PRD-014-08
    proved_by: []
    statement: The current console hides confirmation controls.
    kind: policy
    enforced_at:
      - console
    must_prove: false
    provenance: observed
    source: 'react-console:components/accounting-config/products/product-section-types.ts:REMOVED_SECTION_KEYS'
    origin: 'services-accounting:docs/milestones/ACCT-M1-books-and-invoices.md#R22'
scenarios:
  - id: SC-CAP-ACC-PRD-014-01
    given: A product uses an owned confirmation template.
    when: A client supplies content Platform rejects.
    then: The product remains unchanged and the refusal identifies the content problem.
    provenance: test
    source: >-
      services-accounting:modules/products/tests/integration/services/persistence/products.features.integration.spec.js#refuses
      content Platform refuses, naming the property, and writes nothing
edge_cases:
  - id: SC-CAP-ACC-PRD-014-02
    given: A product has owned confirmation content.
    when: Replacement omits confirmation configuration.
    then: Both content and setting remain and no Platform call is made.
    provenance: test
    source: >-
      services-accounting:modules/products/tests/integration/services/persistence/products.features.integration.spec.js#asks
      Platform for nothing
constraints: []
depends_on:
  - CAP-ACC-PRD-002
related:
  - CAP-ACC-PRD-004
  - CAP-ACC-PRD-006
journeys:
  - JNY-ACC-PRD-004
open_questions: []
evidence:
  - 'react-console:components/accounting-config/products/product-confirmation-email-section.tsx'
  - 'react-console:components/accounting-config/products/product-section-types.ts'
  - 'services-accounting:docs/accounting/products.md'
  - 'services-accounting:docs/milestones/ACCT-M1-books-and-invoices.md'
  - 'services-accounting:modules/products/db/products.table.ts'
  - 'services-accounting:modules/products/services/confirmation-emails/confirmation-email-templates.ts'
  - 'services-accounting:modules/products/services/persistence/communication-templates.ts'
  - 'services-accounting:modules/products/services/persistence/products.ts'
  - 'services-accounting:modules/products/services/ports/communications.ts'
  - 'services-accounting:modules/products/tests/e2e/product-features.e2e.spec.js'
  - >-
    services-accounting:modules/products/tests/integration/services/persistence/communication-templates.queries.integration.spec.js
  - >-
    services-accounting:modules/products/tests/integration/services/persistence/products.features.integration.spec.js
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-005, TC-AZ-006, TC-TEN-001, TC-TEN-002, TC-TEN-003, TC-DAT-001, TC-DAT-002, TC-LOG-001, TC-LOG-002, TC-LOG-003, TC-LOG-004, TC-LOG-005, TC-AVL-004, TC-MON-002, TC-PI-001, TC-PI-003, TC-PI-004, TC-PI-005, TC-PRV-001, TC-PRV-002]
exercised_by: [FAS-ACC-PRD-03-01, FAS-ACC-PRD-03-02, FAS-ACC-PRD-03-03, FAS-ACC-PRD-03-04]
suites: [TST-ACC-PRD-039]
---

# Configure a purchase confirmation message

## Purpose

An integrator chooses shared confirmation content or composes content owned by the product.

## How It Works

An integrator chooses shared confirmation content or composes content owned by the product. Accounting checks newly selected shared templates before accepting them. Owned content is sent to Platform after product writes succeed but before their transaction commits. A Platform refusal rolls back the product writes and identifies the problem. Switching away from owned content requests its removal. Omitting the setting leaves existing content untouched. The console hides confirmation controls while preserving loaded values. A failed Accounting commit after a successful Platform call still leaves a consistency gap. Sending a message when a purchase occurs remains an Orders responsibility.

## Relationships

This outcome uses create a product with a permanent identity.
