---
id: WF-ACC-PRD-005
title: Save many accounting setups at once
trigger: A permitted API client submits a group of financial setups, optionally after a missing-setup query.
product_area: accounting
module: products
revision: 3
status: draft
design_intent: proposed
implementation_evidence: observed
inference: []
source_sha:
  services-accounting: f47cb263875bbc0c5640fba7dae6785ec32695f8
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
implements:
- CAP-ACC-PRD-017
- CAP-ACC-PRD-015
- CAP-ACC-PRD-016
moves:
- STATE-ACC-PRD-003
crosses:
- SVC-ACC-PRD-products
idempotency: Successful replacement makes a repeated version stale. Repeating an initial setup request now
  requires the newly existing setup's version. HTTP bulk input cannot be empty.
concurrency: All requested product locks are acquired in key order before any setup is processed. Overlapping
  bulk requests share that order, and same-product mutations wait on these locks.
hops:
- n: 1
  actor_or_service: API client
  action: Read products without setups using ordinary filters and active status unless another is requested.
  anchor: services-accounting:modules/products/services/persistence/product-accounting-setups.ts:listProductsWithoutAccounting
  seam: sync
  on_failure: Return the failed query without changing records.
  left_inconsistent: No configuration was written.
  observer: The client receives the query failure.
  provenance: test
  source: services-accounting:modules/products/tests/e2e/products-security.e2e.spec.js#lists the products without
    an accounting setup
- n: 2
  actor_or_service: Bulk save (before the transaction)
  action: Reject more than the allowed setups or repeated product keys before opening the write transaction.
  anchor: services-accounting:modules/products/services/persistence/product-accounting-setups.ts:replaceProductAccountings
  seam: sync
  on_failure: Refuse the group before writing any setup.
  left_inconsistent: All setups retain their committed values.
  observer: The client receives a batch input error.
  provenance: observed
  source: services-accounting:modules/products/services/persistence/product-accounting-setups.ts:replaceProductAccountings
- n: 3
  actor_or_service: Bulk save (one transaction)
  action: Lock requested products in key order and locate identities absent from the workspace.
  anchor: services-accounting:modules/products/services/persistence/products.ts:lockProductsInIdOrder
  seam: sync
  on_failure: Abort and identify the missing product and input position.
  left_inconsistent: No grouped setup changes commit.
  observer: The client sees the named missing-product problem.
  provenance: observed
  source: services-accounting:modules/products/services/persistence/products.ts:lockProductsInIdOrder
- n: 4
  actor_or_service: Setup persistence, sequentially in request order
  action: Apply the single-setup writer sequentially in input order within the existing transaction.
  anchor: services-accounting:modules/products/services/persistence/product-accounting-setups.ts:replaceProductAccounting
  seam: sync
  on_failure: Abort at the first refusal and qualify recognized errors with entry position and product.
  left_inconsistent: Every setup keeps its previous committed state.
  observer: The client sees the failing entry.
  provenance: observed
  source: services-accounting:modules/products/services/persistence/product-accounting-setups.ts:replaceProductAccountings
- n: 5
  actor_or_service: Database commit
  action: Commit all setups and return results in submitted order.
  anchor: services-accounting:modules/products/services/persistence/product-accounting-setups.ts:replaceProductAccountings
  seam: sync
  on_failure: A failed commit rolls back the entire group.
  left_inconsistent: No setup in the group commits independently.
  observer: The client receives saved results or transaction failure.
  provenance: observed
  source: services-accounting:modules/products/services/persistence/product-accounting-setups.ts:replaceProductAccountings
branches: []
waits: []
evidence:
- 'services-accounting at f47cb263: modules/products/services/persistence/product-accounting-setups.ts, products.ts
  (lockProductsInIdOrder); aws/api/products.routes.ts (replaceProductAccountings, listProductsWithoutAccounting);
  docs/accounting/products.md (Products without a setup, Bulk save).'
- 'react-console at baf6dae3: components/accounting-config/products/products-page.tsx (no missing-setup list
  or bulk editor).'
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-002, TC-PI-003, TC-PI-005]
---

# Save many accounting setups at once

## What It Does

The API can find products lacking setups and save a bounded group of setups together. Each entry uses the single-setup writer within one enclosing transaction, with product locks acquired in a consistent order.

## The Flow

```mermaid
sequenceDiagram
  participant C as Client
  participant B as Bulk setup service
  participant S as Single setup service
  participant D as Database
  C->>B: Read products lacking setups
  C->>B: Submit up to one hundred setups
  B->>B: Check size and duplicate identities
  B->>D: Lock requested products in identity order
  loop Input order
    B->>S: Save setup in existing transaction
    S->>D: Replace setup and children
  end
  B->>D: Commit the group
  B-->>C: Return results in input order
```

## When Something Fails

The first refusal aborts the group, including entries already processed. Recognized errors identify the product and its input position. Success returns setups in request order. The console only marks missing setups and provides no bulk administration screen.

## Open Design Questions

A staff-facing missing-setup and bulk-edit flow is still absent. This workflow specifies the available API without introducing an unbuilt console surface.
