---
id: ATS-ACC-TRX-019
scope: CAP-ACC-TRX-019
product_area: accounting
module: transactions
revision: 1
status: proposed
approved_by: null
approved_at: null
source_sha:
  services-accounting: f47cb263875bbc0c5640fba7dae6785ec32695f8
scenarios:
  - id: ATS-ACC-TRX-019-01
    title: Terms defaults and uniqueness remain workspace-scoped
    level: api
    proves:
      - BR-CAP-ACC-TRX-019-01
      - INV-DOM-ACC-TRX-005-01
    preconditions: >-
      One party lacks local terms and another workspace has the same party
      identity.
    steps:
      - do: Read defaults and attempt duplicate local creation.
        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
    expected: Marked defaults remain isolated and a second saved record is rejected.
    negative: false
    data_needs: Two workspaces sharing a party reference.
    bound_to:
      - >-
        services-accounting:modules/transactions/tests/e2e/customer-terms.e2e.spec.js#it
        answers the defaults, saying so, before Acme has a record
      - >-
        services-accounting:modules/transactions/tests/e2e/customer-terms.e2e.spec.js#it
        answers the other tenant the defaults for Acme, not this tenant’s record
      - >-
        services-accounting:modules/transactions/tests/integration/services/persistence/customer-terms.integration.spec.js#it
        keeps one record per party
      - TST-ACC-TRX-006
      - TST-ACC-TRX-088
    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
    category: boundary
    test_bindings:
      - file: >-
          services-accounting:modules/transactions/tests/e2e/customer-terms.e2e.spec.js
        assertion: 'it answers the defaults, saying so, before Acme has a record'
        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
      - file: >-
          services-accounting:modules/transactions/tests/e2e/customer-terms.e2e.spec.js
        assertion: >-
          it answers the other tenant the defaults for Acme, not this tenant’s
          record
        provenance: test
        source: >-
          services-accounting:modules/transactions/tests/e2e/customer-terms.e2e.spec.js#it
          answers the other tenant the defaults for Acme, not this tenant’s
          record
      - file: >-
          services-accounting:modules/transactions/tests/integration/services/persistence/customer-terms.integration.spec.js
        assertion: it keeps one record per party
        provenance: test
        source: >-
          services-accounting:modules/transactions/tests/integration/services/persistence/customer-terms.integration.spec.js#it
          keeps one record per party
    binding_review: []
  - id: ATS-ACC-TRX-019-02
    title: Whole-record terms replacement resets omissions
    level: api
    proves:
      - BR-CAP-ACC-TRX-019-02
      - INV-DOM-ACC-TRX-005-02
    preconditions: No saved customer override exists.
    steps:
      - do: >-
          Create, duplicate-create, stale-replace and validly replace with
          omissions.
        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
    expected: >-
      Creation starts at version one, invalid writes fail and valid replacement
      advances while resetting absent settings.
    negative: false
    data_needs: Active payment-term definitions.
    bound_to:
      - >-
        services-accounting:modules/transactions/tests/integration/services/persistence/customer-terms.integration.spec.js#it
        creates the record without a version, a UUIDv7 id, at version 1
      - >-
        services-accounting:modules/transactions/tests/integration/services/persistence/customer-terms.integration.spec.js#it
        refuses a create over the existing record (no version sent), writing
        nothing
      - >-
        services-accounting:modules/transactions/tests/integration/services/persistence/customer-terms.integration.spec.js#it
        refuses a replacement at a stale version, writing nothing
      - >-
        services-accounting:modules/transactions/tests/integration/services/persistence/customer-terms.integration.spec.js#it
        replaces the record whole: the settings left out take their defaults,
        the version moves to 2, the id stays
      - TST-ACC-TRX-088
    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
    category: concurrency
    test_bindings:
      - file: >-
          services-accounting:modules/transactions/tests/integration/services/persistence/customer-terms.integration.spec.js
        assertion: 'it creates the record without a version, a UUIDv7 id, at version 1'
        provenance: test
        source: >-
          services-accounting:modules/transactions/tests/integration/services/persistence/customer-terms.integration.spec.js#it
          creates the record without a version, a UUIDv7 id, at version 1
      - file: >-
          services-accounting:modules/transactions/tests/integration/services/persistence/customer-terms.integration.spec.js
        assertion: >-
          it refuses a create over the existing record (no version sent),
          writing nothing
        provenance: test
        source: >-
          services-accounting:modules/transactions/tests/integration/services/persistence/customer-terms.integration.spec.js#it
          refuses a create over the existing record (no version sent), writing
          nothing
      - file: >-
          services-accounting:modules/transactions/tests/integration/services/persistence/customer-terms.integration.spec.js
        assertion: 'it refuses a replacement at a stale version, writing nothing'
        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
      - file: >-
          services-accounting:modules/transactions/tests/integration/services/persistence/customer-terms.integration.spec.js
        assertion: >-
          it replaces the record whole: the settings left out take their
          defaults, the version moves to 2, the id stays
        provenance: test
        source: >-
          services-accounting:modules/transactions/tests/integration/services/persistence/customer-terms.integration.spec.js#it
          replaces the record whole: the settings left out take their defaults,
          the version moves to 2, the id stays
    binding_review: []
  - id: ATS-ACC-TRX-019-03
    title: Invalid collection configuration is rejected
    level: api
    proves:
      - BR-CAP-ACC-TRX-019-03
    preconditions: Inactive and foreign terms are available.
    steps:
      - do: Use each as default and submit an unknown collection standing.
        provenance: test
        source: >-
          services-accounting:modules/transactions/tests/integration/services/persistence/customer-terms.integration.spec.js#it
          refuses inactive terms, naming the field
    expected: Each attempted save refuses the invalid configuration.
    negative: true
    data_needs: Payment terms across workspace boundaries.
    bound_to:
      - >-
        services-accounting:modules/transactions/tests/integration/services/persistence/customer-terms.integration.spec.js#it
        refuses inactive terms, naming the field
      - >-
        services-accounting:modules/transactions/tests/integration/services/persistence/customer-terms.integration.spec.js#it
        refuses another tenant’s terms: the other tenant’s net 30 is not this
        one’s when this one has none
      - >-
        services-accounting:modules/transactions/tests/integration/services/persistence/customer-terms.integration.spec.js#it
        refuses a collection status and a remitting agreement outside their
        vocabularies
      - TST-ACC-TRX-088
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/persistence/customer-terms.integration.spec.js#it
      refuses inactive terms, naming the field
    category: validation
    test_bindings:
      - file: >-
          services-accounting:modules/transactions/tests/integration/services/persistence/customer-terms.integration.spec.js
        assertion: 'it refuses inactive terms, naming the field'
        provenance: test
        source: >-
          services-accounting:modules/transactions/tests/integration/services/persistence/customer-terms.integration.spec.js#it
          refuses inactive terms, naming the field
      - file: >-
          services-accounting:modules/transactions/tests/integration/services/persistence/customer-terms.integration.spec.js
        assertion: >-
          it refuses another tenant’s terms: the other tenant’s net 30 is not
          this one’s when this one has none
        provenance: test
        source: >-
          services-accounting:modules/transactions/tests/integration/services/persistence/customer-terms.integration.spec.js#it
          refuses another tenant’s terms: the other tenant’s net 30 is not this
          one’s when this one has none
      - file: >-
          services-accounting:modules/transactions/tests/integration/services/persistence/customer-terms.integration.spec.js
        assertion: >-
          it refuses a collection status and a remitting agreement outside their
          vocabularies
        provenance: test
        source: >-
          services-accounting:modules/transactions/tests/integration/services/persistence/customer-terms.integration.spec.js#it
          refuses a collection status and a remitting agreement outside their
          vocabularies
    binding_review: []
  - id: ATS-ACC-TRX-019-04
    title: Versioned removal restores defaults
    level: api
    proves:
      - BR-CAP-ACC-TRX-019-04
    preconditions: The party has saved customer terms.
    steps:
      - do: Delete with an obsolete and then current version and read again.
        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
    expected: Obsolete removal preserves the record and valid removal restores defaults.
    negative: false
    data_needs: A saved customer override.
    bound_to:
      - >-
        services-accounting:modules/transactions/tests/integration/services/persistence/customer-terms.integration.spec.js#it
        refuses a delete at a stale version, keeping the record
      - >-
        services-accounting:modules/transactions/tests/integration/services/persistence/customer-terms.integration.spec.js#it
        answers the defaults the party now has
      - TST-ACC-TRX-088
    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
    category: transition
    test_bindings:
      - file: >-
          services-accounting:modules/transactions/tests/integration/services/persistence/customer-terms.integration.spec.js
        assertion: 'it refuses a delete at a stale version, keeping the record'
        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
      - file: >-
          services-accounting:modules/transactions/tests/integration/services/persistence/customer-terms.integration.spec.js
        assertion: it answers the defaults the party now has
        provenance: test
        source: >-
          services-accounting:modules/transactions/tests/integration/services/persistence/customer-terms.integration.spec.js#it
          answers the defaults the party now has
    binding_review: []
  - id: ATS-ACC-TRX-019-05
    title: Referenced payment terms cannot be removed
    level: unit
    proves:
      - BR-CAP-ACC-TRX-019-05
      - INV-DOM-ACC-TRX-005-04
    preconditions: A customer uses a term definition as default.
    steps:
      - do: Delete that definition.
        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)
    expected: Dependency conflict prevents removal.
    negative: true
    data_needs: A referenced default term.
    bound_to:
      - >-
        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)
      - TST-ACC-TRX-088
    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)
    category: invariant
    test_bindings:
      - file: >-
          services-accounting:modules/transactions/tests/integration/services/persistence/customer-terms.integration.spec.js
        assertion: 'it keeps terms a party names from being deleted (409, the key)'
        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)
    binding_review: []
  - id: ATS-ACC-TRX-019-06
    title: Manage authority does not follow read access
    level: api
    proves:
      - BR-CAP-ACC-TRX-019-06
    preconditions: Reader and outsider identities exist.
    steps:
      - do: 'Read as both, then write and remove as reader.'
        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
    expected: 'Only the reader inspects, and its mutations are denied.'
    negative: true
    data_needs: Separate permission personas.
    bound_to:
      - >-
        services-accounting:modules/transactions/tests/e2e/customer-terms.e2e.spec.js#it
        reads with accounting.customer-terms.read alone and refuses a principal
        without it (403)
      - >-
        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
      - TST-ACC-TRX-006
    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
    category: permission
    test_bindings:
      - file: >-
          services-accounting:modules/transactions/tests/e2e/customer-terms.e2e.spec.js
        assertion: >-
          it reads with accounting.customer-terms.read alone and refuses a
          principal without it (403)
        provenance: test
        source: >-
          services-accounting:modules/transactions/tests/e2e/customer-terms.e2e.spec.js#it
          reads with accounting.customer-terms.read alone and refuses a
          principal without it (403)
      - file: >-
          services-accounting:modules/transactions/tests/e2e/customer-terms.e2e.spec.js
        assertion: >-
          it refuses the write and the delete without
          accounting.customer-terms.manage (403), the reader’s key not enough
        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
    binding_review: []
  - id: ATS-ACC-TRX-019-07
    title: Customer-term protection blocks mutations
    level: api
    proves:
      - BR-CAP-ACC-TRX-019-08
    preconditions: Saved terms have full update and delete protection.
    steps:
      - do: Attempt replacement and removal.
        provenance: test
        source: >-
          services-accounting:modules/transactions/tests/integration/services/persistence/customer-terms.integration.spec.js#it
          refuses a replacement (409)
    expected: Both failures retain the saved terms.
    negative: true
    data_needs: A fully locked terms record.
    bound_to:
      - >-
        services-accounting:modules/transactions/tests/integration/services/persistence/customer-terms.integration.spec.js#it
        refuses a replacement (409)
      - >-
        services-accounting:modules/transactions/tests/integration/services/persistence/customer-terms.integration.spec.js#it
        refuses a delete (409)
      - TST-ACC-TRX-088
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/persistence/customer-terms.integration.spec.js#it
      refuses a replacement (409)
    category: failure
    test_bindings:
      - file: >-
          services-accounting:modules/transactions/tests/integration/services/persistence/customer-terms.integration.spec.js
        assertion: it refuses a replacement (409)
        provenance: test
        source: >-
          services-accounting:modules/transactions/tests/integration/services/persistence/customer-terms.integration.spec.js#it
          refuses a replacement (409)
      - file: >-
          services-accounting:modules/transactions/tests/integration/services/persistence/customer-terms.integration.spec.js
        assertion: it refuses a delete (409)
        provenance: test
        source: >-
          services-accounting:modules/transactions/tests/integration/services/persistence/customer-terms.integration.spec.js#it
          refuses a delete (409)
    binding_review: []
  - id: ATS-ACC-TRX-019-08
    title: Saved collection choices reach billing through the service boundary
    category: interaction
    level: api
    proves:
      - BR-CAP-ACC-TRX-019-01
      - BR-CAP-ACC-TRX-019-02
      - BR-CAP-ACC-TRX-019-06
      - BR-CAP-ACC-TRX-001-05
      - BR-CAP-ACC-TRX-017-02
      - BR-CAP-ACC-TRX-020-01
    exercises:
      - CAP-ACC-TRX-019
      - CAP-ACC-TRX-001
      - CAP-ACC-TRX-017
      - CAP-ACC-TRX-020
    preconditions: >-
      An isolated workspace has eligible customers, products, matching accounts,
      an open period and two open batches. Each branch owns separate financial
      records.
    steps:
      - do: >-
          Save forty-five-day customer terms, retrieve them through Commerce’s
          billing function, create a bill without explicit terms and inspect its
          current financial standing. Create another bill with an explicit due
          date.
        provenance: proposed
        source: >-
          services-accounting:modules/transactions/tests/e2e/customer-terms.e2e.spec.js#it
          answers the defaults, saying so, before Acme has a record;
          services-accounting:modules/transactions/tests/integration/services/persistence/customer-terms.integration.spec.js#it
          refuses a replacement at a stale version, writing nothing;
          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;
          rhythm-v2-docs:specs/accounting/transactions/planning/capabilities/CAP-ACC-TRX-019-record-a-customer-s-collection-terms.md#BR-CAP-ACC-TRX-019-01;
          rhythm-v2-docs:specs/accounting/transactions/planning/capabilities/CAP-ACC-TRX-019-record-a-customer-s-collection-terms.md#BR-CAP-ACC-TRX-019-02;
          rhythm-v2-docs:specs/accounting/transactions/planning/capabilities/CAP-ACC-TRX-019-record-a-customer-s-collection-terms.md#BR-CAP-ACC-TRX-019-06;
          rhythm-v2-docs:specs/accounting/transactions/planning/capabilities/CAP-ACC-TRX-001-bill-a-customer-with-an-invoice.md#BR-CAP-ACC-TRX-001-05;
          rhythm-v2-docs:specs/accounting/transactions/planning/capabilities/CAP-ACC-TRX-017-know-where-a-customer-stands.md#BR-CAP-ACC-TRX-017-02;
          rhythm-v2-docs:specs/accounting/transactions/planning/capabilities/CAP-ACC-TRX-020-let-commerce-and-the-processor-work-with-accounting-safely.md#BR-CAP-ACC-TRX-020-01
    expected: >-
      The first bill uses the saved default and the second retains the explicit
      date; standing classifies each debt from its resolved deadline; the
      service read remains separately authorized.
    negative: false
    data_needs: >-
      Separate command keys, two customers, invoice lines, receipts and credit;
      controlled processor outcomes and a fixed calendar where the branch
      requires them.
    bound_to: []
    provenance: proposed
    source: >-
      services-accounting:modules/transactions/tests/e2e/customer-terms.e2e.spec.js#it
      answers the defaults, saying so, before Acme has a record;
      services-accounting:modules/transactions/tests/integration/services/persistence/customer-terms.integration.spec.js#it
      refuses a replacement at a stale version, writing nothing;
      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;
      rhythm-v2-docs:specs/accounting/transactions/planning/capabilities/CAP-ACC-TRX-019-record-a-customer-s-collection-terms.md#BR-CAP-ACC-TRX-019-01;
      rhythm-v2-docs:specs/accounting/transactions/planning/capabilities/CAP-ACC-TRX-019-record-a-customer-s-collection-terms.md#BR-CAP-ACC-TRX-019-02;
      rhythm-v2-docs:specs/accounting/transactions/planning/capabilities/CAP-ACC-TRX-019-record-a-customer-s-collection-terms.md#BR-CAP-ACC-TRX-019-06;
      rhythm-v2-docs:specs/accounting/transactions/planning/capabilities/CAP-ACC-TRX-001-bill-a-customer-with-an-invoice.md#BR-CAP-ACC-TRX-001-05;
      rhythm-v2-docs:specs/accounting/transactions/planning/capabilities/CAP-ACC-TRX-017-know-where-a-customer-stands.md#BR-CAP-ACC-TRX-017-02;
      rhythm-v2-docs:specs/accounting/transactions/planning/capabilities/CAP-ACC-TRX-020-let-commerce-and-the-processor-work-with-accounting-safely.md#BR-CAP-ACC-TRX-020-01
    test_bindings: []
    binding_review: []
  - id: ATS-ACC-TRX-019-09
    title: Collection choices handle empty and maximum allow-lists
    category: boundary
    level: api
    proves:
      - BR-CAP-ACC-TRX-019-03
      - INV-DOM-ACC-TRX-005-03
    preconditions: >-
      The customer has no saved override and fifty-one distinct supported
      collection options are available.
    steps:
      - do: >-
          Save an empty allow-list, replace it with fifty unique options, then
          attempt fifty-one options and a duplicate option.
        provenance: proposed
        source: >-
          services-accounting:modules/transactions/services/persistence/customer-terms.ts;
          services-accounting:modules/transactions/db/customer-terms.table.ts;
          services-accounting:modules/transactions/tests/integration/services/persistence/customer-terms.integration.spec.js#it
          stores an empty allow-list as no allow-list;
          services-accounting:modules/transactions/aws/api/customer-terms.schemas.ts
    expected: >-
      Empty selection becomes unrestricted; fifty unique options are retained;
      excessive and duplicate selections are refused without replacing the last
      valid record.
    negative: true
    data_needs: >-
      Branch-owned records in one configured workspace, valid accounting context
      and controlled requests at the stated boundary.
    bound_to: []
    provenance: proposed
    source: >-
      services-accounting:modules/transactions/services/persistence/customer-terms.ts;
      services-accounting:modules/transactions/db/customer-terms.table.ts;
      services-accounting:modules/transactions/tests/integration/services/persistence/customer-terms.integration.spec.js#it
      stores an empty allow-list as no allow-list;
      services-accounting:modules/transactions/aws/api/customer-terms.schemas.ts
    test_bindings: []
    binding_review: []
evidence:
  - >-
    services-accounting at f47cb263875bbc0c5640fba7dae6785ec32695f8: the test
    files named in bound_to.
  - >-
    rhythm-v2-docs:specs/accounting/transactions/design: related workflows,
    domain invariants and state transitions examined for the back-fill.
coverage:
  rule: 'gap: FND-ACC-TRX-084'
  transition: covered
  validation: covered
  permission: covered
  edge: 'gap: FND-ACC-TRX-084'
  failure: covered
  boundary: covered
  concurrency: covered
  invariant: covered
  interaction: covered
coverage_notes:
  rule: >-
    No dedicated rule scenario covers the applicable conditions; the finding
    identifies the remaining specification work.
  edge: >-
    No dedicated edge scenario covers the applicable conditions; the finding
    identifies the remaining specification work.
interaction_coverage:
  - to: CAP-ACC-TRX-001
    scenarios:
      - ATS-ACC-TRX-019-08
    provenance: proposed
    source: >-
      services-accounting:modules/transactions/tests/e2e/customer-terms.e2e.spec.js#it
      answers the defaults, saying so, before Acme has a record;
      services-accounting:modules/transactions/tests/integration/services/persistence/customer-terms.integration.spec.js#it
      refuses a replacement at a stale version, writing nothing;
      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;
      rhythm-v2-docs:specs/accounting/transactions/planning/capabilities/CAP-ACC-TRX-019-record-a-customer-s-collection-terms.md#BR-CAP-ACC-TRX-019-01;
      rhythm-v2-docs:specs/accounting/transactions/planning/capabilities/CAP-ACC-TRX-019-record-a-customer-s-collection-terms.md#BR-CAP-ACC-TRX-019-02;
      rhythm-v2-docs:specs/accounting/transactions/planning/capabilities/CAP-ACC-TRX-019-record-a-customer-s-collection-terms.md#BR-CAP-ACC-TRX-019-06;
      rhythm-v2-docs:specs/accounting/transactions/planning/capabilities/CAP-ACC-TRX-001-bill-a-customer-with-an-invoice.md#BR-CAP-ACC-TRX-001-05;
      rhythm-v2-docs:specs/accounting/transactions/planning/capabilities/CAP-ACC-TRX-017-know-where-a-customer-stands.md#BR-CAP-ACC-TRX-017-02;
      rhythm-v2-docs:specs/accounting/transactions/planning/capabilities/CAP-ACC-TRX-020-let-commerce-and-the-processor-work-with-accounting-safely.md#BR-CAP-ACC-TRX-020-01
  - to: CAP-ACC-TRX-017
    scenarios:
      - ATS-ACC-TRX-019-08
    provenance: proposed
    source: >-
      services-accounting:modules/transactions/tests/e2e/customer-terms.e2e.spec.js#it
      answers the defaults, saying so, before Acme has a record;
      services-accounting:modules/transactions/tests/integration/services/persistence/customer-terms.integration.spec.js#it
      refuses a replacement at a stale version, writing nothing;
      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;
      rhythm-v2-docs:specs/accounting/transactions/planning/capabilities/CAP-ACC-TRX-019-record-a-customer-s-collection-terms.md#BR-CAP-ACC-TRX-019-01;
      rhythm-v2-docs:specs/accounting/transactions/planning/capabilities/CAP-ACC-TRX-019-record-a-customer-s-collection-terms.md#BR-CAP-ACC-TRX-019-02;
      rhythm-v2-docs:specs/accounting/transactions/planning/capabilities/CAP-ACC-TRX-019-record-a-customer-s-collection-terms.md#BR-CAP-ACC-TRX-019-06;
      rhythm-v2-docs:specs/accounting/transactions/planning/capabilities/CAP-ACC-TRX-001-bill-a-customer-with-an-invoice.md#BR-CAP-ACC-TRX-001-05;
      rhythm-v2-docs:specs/accounting/transactions/planning/capabilities/CAP-ACC-TRX-017-know-where-a-customer-stands.md#BR-CAP-ACC-TRX-017-02;
      rhythm-v2-docs:specs/accounting/transactions/planning/capabilities/CAP-ACC-TRX-020-let-commerce-and-the-processor-work-with-accounting-safely.md#BR-CAP-ACC-TRX-020-01
  - to: CAP-ACC-TRX-020
    scenarios:
      - ATS-ACC-TRX-019-08
    provenance: proposed
    source: >-
      services-accounting:modules/transactions/tests/e2e/customer-terms.e2e.spec.js#it
      answers the defaults, saying so, before Acme has a record;
      services-accounting:modules/transactions/tests/integration/services/persistence/customer-terms.integration.spec.js#it
      refuses a replacement at a stale version, writing nothing;
      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;
      rhythm-v2-docs:specs/accounting/transactions/planning/capabilities/CAP-ACC-TRX-019-record-a-customer-s-collection-terms.md#BR-CAP-ACC-TRX-019-01;
      rhythm-v2-docs:specs/accounting/transactions/planning/capabilities/CAP-ACC-TRX-019-record-a-customer-s-collection-terms.md#BR-CAP-ACC-TRX-019-02;
      rhythm-v2-docs:specs/accounting/transactions/planning/capabilities/CAP-ACC-TRX-019-record-a-customer-s-collection-terms.md#BR-CAP-ACC-TRX-019-06;
      rhythm-v2-docs:specs/accounting/transactions/planning/capabilities/CAP-ACC-TRX-001-bill-a-customer-with-an-invoice.md#BR-CAP-ACC-TRX-001-05;
      rhythm-v2-docs:specs/accounting/transactions/planning/capabilities/CAP-ACC-TRX-017-know-where-a-customer-stands.md#BR-CAP-ACC-TRX-017-02;
      rhythm-v2-docs:specs/accounting/transactions/planning/capabilities/CAP-ACC-TRX-020-let-commerce-and-the-processor-work-with-accounting-safely.md#BR-CAP-ACC-TRX-020-01
transition_coverage: []
permission_coverage:
  - key: accounting.customer-terms.read
    where_checked: api
    gap: FND-ACC-TRX-084
    provenance: unknown
    source: FND-ACC-TRX-084
    note: >-
      Existing permission scenarios are retained; assertion-level coverage of
      this grant at every declared surface remains unverified.
    evidence:
      - >-
        rhythm-v2-docs:specs/accounting/transactions/planning/capabilities/CAP-ACC-TRX-019-record-a-customer-s-collection-terms.md#CAP-ACC-TRX-019
  - key: accounting.customer-terms.manage
    where_checked: api
    gap: FND-ACC-TRX-084
    provenance: unknown
    source: FND-ACC-TRX-084
    note: >-
      Existing permission scenarios are retained; assertion-level coverage of
      this grant at every declared surface remains unverified.
    evidence:
      - >-
        rhythm-v2-docs:specs/accounting/transactions/planning/capabilities/CAP-ACC-TRX-019-record-a-customer-s-collection-terms.md#CAP-ACC-TRX-019
rule_coverage:
  - rule: BR-CAP-ACC-TRX-019-01
    scenarios:
      - ATS-ACC-TRX-019-01
      - ATS-ACC-TRX-019-08
    provenance: proposed
    source: >-
      services-accounting:modules/transactions/tests/e2e/customer-terms.e2e.spec.js#it
      answers the defaults, saying so, before Acme has a record
  - rule: BR-CAP-ACC-TRX-019-02
    scenarios:
      - ATS-ACC-TRX-019-02
      - ATS-ACC-TRX-019-08
    provenance: proposed
    source: >-
      services-accounting:modules/transactions/tests/integration/services/persistence/customer-terms.integration.spec.js#it
      refuses a replacement at a stale version, writing nothing
  - rule: BR-CAP-ACC-TRX-019-03
    scenarios:
      - ATS-ACC-TRX-019-03
    provenance: proposed
    source: >-
      services-accounting:modules/transactions/aws/api/customer-terms.schemas.ts:customerTermsPutSchema
  - rule: BR-CAP-ACC-TRX-019-04
    scenarios:
      - ATS-ACC-TRX-019-04
    provenance: proposed
    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
  - rule: BR-CAP-ACC-TRX-019-05
    scenarios:
      - ATS-ACC-TRX-019-05
    provenance: proposed
    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)
  - rule: BR-CAP-ACC-TRX-019-06
    scenarios:
      - ATS-ACC-TRX-019-06
      - ATS-ACC-TRX-019-08
    provenance: proposed
    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
  - rule: BR-CAP-ACC-TRX-019-08
    scenarios:
      - ATS-ACC-TRX-019-07
    provenance: proposed
    source: >-
      services-accounting:modules/transactions/services/persistence/customer-terms.ts
executable_gaps:
  - scenario: ATS-ACC-TRX-019-08
    gap: FND-ACC-TRX-084
    provenance: unknown
    source: FND-ACC-TRX-084
    evidence:
      - >-
        services-accounting:modules/transactions/tests/e2e/customer-terms.e2e.spec.js#it
        answers the defaults, saying so, before Acme has a record;
        services-accounting:modules/transactions/tests/integration/services/persistence/customer-terms.integration.spec.js#it
        refuses a replacement at a stale version, writing nothing;
        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
  - scenario: ATS-ACC-TRX-019-09
    gap: FND-ACC-TRX-084
    provenance: unknown
    source: FND-ACC-TRX-084
    evidence:
      - >-
        services-accounting:modules/transactions/services/persistence/customer-terms.ts;
        services-accounting:modules/transactions/db/customer-terms.table.ts;
        services-accounting:modules/transactions/tests/integration/services/persistence/customer-terms.integration.spec.js#it
        stores an empty allow-list as no allow-list;
        services-accounting:modules/transactions/aws/api/customer-terms.schemas.ts
invariant_coverage:
  - invariant: INV-DOM-ACC-TRX-005-01
    scenarios:
      - ATS-ACC-TRX-019-01
    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
    note: >-
      The cited scenario and its constituent test assertions are the proof
      boundary.
  - invariant: INV-DOM-ACC-TRX-005-02
    scenarios:
      - ATS-ACC-TRX-019-02
    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
    note: >-
      The cited scenario and its constituent test assertions are the proof
      boundary.
  - invariant: INV-DOM-ACC-TRX-005-03
    gap: FND-ACC-TRX-084
    provenance: unknown
    source: FND-ACC-TRX-084
    evidence:
      - >-
        services-accounting:modules/transactions/aws/api/customer-terms.schemas.ts:customerTermsPutSchema
    note: >-
      The complete invariant has no exact assertion binding in this
      specification; component evidence does not close the gap.
  - invariant: INV-DOM-ACC-TRX-005-04
    scenarios:
      - ATS-ACC-TRX-019-05
    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)
    note: >-
      The cited scenario and its constituent test assertions are the proof
      boundary.
  - invariant: INV-DOM-ACC-TRX-005-05
    gap: FND-ACC-TRX-084
    provenance: unknown
    source: FND-ACC-TRX-084
    evidence:
      - >-
        services-accounting:modules/transactions/services/persistence/customer-terms.ts
    note: >-
      The complete invariant has no exact assertion binding in this
      specification; component evidence does not close the gap.
  - invariant: INV-DOM-ACC-TRX-005-13
    gap: FND-ACC-TRX-084
    provenance: unknown
    source: FND-ACC-TRX-084
    evidence:
      - >-
        services-accounting:docs/milestones/plans/ACCT-M2-plan.md#7a. Entity
        capabilities (R2-ARCH-001)
    note: >-
      The complete invariant has no exact assertion binding in this
      specification; component evidence does not close the gap.
---

# Maintain customer-specific collection choices: Capability Test Specification

## Coverage

The category map separates specified examples from recorded gaps. The table lists a scenario or finding for each rule requiring proof; a listed scenario may still be proposed. Executable bindings cover their cited assertions, while the transition, permission and invariant registers identify combinations that need further proof.

| Required rule | Scenario or finding |
|---|---|
| `BR-CAP-ACC-TRX-019-01` | `ATS-ACC-TRX-019-01`, `ATS-ACC-TRX-019-08` |
| `BR-CAP-ACC-TRX-019-02` | `ATS-ACC-TRX-019-02`, `ATS-ACC-TRX-019-08` |
| `BR-CAP-ACC-TRX-019-03` | `ATS-ACC-TRX-019-03`, `ATS-ACC-TRX-019-09` |
| `BR-CAP-ACC-TRX-019-04` | `ATS-ACC-TRX-019-04` |
| `BR-CAP-ACC-TRX-019-05` | `ATS-ACC-TRX-019-05` |
| `BR-CAP-ACC-TRX-019-06` | `ATS-ACC-TRX-019-06`, `ATS-ACC-TRX-019-08` |
| `BR-CAP-ACC-TRX-019-08` | `ATS-ACC-TRX-019-07` |

## Interactions With Related Capabilities

Save forty-five-day customer terms, retrieve them through Commerce’s billing function, create a bill without explicit terms and inspect its current financial standing. Create another bill with an explicit due date.

The first bill uses the saved default and the second retains the explicit date; standing classifies each debt from its resolved deadline; the service read remains separately authorized. The complete chain remains proposed until one executable run proves its combined outcomes.
