---
id: DOM-ACC-BKS-002
title: Chart of Accounts
realises: CON-ACC-BKS-002
product_area: accounting
module: books
revision: 1
status: draft
design_intent: proposed
implementation_evidence: observed
source_sha:
  services-accounting: f47cb263875bbc0c5640fba7dae6785ec32695f8
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
owned_by: SVC-ACC-BKS-books
readable_by:
  - SVC-ACC-BKS-maintenance
custom_fields: none
identity: >-
  Chart records have workspace-scoped configuration identities. GL accounts,
  departments and projects can derive identity from unit and normalized code;
  each collection has unique immutable codes within a unit. A default mapping is
  identified by unit and purpose.
attributes:
  - name: GL account code
    kind: text
    required: true
    computed: false
    notes: >-
      Creation trims and uppercases the code; it is unique in the unit and
      cannot be replaced.
  - name: GL account name and display name
    kind: text
    required: false
    computed: true
    notes: The optional name combines with the code to form a computed display label.
  - name: GL account type
    kind: enum
    required: true
    computed: false
    notes: 'Fourteen account types are available, with income as the default.'
  - name: GL account currency
    kind: reference
    required: true
    computed: false
    notes: >-
      The unit must enable the selected currency. Existing console records lock
      this control; service replacement remains possible when references permit
      it.
  - name: default purpose assignments
    kind: collection
    required: false
    computed: false
    notes: >-
      Fifteen global purposes each accept one active account per unit; expected
      types guide clients rather than constrain the service.
  - name: bank accounts
    kind: collection
    required: false
    computed: false
    notes: >-
      Descriptive bank details, an optional four-digit suffix, currency and a
      same-unit GL destination are stored without full account or routing
      numbers.
  - name: merchant accounts
    kind: collection
    required: false
    computed: false
    notes: >-
      Processor and account references contain no credentials. Status remains
      Not Connected; ordinary Books saves preserve the settlement fields managed
      by Reconciliation.
  - name: departments and accounting projects
    kind: collection
    required: false
    computed: false
    notes: >-
      Separate department and project collections use fixed uppercase codes;
      departments require names, while projects allow an optional name and
      informational end date.
  - name: tax payable mapping
    kind: collection
    required: false
    computed: false
    notes: >-
      A rate may select one payable account for each unit; the link is stored
      with the transitional tax-rate setup.
  - name: 'active, lock and version'
    kind: collection
    required: true
    computed: false
    notes: >-
      Availability and lock settings are stored on ordinary records, while
      versions advance automatically; default assignments carry no availability
      flag or lock.
relationships:
  - to: DOM-ACC-BKS-001
    cardinality: Each chart record belongs to exactly one unit
    ownership: >-
      The unit scopes these records; they do not transfer to a different set of
      books.
    cross_service: false
  - to: DOM-ACC-BKS-006
    cardinality: A workspace rate has multiple unit-specific payable assignments
    ownership: >-
      Tax setup owns the rate-to-account link, while the referenced GL account
      remains in its unit’s chart.
    cross_service: false
invariants:
  - id: INV-DOM-ACC-BKS-002-01
    statement: >-
      The unit and normalized code of a GL account cannot change, and its code
      is unique within that unit.
    enforced_at:
      - service
      - database
    provenance: test
    source: >-
      services-accounting:modules/books/tests/e2e/gl-accounts.e2e.spec.js#answers
      409 to a change of code, naming the column
  - id: INV-DOM-ACC-BKS-002-02
    statement: >-
      GL, bank and merchant destinations use currency rows enabled for their own
      unit.
    enforced_at:
      - api
      - service
      - database
    provenance: test
    source: >-
      services-accounting:modules/books/tests/e2e/gl-accounts.e2e.spec.js#answers
      400 to a currency the unit is not enabled for, in Rhythm 1.0’s words
  - id: INV-DOM-ACC-BKS-002-03
    statement: >-
      Default mappings and bank, merchant and tax destinations reference GL
      accounts belonging to the mapped unit.
    enforced_at:
      - service
      - database
    provenance: test
    source: >-
      services-accounting:modules/books/tests/e2e/default-gl-accounts.e2e.spec.js#answers
      400 to another unit’s GL account, naming both units
  - id: INV-DOM-ACC-BKS-002-04
    statement: >-
      A GL account cannot be deactivated or removed while it serves a default
      purpose.
    enforced_at:
      - database
    provenance: observed
    source: >-
      services-accounting:modules/books/db/gl-accounts.table.ts:gl_accounts_default_guard_trigger
  - id: INV-DOM-ACC-BKS-002-05
    statement: >-
      Restricting references block deletion of chart records; recognized
      constraints produce a refusal identifying the dependent kind.
    enforced_at:
      - service
      - database
    provenance: test
    source: >-
      services-accounting:modules/books/tests/integration/services/persistence/gl-accounts.integration.spec.js#translates
      the refusal of each restrict foreign key to a GL account into a 409 naming
      it
  - id: INV-DOM-ACC-BKS-002-06
    statement: >-
      A unit has no more than one active GL account assigned to each standard
      purpose.
    enforced_at:
      - service
      - database
    provenance: observed
    source: >-
      services-accounting:modules/books/db/business-unit-default-gl-accounts.table.ts:business_unit_default_gl_accounts_active_trigger
  - id: INV-DOM-ACC-BKS-002-07
    statement: A bank-account suffix is absent or consists of exactly four digits.
    enforced_at:
      - api
      - database
    provenance: test
    source: >-
      services-accounting:modules/books/tests/e2e/bank-accounts.e2e.spec.js#answers
      400 to an account_number_last4 of five digits
  - id: INV-DOM-ACC-BKS-002-08
    statement: >-
      A processor account reference requires a processor selection; the
      merchant-account schema provides no credential storage.
    enforced_at:
      - api
      - service
      - database
    provenance: test
    source: >-
      services-accounting:modules/books/tests/e2e/merchant-accounts.e2e.spec.js#answers
      400 to a processor account reference without a processor
  - id: INV-DOM-ACC-BKS-002-09
    statement: >-
      Department and project codes cannot change and are unique within their
      respective unit collections.
    enforced_at:
      - service
      - database
    provenance: test
    source: >-
      services-accounting:modules/books/tests/e2e/departments.e2e.spec.js#answers
      400 to a code the unit already has, under the id it derives
physical:
  - accounting.gl_accounts
  - accounting.business_unit_default_gl_accounts
  - accounting.default_gl_account_purposes (global vocabulary)
  - accounting.bank_accounts
  - accounting.merchant_accounts
  - accounting.payment_processors (global vocabulary)
  - accounting.departments
  - accounting.accounting_projects
  - accounting.tax_rate_accounts
evidence:
  - >-
    services-accounting at f47cb263: modules/books/db/gl-accounts.table.ts,
    business-unit-default-gl-accounts.table.ts,
    default-gl-account-purposes.table.ts, bank-accounts.table.ts,
    merchant-accounts.table.ts, payment-processors.table.ts,
    departments.table.ts, accounting-projects.table.ts, tax-zone-rates.table.ts
  - >-
    services-accounting at f47cb263:
    modules/books/services/persistence/gl-accounts.ts, default-gl-accounts.ts,
    bank-accounts.ts, merchant-accounts.ts, departments.ts,
    accounting-projects.ts, configuration-refusals.ts,
    tax-zones.ts:taxRateAccountsOfUnit
  - >-
    services-accounting at f47cb263:
    modules/batches/services/engine/posting-documents.ts:TaxAccounts (cited
    reader)
  - >-
    react-console at baf6dae3:
    components/configuration/accounting/business-unit-default-gl-accounts.tsx,
    components/configuration/resources/accounting-gl-accounts.tsx
---

# Chart of Accounts

## What It Models

A chart provides the accounts to which a unit records money and the mappings that direct financial activity. It includes standard-purpose assignments, bank and merchant destinations, and department and project classifications. Tax payable links connect shared rate configuration to the unit’s liability destinations.

## Identity and Attributes

Codes are normalized at creation and remain unique within their unit and collection. The same code can exist in another unit. A computed display label combines code and optional name.

Defaults select one account per purpose. Bank records hold descriptive details and an optional four-digit suffix. Merchant records retain a processor reference without credentials and show Not Connected. Departments and projects supply separate reporting vocabularies. Availability and record locks are stored settings; mutation versions are maintained automatically.

## Relationships

Chart records stay in their originating unit. Internal destinations are checked against that unit. Financial and product configuration can retain restricting references that prevent deletion. Tax mappings belong to the rate setup even though their destination is a chart account.

## Invariants

Fixed codes and unit ownership preserve chart identities. The console locks account currency, while the service permits a supported replacement subject to references. Default-purpose assignments keep their destinations active. Restricting keys enforce deletion safety for declared dependencies, and the service translates the dependencies it recognizes. Soft references and unrecognized refusal paths are outside that guarantee.

## How It Is Stored and Shared

Books maintains the chart and purpose mappings. Posting reads the shared configuration when resolving destinations. Product setup and Reconciliation consume the same records; Reconciliation writes its settlement fields, while maintenance handles workspace exports and removal.

Customer chart rows have no declared custom fields and use workspace row policies. Purpose and processor catalogues are global vocabularies. No configuration revision stream or change event is produced.

## Open Design Questions

The console filters default choices by expected type, while the service accepts other types. The required-default warning list is also local to the console. Replacing tax rates removes the mappings that previously issued tax lines refer to; Product must choose how those mappings survive configuration changes.
