---
id: DOM-ACC-TRX-005
title: Customer Account
realises: CON-ACC-TRX-005
product_area: accounting
module: transactions
revision: 1
status: draft
design_intent: proposed
implementation_evidence: partially-observed
source_sha:
  services-accounting: f47cb263875bbc0c5640fba7dae6785ec32695f8
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
owned_by: SVC-ACC-TRX-transactions
custom_fields: none
identity: >-
  The CRM party identifies the account view. Saved terms have a separate
  workspace-scoped record, and aging versions are identified by workspace, month
  end and snapshot run.
attributes:
  - name: party
    kind: reference
    required: true
    computed: false
    notes: >-
      Identifies the contact or organization; retained customer names occur on
      documents and snapshot rows.
  - name: open items
    kind: collection
    required: true
    computed: true
    notes: >-
      Combines outstanding invoice lines with remaining receipts and credits
      using receivable facts.
  - name: financial summary
    kind: collection
    required: true
    computed: true
    notes: >-
      Shows today's debt, overdue debt, unapplied receipts, credit and net
      position by currency, distinguishing money received from other payers.
  - name: payable description
    kind: collection
    required: false
    computed: true
    notes: >-
      Describes oldest outstanding invoices and their electronic tender
      eligibility and fee quotes.
  - name: customer terms
    kind: json
    required: false
    computed: false
    notes: >-
      Stores versioned collection choices and permitted options; an unsaved
      party receives explicitly marked defaults.
  - name: expected remittances
    kind: collection
    required: false
    computed: true
    notes: Identifies outstanding order invoices associated with a remitter.
  - name: aging snapshot versions
    kind: collection
    required: false
    computed: true
    notes: >-
      Retains validated month-end items and bucket totals for each published
      knowledge-cutoff version.
relationships:
  - to: DOM-ACC-TRX-001
    cardinality: one-to-many
    ownership: The account aggregates the customer's invoices without owning them.
    cross_service: false
  - to: DOM-ACC-TRX-003
    cardinality: one-to-many
    ownership: >-
      The account reports the customer's available receipt money without owning
      its receipts.
    cross_service: false
  - to: DOM-ACC-TRX-004
    cardinality: one-to-many
    ownership: >-
      The account reports the customer's available credit without owning its
      grants.
    cross_service: false
  - to: DOM-ACC-TRX-006
    cardinality: one-to-many
    ownership: >-
      The account derives its financial figures from the shared receivable
      facts.
    cross_service: false
invariants:
  - id: INV-DOM-ACC-TRX-005-01
    statement: >-
      A party has at most one saved terms record and receives identified
      defaults when none exists.
    enforced_at:
      - service
      - database
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/e2e/customer-terms.e2e.spec.js#it
      answers the defaults, saying so, before Acme has a record
  - id: INV-DOM-ACC-TRX-005-02
    statement: >-
      New terms omit a version, while replacement requires the current version
      and rejects duplicates or stale updates.
    enforced_at:
      - service
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/persistence/customer-terms.integration.spec.js#it
      refuses a replacement at a stale version, writing nothing
  - id: INV-DOM-ACC-TRX-005-03
    statement: >-
      Terms choices use supported vocabularies, unique allow-lists of up to
      fifty entries and an active default payment term.
    enforced_at:
      - api
      - service
      - database
    provenance: observed
    source: >-
      services-accounting:modules/transactions/aws/api/customer-terms.schemas.ts:customerTermsPutSchema
  - id: INV-DOM-ACC-TRX-005-04
    statement: A referenced customer default protects its payment term from deletion.
    enforced_at:
      - database
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/persistence/customer-terms.integration.spec.js#it
      keeps terms a party names from being deleted (409, the key)
  - id: INV-DOM-ACC-TRX-005-05
    statement: >-
      Update protection blocks replacement and deletion, while deletion
      protection blocks removal alone.
    enforced_at:
      - service
    provenance: observed
    source: >-
      services-accounting:modules/transactions/services/persistence/customer-terms.ts
  - id: INV-DOM-ACC-TRX-005-06
    statement: >-
      Customer summary and aging derive the customer's position from the same
      receivable facts.
    enforced_at:
      - service
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/customers/customer-summary.integration.spec.js#it
      agrees with the aging’s as-of read for the customer: the same open items,
      the same amounts
  - id: INV-DOM-ACC-TRX-005-07
    statement: Debt first becomes overdue on the day following its due date.
    enforced_at:
      - service
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/unit/rules/customer-summary.spec.js#it
      counts an invoice due today as not yet overdue, and one due yesterday as
      overdue
  - id: INV-DOM-ACC-TRX-005-08
    statement: >-
      A contact summary contains that contact's figures without aggregating its
      organization.
    enforced_at:
      - service
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/customers/customer-summary.integration.spec.js#it
      keeps the contact’s figures its own: Acme’s invoices are not counted in
      Ivy’s summary (1.0’s balances.js)
  - id: INV-DOM-ACC-TRX-005-09
    statement: >-
      Month-end capture uses the knowledge cutoff and excludes facts learned
      after it.
    enforced_at:
      - service
      - database
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/runs/ar-aging-pipeline.integration.spec.js#it
      captures the open items as known at September’s end: the back-dated check
      recorded on 5 October is not in it
  - id: INV-DOM-ACC-TRX-005-10
    statement: >-
      Validation precedes publication and failed single-transaction capture
      rolls back, with chunk cleanup unproved by that test.
    enforced_at:
      - service
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/runs/ar-aging-pipeline.integration.spec.js#it
      leaves none of the failed run’s rows behind: its transaction rolled back
  - id: INV-DOM-ACC-TRX-005-11
    statement: >-
      Publication protects snapshot rows and a rerun retains earlier versions
      under their run identities.
    enforced_at:
      - database
      - service
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/runs/ar-aging-pipeline.integration.spec.js#it
      keeps version 1’s rows as they were captured, readable by its run
  - id: INV-DOM-ACC-TRX-005-12
    statement: Version-aware cursors prevent paging across different published captures.
    enforced_at:
      - api
      - service
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/e2e/ar-aging.e2e.spec.js#it
      refuses the first version’s cursor with 409 version_changed, rather than
      continuing in the second version
  - id: INV-DOM-ACC-TRX-005-13
    statement: >-
      Terms and aging storage have no custom fields and the module registration
      has no custom-field capability declaration.
    enforced_at:
      - api
      - service
    provenance: documented
    source: >-
      services-accounting:docs/milestones/plans/ACCT-M2-plan.md#7a. Entity
      capabilities (R2-ARCH-001)
physical:
  - customer_terms
  - ar_snapshot_items
  - ar_snapshot_totals
  - ar_snapshot_items_published
  - ar_snapshot_totals_published
  - snapshot_run_jobs
  - snapshot_run_job_steps
  - snapshot_run_job_events
  - expected_remittances_v
evidence:
  - >-
    services-accounting at f47cb263: modules/transactions/services/customers/*,
    invoices/invoice-payability.ts, persistence/customer-summaries.ts,
    customer-terms.ts, parties.ts, ar-snapshot-items.ts, ar-snapshot-totals.ts,
    snapshot-runs.ts; db/customer-terms.table.ts, ar-snapshot-*.ts,
    snapshot-run-job*.table.ts, expected-remittances.view.ts.
  - >-
    services-accounting at f47cb263: docs/snapshots/ar-aging.md;
    docs/accounting/customers.md;
    docs/architecture/accounting-2.0/02-decisions.md (A-16, §2.11 D-06, C-9).
---
# Customer Account

## What It Models

Customer Account combines a party’s financial position with saved collection choices and historical aging. It is an Accounting view over customer obligations rather than another customer master record.

## Identity and Attributes

The party is the entry point for current reads. Saved terms represent explicit customer choices, while versioned snapshots retain a historical account view.

## Relationships

Invoices, receipts and credits supply the financial records. CRM supplies party context, and Commerce uses terms and payable descriptions during collection.

## Invariants

Version and lock checks govern terms changes. The historical reads use cutoff-aware facts, and publication protects completed snapshot versions.

## How It Is Stored and Shared

Transactions stores customer terms and aging results and computes the remaining views. Platform supplies the snapshot run ledger and query infrastructure.

## Open Design Questions

Contact summaries and payable discovery use different customer scopes. Collection holds, a terms editor and console snapshot reruns are absent; snapshot money representation and chunk recovery also need review.
