---
id: CAP-ACC-PRD-017
title: Complete accounting setup for a group of products
feature: FEAT-ACC-PRD-04
product_area: accounting
module: products
revision: 3
status: draft
product_intent: proposed
implementation_evidence: partially-observed
supersedes:
  - react-console acceptance inventory CAP-ACC-PRD-015
  - react-console acceptance inventory RUL-ACC-PRD-040
  - react-console acceptance inventory RUL-ACC-PRD-041
source_sha:
  services-accounting: f47cb263875bbc0c5640fba7dae6785ec32695f8
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
intent_sources:
  - 'services-accounting:docs/milestones/ACCT-M1-books-and-invoices.md#D3'
purpose: Finance requests the products still lacking accounting setup.
outcomes:
  - Finance can complete multiple setups in a single transaction.
concepts:
  - CON-ACC-PRD-004
actors:
  - ACT-ACC-008
  - ACT-ACC-006
  - ACT-ACC-007
surfaces:
  - api
permissions:
  - key: accounting.product-accounting.read
    where_checked: api
    scope: tenant
  - key: accounting.product-accounting.update
    where_checked: api
    scope: tenant
rules:
  - id: BR-CAP-ACC-PRD-017-01
    proved_by: [ATS-ACC-PRD-015-17, ATS-ACC-PRD-017-01, TST-ACC-PRD-025, TST-ACC-PRD-037]
    statement: >-
      Products lacking a setup use the regular product filters, sort, paging and shape, with active status
      selected unless another status is requested.
    kind: policy
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/products/tests/e2e/product-accounting-setups.e2e.spec.js#answers the active
      products with no setup, by name
    origin: none
  - id: BR-CAP-ACC-PRD-017-02
    proved_by: [ATS-ACC-PRD-017-02, TST-ACC-PRD-025, TST-ACC-PRD-036]
    statement: >-
      The bulk API accepts one to one hundred distinct product setups and uses single-setup replacement
      semantics for each.
    kind: validation
    enforced_at:
      - api
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
      101 setups before reading any product
    origin: none
  - id: BR-CAP-ACC-PRD-017-03
    proved_by: [ATS-ACC-PRD-017-03, ATS-ACC-PRD-017-06, ATS-ACC-PRD-017-07, TST-ACC-PRD-025, TST-ACC-PRD-036]
    statement: A failing bulk setup rolls back the entire request and identifies its position and product.
    kind: invariant
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
      a rule of a later setup naming its position and product, the earlier create rolled back
    origin: none
  - id: BR-CAP-ACC-PRD-017-04
    proved_by: [ATS-ACC-PRD-017-04, TST-ACC-PRD-025, TST-ACC-PRD-028, TST-ACC-PRD-036]
    statement: >-
      Duplicate, absent and other-workspace product identities reject the bulk request before any setup
      persists.
    kind: validation
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/products/tests/e2e/products-security.e2e.spec.js#refuses tenant B a bulk
      save naming tenant A’s product as unknown
    origin: none
  - id: BR-CAP-ACC-PRD-017-05
    proved_by: [ATS-ACC-PRD-017-06]
    statement: >-
      Bulk writes acquire product locks in identity order, avoiding conflicting acquisition orders between
      bulk saves.
    kind: invariant
    enforced_at:
      - service
    must_prove: false
    provenance: observed
    source: 'services-accounting:modules/products/services/persistence/products.ts:lockProductsInIdOrder'
    origin: none
  - id: BR-CAP-ACC-PRD-017-06
    proved_by: [ATS-ACC-PRD-017-05, TST-ACC-PRD-028]
    statement: >-
      The missing-setup list requires product-accounting read permission and bulk replacement requires
      product-accounting update permission.
    kind: permission
    enforced_at:
      - api
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/products/tests/e2e/products-security.e2e.spec.js#is refused listing the
      products without an accounting setup
    origin: 'services-accounting:docs/milestones/ACCT-M1-books-and-invoices.md#D3'
  - id: BR-CAP-ACC-PRD-017-07
    proved_by: []
    statement: >-
      The console marks missing setups on individual rows but provides no dedicated missing-setup list or bulk
      editor.
    kind: policy
    enforced_at:
      - console
    must_prove: false
    provenance: observed
    source: 'react-console:components/accounting-config/products/products-page.tsx:AccountingCell'
    origin: none
scenarios:
  - id: SC-CAP-ACC-PRD-017-01
    given: Products in two units lack accounting setup.
    when: Finance saves one unit’s setups and requests the remaining list.
    then: Only the other unit’s product remains on that list.
    provenance: test
    source: >-
      services-accounting:modules/products/tests/e2e/product-accounting-setups.e2e.spec.js#leaves only the
      product of the other unit without a setup
edge_cases:
  - id: SC-CAP-ACC-PRD-017-02
    given: The third bulk entry selects another unit’s revenue account.
    when: Finance submits the bulk setup request.
    then: No setup persists and the error identifies that entry and product.
    provenance: test
    source: >-
      services-accounting:modules/products/tests/e2e/product-accounting-setups.e2e.spec.js#refuses another
      unit’s account in a later setup 400, naming it, and writes nothing
constraints: []
depends_on:
  - CAP-ACC-PRD-015
  - CAP-ACC-PRD-003
related:
  - CAP-ACC-PRD-016
journeys:
  - JNY-ACC-PRD-005
open_questions: []
evidence:
  - 'react-console:components/accounting-config/products/products-page.tsx'
  - 'services-accounting:docs/accounting/products.md'
  - 'services-accounting:docs/milestones/ACCT-M1-books-and-invoices.md'
  - 'services-accounting:modules/products/aws/api/products.routes.ts'
  - 'services-accounting:modules/products/services/persistence/product-accounting-setups.ts'
  - 'services-accounting:modules/products/services/persistence/products.ts'
  - 'services-accounting:modules/products/tests/e2e/product-accounting-setups.e2e.spec.js'
  - 'services-accounting:modules/products/tests/e2e/products-security.e2e.spec.js'
  - >-
    services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js
  - >-
    services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.queries.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-LOG-001, TC-LOG-002, TC-LOG-003, TC-LOG-004, TC-LOG-005, TC-PI-001, TC-PI-003, TC-PI-005]
exercised_by: [FAS-ACC-PRD-04-02, FAS-ACC-PRD-04-03, FAS-ACC-PRD-04-04]
suites: [TST-ACC-PRD-025, TST-ACC-PRD-028, TST-ACC-PRD-036, TST-ACC-PRD-037]
---

# Complete accounting setup for a group of products

## Purpose

Finance requests the products still lacking accounting setup.

## How It Works

Finance requests the products still lacking accounting setup. The API keeps ordinary product filters and paging while defaulting to active products. A specialist can submit several complete setups in one request. Each setup uses the single-product validation contract. The bulk operation locks products in a consistent order before writing. One refusal rolls back every setup in the request. Its error identifies the offending position and product. The console currently provides only a per-row missing-setup indicator, leaving this workflow available through the API.

## Relationships

This outcome uses assign a product’s accounting treatment. This outcome uses locate products and inspect their configuration.
