---
id: DOM-ACC-PRD-004
title: Accounting Setup
realises: CON-ACC-PRD-004
product_area: accounting
module: products
revision: 3
status: draft
design_intent: proposed
implementation_evidence: observed
source_sha:
  services-accounting: f47cb263875bbc0c5640fba7dae6785ec32695f8
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
owned_by: SVC-ACC-PRD-products
readable_by: []
lifecycle: STATE-ACC-PRD-003
custom_fields: none
identity: The workspace product key identifies at most one setup. Its copied business unit is permanent. Revenue-share
  keys are generated when absent and retained when supplied. A kind tax default instead uses the workspace
  and kind as its key.
attributes:
- name: product and business unit
  kind: reference
  required: true
  computed: true
  notes: Product identity determines the setup key and its unchanging business unit.
- name: account slots
  kind: reference
  required: false
  computed: false
  notes: Optional receivable, revenue, deferred revenue, write-off, cost and inventory references use slot-specific
    account categories. Sellable kinds require revenue during service validation.
- name: dimensions and merchant account
  kind: reference
  required: false
  computed: false
  notes: Department, project and merchant account are optional references in the product's business unit.
- name: tax class
  kind: reference
  required: false
  computed: false
  notes: A workspace tax class overrides the kind default. New choices must be active, while held choices may
    remain inactive. The approved realignment transfers this assignment to Commerce.
- name: recognition strategy
  kind: enum
  required: true
  computed: false
  notes: None means immediate recognition and is the default. Automatic, relative-date and fixed-date strategies
    require kind support and a deferred revenue account.
- name: relative-date fallback
  kind: enum
  required: false
  computed: false
  notes: Transactions outside relative ranges use either immediate recognition or the configured default deferral.
- name: fixed recognition dates
  kind: collection
  required: false
  computed: false
  notes: At most 120 distinct dates distribute exactly one hundred percent of recognition.
- name: relative recognition ranges
  kind: collection
  required: false
  computed: false
  notes: Up to 12 inclusive transaction-month ranges may wrap the year end but cannot overlap; saving sorts
    them by opening month and retains recognition offsets.
- name: revenue shares
  kind: collection
  required: false
  computed: false
  notes: Up to 50 income-account shares use percentages totaling at most one hundred or fixed amounts bounded
    by the selected standard base price when one is available.
- name: inter-entity accounts
  kind: collection
  required: false
  computed: false
  notes: Up to 200 entries name another unit once each and reference that unit's receivable and liability accounts.
- name: notes
  kind: text
  required: false
  computed: false
  notes: Finance can keep optional free-text notes on the setup.
- name: lock, version and stamps
  kind: computed
  required: true
  computed: true
  notes: Protection and version belong to the setup separately from the product; persistence maintains the
    stamps.
- name: kind default tax class
  kind: reference
  required: false
  computed: false
  notes: Each workspace can keep one tax default per kind with independent version and protection, governed
    by tax-class permissions.
relationships:
- to: DOM-ACC-PRD-001
  cardinality: zero-or-one-to-one
  ownership: The product owns setup lifetime; its deletion cascades to the setup and children.
  cross_service: false
- to: DOM-ACC-PRD-002
  cardinality: 'informational: the standard base-currency amount bounds fixed-share validation'
  ownership: Neither price nor setup owns the other; setup validation locks their shared product while reading
    the price.
  cross_service: false
invariants:
- id: INV-DOM-ACC-PRD-004-01
  statement: A product can own only one setup, which cannot change its product or business unit.
  enforced_at:
  - service
  - database
  provenance: test
  source: services-accounting:modules/products/tests/integration/db/products.table.integration.spec.js#refuses
    a second setup of the product
- id: INV-DOM-ACC-PRD-004-02
  statement: Ordinary setup references belong to the product's unit; inter-entity references belong to their
    named other unit.
  enforced_at:
  - service
  - database
  provenance: test
  source: services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
    a revenue GL account of another business unit, naming both units
- id: INV-DOM-ACC-PRD-004-03
  statement: Service checks reject ordinary account slots whose account category is unsuitable.
  enforced_at:
  - service
  provenance: test
  source: services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
    an asset account as the revenue account, naming the slot and the types it takes, and writes no setup
- id: INV-DOM-ACC-PRD-004-04
  statement: Sellable-kind validation requires revenue, and deferred-recognition validation requires a deferred
    revenue account.
  enforced_at:
  - service
  provenance: test
  source: services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
    a Donation Product’s setup without a revenue GL account
- id: INV-DOM-ACC-PRD-004-05
  statement: New references must be active, but an inactive value already retained in that field remains valid.
  enforced_at:
  - service
  provenance: test
  source: services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
    newly assigning an inactive GL account
- id: INV-DOM-ACC-PRD-004-06
  statement: Fixed recognition dates cannot repeat and their percentages must total one hundred.
  enforced_at:
  - service
  provenance: test
  source: services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#accepts
    fractional percentages that add up to exactly 100
- id: INV-DOM-ACC-PRD-004-07
  statement: Relative ranges cannot share a transaction month, including across the year boundary.
  enforced_at:
  - service
  provenance: test
  source: services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#REGRESSION
    — refuses 1-3 beside 11-2, the wrapping last rule overlapping the first, which Rhythm 1.0 accepted
- id: INV-DOM-ACC-PRD-004-08
  statement: Setup saving checks share totals and duplicate supplied identities against an available always-period
    standard base price; later product saving does not revalidate those shares.
  enforced_at:
  - service
  provenance: observed
  source: services-accounting:modules/products/services/persistence/product-accounting-setups.ts:replaceProductAccounting;
    services-accounting:modules/products/services/persistence/products.ts:updateProduct
- id: INV-DOM-ACC-PRD-004-09
  statement: The setup row and all four child collections share a transaction, so refused replacement retains
    their prior committed values.
  enforced_at:
  - service
  provenance: test
  source: services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#leaves
    the previous setup and collections when the database refuses a new row after the old ones were removed
- id: INV-DOM-ACC-PRD-004-10
  statement: A referenced account, dimension, merchant account or tax class cannot be deleted while a setup
    or kind default uses it.
  enforced_at:
  - database
  provenance: test
  source: services-accounting:modules/products/tests/integration/services/persistence/products.shared-base.integration.spec.js#refuses
    deleting a tax class a default names, as one a setup names
- id: INV-DOM-ACC-PRD-004-11
  statement: Resolution prefers the setup's tax class, falls back to the workspace kind default, and otherwise
    returns no class.
  enforced_at:
  - service
  - database
  provenance: test
  source: services-accounting:modules/products/tests/e2e/products-shared-base.e2e.spec.js#lets the product’s
    own accounting setup class win over the type default
- id: INV-DOM-ACC-PRD-004-12
  statement: The workspace-kind key allows one tax default and prevents reassignment to another kind.
  enforced_at:
  - service
  - database
  provenance: observed
  source: services-accounting:modules/products/db/product-type-tax-classes.table.ts:productTypeTaxClasses
- id: INV-DOM-ACC-PRD-004-13
  statement: The documented posting boundary keeps posted accounts unchanged by subsequent setup corrections.
  enforced_at: []
  provenance: documented
  source: services-accounting:docs/architecture/accounting-2.0/06-integrity-model.md#The accounting is resolved
    and frozen at posting
physical:
- product_accounting_setups
- product_deferral_fixed_dates
- product_deferral_relative_rules
- product_revenue_splits
- product_inter_entity_accounts
- product_type_tax_classes
evidence:
- 'services-accounting at f47cb263: modules/products/db/product-accounting-setups.table.ts, product-accounting-children.table.ts,
  product-type-tax-classes.table.ts; services/persistence/product-accounting-setups.ts (replaceProductAccounting,
  replaceProductAccountings, deleteProductAccounting, listProductsWithoutAccounting); services/persistence/product-type-tax-classes.ts
  (resolveProductTaxClasses); services/rules/product-rules.ts (ACCOUNTING_SLOT_ACCOUNT_TYPES, revenueSplitsProblem,
  relativeRulesProblem); docs/accounting/products.md (Accounting setup, Tax class); docs/architecture/accounting-2.0/06-integrity-model.md;
  docs/architecture/realignment-2026-10-22/ownership.md.'
- 'services-accounting at f47cb263: tests/integration/services/persistence/product-accounting-setups.integration.spec.js,
  products.shared-base.integration.spec.js; tests/e2e/products-shared-base.e2e.spec.js.'
- 'react-console at baf6dae3: lib/accounting-config/product-accounting-rules.ts, product-accounting-form.ts.'
---

# Accounting Setup

## What It Models

An accounting setup tells finance how a product's money is routed, recognized and shared. It contains account and dimension references, recognition dates or ranges, revenue shares and accounts for other business units. A product may have no setup; the documented posting policy then uses its unit's defaults. Product-kind tax defaults remain a facet here pending the approved transfer to Commerce.

## Identity and Attributes

The product identifies its optional setup, which has its own version and lock. A setup write replaces the row and four child collections together. The API can preserve supplied revenue-share identities, but the current console does not return them when saving.

## Relationships

The setup belongs to its product and retains that product's business unit. Ordinary accounts and dimensions resolve in that unit, tax classes in the workspace, and inter-entity accounts in their named other unit. Validation obtains the product lock before reading the standard price used to bound fixed shares.

## Invariants

Allocation totals are checked during setup writes. A subsequent product edit does not check existing shares against a reduced price. The posting record's account preservation is documented downstream behavior and is not enforced by this setup service.

## How It Is Stored and Shared

Products owns setup persistence under permissions independent of catalogue editing. Consumers read the configuration needed for their financial work. The tax transfer changes future ownership; until that cutover, Accounting retains setup assignments and kind defaults and resolves their precedence.

## Open Design Questions

Existing tax assignments need a migration and cutover plan. Product must decide the history requirement and whether staged console saving needs an atomic option. Browser validation differences, regenerated share identities and the absent setup-delete action remain implementation findings.
