---
id: CAP-ACC-TRX-019
title: Maintain customer-specific collection choices
feature: FEAT-ACC-TRX-05
product_area: accounting
module: transactions
revision: 1
status: draft
product_intent: proposed
implementation_evidence: observed
supersedes: []
source_sha:
  services-accounting: f47cb263875bbc0c5640fba7dae6785ec32695f8
intent_sources:
  - 'services-accounting:docs/architecture/accounting-2.0/02-decisions.md#D-06'
  - 'services-accounting:docs/architecture/accounting-2.0/02-decisions.md#D-02'
purpose: Finance records exceptions to default collection behavior for a CRM party.
outcomes:
  - Finance records exceptions to default collection behavior for a CRM party.
  - >-
    Removing the exception restores default behavior. Commerce reads these choices during checkout, while the
    product should provide a dedicated staff editor.
concepts:
  - CON-ACC-TRX-005
actors:
  - ACT-ACC-012
  - ACT-ACC-002
  - ACT-ACC-021
surfaces:
  - api
permissions:
  - key: accounting.customer-terms.read
    where_checked: api
    scope: tenant
  - key: accounting.customer-terms.manage
    where_checked: api
    scope: tenant
rules:
  - id: BR-CAP-ACC-TRX-019-01
    proved_by: [ATS-ACC-TRX-017-08, ATS-ACC-TRX-019-01, ATS-ACC-TRX-019-08, TST-ACC-TRX-006, TST-ACC-TRX-088]
    statement: >-
      A contact or organization without saved terms receives marked defaults, and each party can have at most
      one saved terms record.
    kind: policy
    enforced_at:
      - service
      - database
    must_prove: true
    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
    origin: 'services-accounting:docs/architecture/accounting-2.0/02-decisions.md#D-06'
  - id: BR-CAP-ACC-TRX-019-02
    proved_by: [ATS-ACC-TRX-019-02, ATS-ACC-TRX-019-08, TST-ACC-TRX-088]
    statement: >-
      Creation omits a version and replacement requires the version read; duplicate creation and stale saves
      fail, while omitted settings revert to defaults.
    kind: validation
    enforced_at:
      - service
    must_prove: true
    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
    origin: 'services-accounting:docs/architecture/accounting-2.0/02-decisions.md#D-06'
  - id: BR-CAP-ACC-TRX-019-03
    proved_by: [ATS-ACC-TRX-017-08, ATS-ACC-TRX-019-03, ATS-ACC-TRX-019-09, TST-ACC-TRX-088]
    statement: >-
      Collection choices use fixed vocabularies, allow-lists permit at most fifty unique options with empty
      meaning unrestricted, and default payment terms must be active within the workspace.
    kind: validation
    enforced_at:
      - api
      - service
      - database
    must_prove: true
    provenance: observed
    source: 'services-accounting:modules/transactions/aws/api/customer-terms.schemas.ts:customerTermsPutSchema'
    origin: 'services-accounting:docs/architecture/accounting-2.0/02-decisions.md#D-02'
  - id: BR-CAP-ACC-TRX-019-04
    proved_by: [ATS-ACC-TRX-019-04, TST-ACC-TRX-088]
    statement: 'Removing terms restores default behavior, and a stale version prevents deletion.'
    kind: lifecycle
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/persistence/customer-terms.integration.spec.js#it
      refuses a delete at a stale version, keeping the record
    origin: 'services-accounting:docs/architecture/accounting-2.0/02-decisions.md#D-06'
  - id: BR-CAP-ACC-TRX-019-05
    proved_by: [ATS-ACC-TRX-019-05, TST-ACC-TRX-088]
    statement: Payment terms referenced as a customer default are protected from deletion.
    kind: invariant
    enforced_at:
      - database
    must_prove: true
    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)
    origin: 'services-accounting:docs/architecture/accounting-2.0/02-decisions.md#D-06'
  - id: BR-CAP-ACC-TRX-019-06
    proved_by: [ATS-ACC-TRX-019-06, ATS-ACC-TRX-019-08, TST-ACC-TRX-006]
    statement: >-
      Terms read and manage authorities are separate, and Commerce can retrieve terms through its billing
      service at checkout.
    kind: permission
    enforced_at:
      - api
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/e2e/customer-terms.e2e.spec.js#it refuses the write and
      the delete without accounting.customer-terms.manage (403), the reader’s key not enough
    origin: 'services-accounting:docs/architecture/accounting-2.0/02-decisions.md#D-06'
  - id: BR-CAP-ACC-TRX-019-07
    proved_by: []
    statement: >-
      The product should provide a staff editor for customer terms; the current console only shows them
      alongside financial standing.
    kind: policy
    enforced_at:
      - console
    must_prove: false
    provenance: inferred
    source: 'react-console:lib/accounting/transactions/types.ts'
    origin: none
    note: >-
      The scoped console pages provide no customer-terms editor; the recommendation does not claim implemented
      enforcement.
  - id: BR-CAP-ACC-TRX-019-08
    proved_by: [ATS-ACC-TRX-019-07, TST-ACC-TRX-088]
    statement: 'An update lock blocks replacing or deleting customer terms, while a deletion-only lock blocks removal.'
    kind: validation
    enforced_at:
      - service
    must_prove: true
    provenance: observed
    source: 'services-accounting:modules/transactions/services/persistence/customer-terms.ts'
    origin: none
scenarios:
  - id: SC-CAP-ACC-TRX-019-01
    given: An employer remits for staff and uses forty-five-day terms.
    when: Save its customer terms and create an invoice without requested terms.
    then: Financial standing includes the saved choices and the invoice derives its forty-five-day due date.
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/invoices/customer-terms-precedence.integration.spec.js#it
      takes the bill-to’s default terms when the request names none, the due date 45 days after the invoice
      date
  - id: SC-CAP-ACC-TRX-019-02
    given: Two editors started from the same terms version.
    when: Save the second editor’s replacement after the first succeeds.
    then: The obsolete version is rejected and the first saved state remains.
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/e2e/customer-terms.e2e.spec.js#it refuses a replacement
      at a stale version: 409
edge_cases: []
depends_on: []
related:
  - CAP-ACC-TRX-001
  - CAP-ACC-TRX-017
  - CAP-ACC-TRX-020
journeys: []
evidence:
  - >-
    services-accounting at f47cb263875bbc0c5640fba7dae6785ec32695f8:
    modules/transactions/aws/api/customer-terms.routes.ts (getCustomerTerms, putCustomerTerms,
    deleteCustomerTerms), customer-terms.schemas.ts; services/customers/customer-terms-rules.ts;
    services/persistence/customer-terms.ts; db/customer-terms.table.ts; docs/accounting/customers.md
    ("Customer terms"); aws/accounting.service-functions.ts (the billing function's customer terms read);
    tests e2e/customer-terms.e2e.spec.js, integration/services/persistence/customer-terms,
    customer-terms.queries, invoices/customer-terms-precedence, unit/rules/customer-terms-rules.
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-006, TC-TEN-001, TC-TEN-002, TC-TEN-003, TC-DAT-001, TC-DAT-002, TC-DAT-003, TC-DAT-004, TC-LOG-002, TC-LOG-003, TC-LOG-004, TC-PI-001, TC-PI-003, TC-PI-005, TC-PRV-001, TC-PRV-002]
exercised_by: [FAS-ACC-TRX-05-01, FAS-ACC-TRX-05-03, FAS-ACC-TRX-05-04]
suites: [TST-ACC-TRX-006, TST-ACC-TRX-088]
---

# Maintain customer-specific collection choices

## Purpose

Finance records exceptions to default collection behavior for a CRM party.

## How It Works

Staff read the party’s saved terms or the marked defaults. Creating an exception produces one customer-terms record. Replacing it requires the version the editor read and supplies the complete intended settings. Missing settings return to their defaults rather than retaining earlier overrides. Invalid terms or protected records prevent the write. Removing the exception restores default behavior. Commerce reads these choices during checkout, while the product should provide a dedicated staff editor.

## Relationships

- Issue customer bills and numbered quotes supplies or continues the related financial work.
- Explain a customer’s current financial position supplies or continues the related financial work.
- Coordinate financial commands across applications supplies or continues the related financial work.
