---
id: ATS-ACC-PRD-016
scope: CAP-ACC-PRD-016
product_area: accounting
module: products
revision: 3
status: proposed
approved_by: null
approved_at: null
source_sha:
  services-accounting: f47cb263875bbc0c5640fba7dae6785ec32695f8
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
scenarios:
  - id: ATS-ACC-PRD-016-01
    title: Deferral requires its liability account
    level: api
    proves:
      - BR-CAP-ACC-PRD-016-01
    preconditions: A product can defer revenue.
    steps: Choose deferred treatment without its deferred revenue account.
    expected: The setup save fails.
    negative: true
    data_needs: A product can defer revenue.
    bound_to:
      - >-
        services-accounting:modules/products/tests/e2e/product-accounting.e2e.spec.js#answers 400 to deferral
        without a deferred revenue GL account
      - >-
        services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
        deferring revenue without a deferred revenue GL account
      - TST-ACC-PRD-026
      - TST-ACC-PRD-036
    provenance: test
    source: >-
      services-accounting:modules/products/tests/e2e/product-accounting.e2e.spec.js#answers 400 to deferral
      without a deferred revenue GL account
    category: validation
    binding_scope:
      - suite: TST-ACC-PRD-026
        assertions:
          - >-
            services-accounting:modules/products/tests/e2e/product-accounting.e2e.spec.js#answers 400 to
            deferral without a deferred revenue GL account
        provenance: test
        source: >-
          services-accounting:modules/products/tests/e2e/product-accounting.e2e.spec.js#answers 400 to
          deferral without a deferred revenue GL account;
          services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
          deferring revenue without a deferred revenue GL account
      - suite: TST-ACC-PRD-036
        assertions:
          - >-
            services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
            deferring revenue without a deferred revenue GL account
        provenance: test
        source: >-
          services-accounting:modules/products/tests/e2e/product-accounting.e2e.spec.js#answers 400 to
          deferral without a deferred revenue GL account;
          services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
          deferring revenue without a deferred revenue GL account
  - id: ATS-ACC-PRD-016-02
    title: Fixed allocation must be complete and unique
    level: unit
    proves:
      - BR-CAP-ACC-PRD-016-02
      - INV-DOM-ACC-PRD-004-06
    preconditions: A setup uses fixed-date recognition.
    steps: 'Try missing dates, incorrect totals, duplicate dates and exact fractional totals.'
    expected: Invalid configurations fail and exact distinct allocation succeeds.
    negative: true
    data_needs: A setup uses fixed-date recognition.
    bound_to:
      - >-
        services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
        percentages that add up to less than 100, in Rhythm 1.0’s words
      - >-
        services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
        the fixed_dates strategy without fixed dates
      - >-
        services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
        percentages that add up to more than 100
      - >-
        services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#accepts
        fractional percentages that add up to exactly 100
      - >-
        services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
        the same date twice
      - >-
        services-accounting:modules/products/tests/e2e/product-accounting.e2e.spec.js#answers 400 to fixed
        dates that do not total 100
      - 'react-console:acceptance/accounting/playwright/journeys/products/ACT-ACC-0119.spec.ts#ACT-ACC-0119'
      - TST-ACC-PRD-036
      - TST-ACC-PRD-026
      - TST-ACC-PRD-010
    provenance: test
    source: >-
      services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
      percentages that add up to less than 100, in Rhythm 1.0’s words
    category: boundary
    binding_scope:
      - suite: TST-ACC-PRD-036
        assertions:
          - >-
            services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
            percentages that add up to less than 100, in Rhythm 1.0’s words
          - >-
            services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
            the fixed_dates strategy without fixed dates
          - >-
            services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
            percentages that add up to more than 100
          - >-
            services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#accepts
            fractional percentages that add up to exactly 100
          - >-
            services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
            the same date twice
        provenance: test
        source: >-
          services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
          percentages that add up to less than 100, in Rhythm 1.0’s words;
          services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
          the fixed_dates strategy without fixed dates;
          services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
          percentages that add up to more than 100;
          services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#accepts
          fractional percentages that add up to exactly 100;
          services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
          the same date twice;
          services-accounting:modules/products/tests/e2e/product-accounting.e2e.spec.js#answers 400 to fixed
          dates that do not total 100;
          react-console:acceptance/accounting/playwright/journeys/products/ACT-ACC-0119.spec.ts#ACT-ACC-0119
      - suite: TST-ACC-PRD-026
        assertions:
          - >-
            services-accounting:modules/products/tests/e2e/product-accounting.e2e.spec.js#answers 400 to fixed
            dates that do not total 100
        provenance: test
        source: >-
          services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
          percentages that add up to less than 100, in Rhythm 1.0’s words;
          services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
          the fixed_dates strategy without fixed dates;
          services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
          percentages that add up to more than 100;
          services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#accepts
          fractional percentages that add up to exactly 100;
          services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
          the same date twice;
          services-accounting:modules/products/tests/e2e/product-accounting.e2e.spec.js#answers 400 to fixed
          dates that do not total 100;
          react-console:acceptance/accounting/playwright/journeys/products/ACT-ACC-0119.spec.ts#ACT-ACC-0119
      - suite: TST-ACC-PRD-010
        assertions:
          - 'react-console:acceptance/accounting/playwright/journeys/products/ACT-ACC-0119.spec.ts#ACT-ACC-0119'
        provenance: test
        source: >-
          services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
          percentages that add up to less than 100, in Rhythm 1.0’s words;
          services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
          the fixed_dates strategy without fixed dates;
          services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
          percentages that add up to more than 100;
          services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#accepts
          fractional percentages that add up to exactly 100;
          services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
          the same date twice;
          services-accounting:modules/products/tests/e2e/product-accounting.e2e.spec.js#answers 400 to fixed
          dates that do not total 100;
          react-console:acceptance/accounting/playwright/journeys/products/ACT-ACC-0119.spec.ts#ACT-ACC-0119
  - id: ATS-ACC-PRD-016-03
    title: Month coverage includes the year boundary
    level: unit
    proves:
      - BR-CAP-ACC-PRD-016-03
      - INV-DOM-ACC-PRD-004-07
    preconditions: A setup uses relative recognition.
    steps: 'Try missing rules, shared months, year-end overlaps and disjoint wrapping ranges.'
    expected: Invalid coverage fails and disjoint ranges are retained in starting-month order.
    negative: true
    data_needs: A setup uses relative recognition.
    bound_to:
      - >-
        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
      - >-
        services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
        the relative_dates strategy without relative rules
      - >-
        services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
        two ranges sharing a month, in Rhythm 1.0’s words
      - >-
        services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
        a range wrapping the year end overlapping the next, in Rhythm 1.0’s multi-year words
      - >-
        services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#accepts
        disjoint ranges, one wrapping the year end, and stores them by start month
      - >-
        services-accounting:modules/products/tests/e2e/product-accounting.e2e.spec.js#answers 400 to relative
        rules overlapping across the year end
      - TST-ACC-PRD-036
      - TST-ACC-PRD-026
    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
    category: edge
    binding_scope:
      - suite: TST-ACC-PRD-036
        assertions:
          - >-
            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
          - >-
            services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
            the relative_dates strategy without relative rules
          - >-
            services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
            two ranges sharing a month, in Rhythm 1.0’s words
          - >-
            services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
            a range wrapping the year end overlapping the next, in Rhythm 1.0’s multi-year words
          - >-
            services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#accepts
            disjoint ranges, one wrapping the year end, and stores them by start month
        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;
          services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
          the relative_dates strategy without relative rules;
          services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
          two ranges sharing a month, in Rhythm 1.0’s words;
          services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
          a range wrapping the year end overlapping the next, in Rhythm 1.0’s multi-year words;
          services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#accepts
          disjoint ranges, one wrapping the year end, and stores them by start month;
          services-accounting:modules/products/tests/e2e/product-accounting.e2e.spec.js#answers 400 to
          relative rules overlapping across the year end
      - suite: TST-ACC-PRD-026
        assertions:
          - >-
            services-accounting:modules/products/tests/e2e/product-accounting.e2e.spec.js#answers 400 to
            relative rules overlapping across the year end
        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;
          services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
          the relative_dates strategy without relative rules;
          services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
          two ranges sharing a month, in Rhythm 1.0’s words;
          services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
          a range wrapping the year end overlapping the next, in Rhythm 1.0’s multi-year words;
          services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#accepts
          disjoint ranges, one wrapping the year end, and stores them by start month;
          services-accounting:modules/products/tests/e2e/product-accounting.e2e.spec.js#answers 400 to
          relative rules overlapping across the year end
  - id: ATS-ACC-PRD-016-04
    title: Split kinds exclude the other value form
    level: unit
    proves:
      - BR-CAP-ACC-PRD-016-05
    preconditions: A setup can take revenue splits.
    steps: Supply both value forms for percentage and fixed splits.
    expected: Both configurations fail.
    negative: true
    data_needs: A setup can take revenue splits.
    bound_to:
      - >-
        services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
        a percentage split that also states an amount
      - >-
        services-accounting:modules/products/tests/unit/rules/product-rules.spec.js#refuses a fixed amount
        split that states a percentage
      - TST-ACC-PRD-036
      - TST-ACC-PRD-066
    provenance: test
    source: >-
      services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
      a percentage split that also states an amount
    category: validation
    binding_scope:
      - suite: TST-ACC-PRD-036
        assertions:
          - >-
            services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
            a percentage split that also states an amount
        provenance: test
        source: >-
          services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
          a percentage split that also states an amount;
          services-accounting:modules/products/tests/unit/rules/product-rules.spec.js#refuses a fixed amount
          split that states a percentage
      - suite: TST-ACC-PRD-066
        assertions:
          - >-
            services-accounting:modules/products/tests/unit/rules/product-rules.spec.js#refuses a fixed amount
            split that states a percentage
        provenance: test
        source: >-
          services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
          a percentage split that also states an amount;
          services-accounting:modules/products/tests/unit/rules/product-rules.spec.js#refuses a fixed amount
          split that states a percentage
  - id: ATS-ACC-PRD-016-05
    title: Split totals honor percentage and price limits
    level: unit
    proves:
      - BR-CAP-ACC-PRD-016-06
    preconditions: The product’s standard price is 5000 minor units.
    steps: Try percentages of 101 and 100 and fixed totals of 5001 and 5000.
    expected: Over-limit totals fail and exact limits succeed.
    negative: true
    data_needs: The product’s standard price is 5000 minor units.
    bound_to:
      - >-
        services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
        fixed amounts adding up to more than the standard base price
      - >-
        services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
        percentages that add up to more than 100, in Rhythm 1.0’s words
      - >-
        services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#accepts
        percentages that add up to exactly 100
      - >-
        services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#accepts
        fixed amounts adding up to the standard base price
      - >-
        services-accounting:modules/products/tests/unit/rules/product-rules.spec.js#refuses fixed amounts
        above the product’s price, which Rhythm 1.0 summed as NaN and passed
      - >-
        services-accounting:modules/products/tests/e2e/product-accounting.e2e.spec.js#answers 400 to fixed
        revenue splits above the product’s price
      - TST-ACC-PRD-036
      - TST-ACC-PRD-066
      - TST-ACC-PRD-026
    provenance: test
    source: >-
      services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
      fixed amounts adding up to more than the standard base price
    category: boundary
    binding_scope:
      - suite: TST-ACC-PRD-036
        assertions:
          - >-
            services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
            fixed amounts adding up to more than the standard base price
          - >-
            services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
            percentages that add up to more than 100, in Rhythm 1.0’s words
          - >-
            services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#accepts
            percentages that add up to exactly 100
          - >-
            services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#accepts
            fixed amounts adding up to the standard base price
        provenance: test
        source: >-
          services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
          fixed amounts adding up to more than the standard base price;
          services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
          percentages that add up to more than 100, in Rhythm 1.0’s words;
          services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#accepts
          percentages that add up to exactly 100;
          services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#accepts
          fixed amounts adding up to the standard base price;
          services-accounting:modules/products/tests/unit/rules/product-rules.spec.js#refuses fixed amounts
          above the product’s price, which Rhythm 1.0 summed as NaN and passed;
          services-accounting:modules/products/tests/e2e/product-accounting.e2e.spec.js#answers 400 to fixed
          revenue splits above the product’s price
      - suite: TST-ACC-PRD-066
        assertions:
          - >-
            services-accounting:modules/products/tests/unit/rules/product-rules.spec.js#refuses fixed amounts
            above the product’s price, which Rhythm 1.0 summed as NaN and passed
        provenance: test
        source: >-
          services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
          fixed amounts adding up to more than the standard base price;
          services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
          percentages that add up to more than 100, in Rhythm 1.0’s words;
          services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#accepts
          percentages that add up to exactly 100;
          services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#accepts
          fixed amounts adding up to the standard base price;
          services-accounting:modules/products/tests/unit/rules/product-rules.spec.js#refuses fixed amounts
          above the product’s price, which Rhythm 1.0 summed as NaN and passed;
          services-accounting:modules/products/tests/e2e/product-accounting.e2e.spec.js#answers 400 to fixed
          revenue splits above the product’s price
      - suite: TST-ACC-PRD-026
        assertions:
          - >-
            services-accounting:modules/products/tests/e2e/product-accounting.e2e.spec.js#answers 400 to fixed
            revenue splits above the product’s price
        provenance: test
        source: >-
          services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
          fixed amounts adding up to more than the standard base price;
          services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
          percentages that add up to more than 100, in Rhythm 1.0’s words;
          services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#accepts
          percentages that add up to exactly 100;
          services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#accepts
          fixed amounts adding up to the standard base price;
          services-accounting:modules/products/tests/unit/rules/product-rules.spec.js#refuses fixed amounts
          above the product’s price, which Rhythm 1.0 summed as NaN and passed;
          services-accounting:modules/products/tests/e2e/product-accounting.e2e.spec.js#answers 400 to fixed
          revenue splits above the product’s price
  - id: ATS-ACC-PRD-016-06
    title: Split identities remain distinct
    level: unit
    proves:
      - BR-CAP-ACC-PRD-016-07
    preconditions: A saved setup contains revenue splits.
    steps: 'Resend an existing identity, provide a new identity and duplicate one identity.'
    expected: Supplied unique identities remain and duplicates fail.
    negative: true
    data_needs: A saved setup contains revenue splits.
    bound_to:
      - >-
        services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#keeps
        the id of a split sent back
      - >-
        services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#keeps
        the id a new split is sent with
      - >-
        services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
        two splits with the same id
      - >-
        services-accounting:modules/products/tests/e2e/product-accounting.e2e.spec.js#replaces the splits as a
        whole, keeping the id sent back
      - TST-ACC-PRD-036
      - TST-ACC-PRD-026
    provenance: test
    source: >-
      services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#keeps
      the id of a split sent back
    category: invariant
    binding_scope:
      - suite: TST-ACC-PRD-036
        assertions:
          - >-
            services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#keeps
            the id of a split sent back
          - >-
            services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#keeps
            the id a new split is sent with
          - >-
            services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
            two splits with the same id
        provenance: test
        source: >-
          services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#keeps
          the id of a split sent back;
          services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#keeps
          the id a new split is sent with;
          services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
          two splits with the same id;
          services-accounting:modules/products/tests/e2e/product-accounting.e2e.spec.js#replaces the splits as
          a whole, keeping the id sent back
      - suite: TST-ACC-PRD-026
        assertions:
          - >-
            services-accounting:modules/products/tests/e2e/product-accounting.e2e.spec.js#replaces the splits
            as a whole, keeping the id sent back
        provenance: test
        source: >-
          services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#keeps
          the id of a split sent back;
          services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#keeps
          the id a new split is sent with;
          services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
          two splits with the same id;
          services-accounting:modules/products/tests/e2e/product-accounting.e2e.spec.js#replaces the splits as
          a whole, keeping the id sent back
  - id: ATS-ACC-PRD-016-07
    title: Inter-entity accounts belong to the other unit
    level: unit
    proves:
      - BR-CAP-ACC-PRD-016-08
    preconditions: Three units provide account fixtures.
    steps: 'Try own-unit, repeated-unit, missing-unit and wrongly scoped account entries, then a valid entry.'
    expected: Invalid relationships fail and the valid other-unit entry succeeds.
    negative: true
    data_needs: Three units provide account fixtures.
    bound_to:
      - >-
        services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
        a liability account of a third unit
      - >-
        services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
        an entry for the product’s own business unit
      - >-
        services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
        two entries for the same unit
      - >-
        services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
        a business unit the tenant does not have
      - >-
        services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
        a receivable account of the product’s own unit
      - >-
        services-accounting:modules/products/tests/e2e/product-accounting.e2e.spec.js#answers 400 to an
        inter-entity entry naming the product’s own unit
      - TST-ACC-PRD-036
      - TST-ACC-PRD-026
    provenance: test
    source: >-
      services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
      a liability account of a third unit
    category: validation
    binding_scope:
      - suite: TST-ACC-PRD-036
        assertions:
          - >-
            services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
            a liability account of a third unit
          - >-
            services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
            an entry for the product’s own business unit
          - >-
            services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
            two entries for the same unit
          - >-
            services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
            a business unit the tenant does not have
          - >-
            services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
            a receivable account of the product’s own unit
        provenance: test
        source: >-
          services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
          a liability account of a third unit;
          services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
          an entry for the product’s own business unit;
          services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
          two entries for the same unit;
          services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
          a business unit the tenant does not have;
          services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
          a receivable account of the product’s own unit;
          services-accounting:modules/products/tests/e2e/product-accounting.e2e.spec.js#answers 400 to an
          inter-entity entry naming the product’s own unit
      - suite: TST-ACC-PRD-026
        assertions:
          - >-
            services-accounting:modules/products/tests/e2e/product-accounting.e2e.spec.js#answers 400 to an
            inter-entity entry naming the product’s own unit
        provenance: test
        source: >-
          services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
          a liability account of a third unit;
          services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
          an entry for the product’s own business unit;
          services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
          two entries for the same unit;
          services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
          a business unit the tenant does not have;
          services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js#refuses
          a receivable account of the product’s own unit;
          services-accounting:modules/products/tests/e2e/product-accounting.e2e.spec.js#answers 400 to an
          inter-entity entry naming the product’s own unit
  - id: ATS-ACC-PRD-016-08
    title: Setup child collections reach their separate limits
    category: boundary
    level: api
    proves:
      - BR-CAP-ACC-PRD-016-09
    preconditions: A valid setup has eligible accounts and distinct other-unit fixtures.
    steps: 'Save fifty revenue splits and two hundred inter-entity entries, then exceed each limit separately.'
    expected: >-
      Each maximum saves successfully; either excessive collection refuses the replacement without changing
      the setup.
    negative: true
    data_needs: A valid setup has eligible accounts and distinct other-unit fixtures.
    bound_to: []
    provenance: proposed
    source: >-
      services-accounting:modules/products/services/persistence/product-accounting-setups.ts:replaceProductAccounting
    binding_scope: []
  - id: ATS-ACC-PRD-016-09
    title: A lower price affects the next revenue-share save
    category: interaction
    level: api
    proves:
      - BR-CAP-ACC-PRD-016-06
      - BR-CAP-ACC-PRD-008-12
      - BR-CAP-ACC-PRD-011-06
      - INV-DOM-ACC-PRD-004-08
    preconditions: A bundle has a standard price and existing fixed shares.
    steps: >-
      Lower the grid price with compatible component totals, inspect the existing shares, then resubmit those
      shares as a setup replacement.
    expected: >-
      The product edit does not rewrite the setup; the later setup replacement rejects shares above its new
      price limit.
    negative: true
    data_needs: A bundle has a standard price and existing fixed shares.
    bound_to: []
    provenance: proposed
    source: >-
      services-accounting:modules/products/services/rules/product-rules.ts:listPrice;
      services-accounting:modules/products/services/rules/product-rules.ts:revenueSplitsProblem;
      services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
      more than 500 prices (the bound of the grid);
      services-accounting:modules/products/services/rules/product-rules.ts:listPrice;
      services-accounting:modules/products/services/rules/product-rules.ts:bundleTotalsProblem
    exercises:
      - CAP-ACC-PRD-016
      - CAP-ACC-PRD-008
      - CAP-ACC-PRD-011
    binding_scope: []
evidence:
  - 'react-console:acceptance/accounting/playwright/journeys/products/ACT-ACC-0119.spec.ts'
  - 'services-accounting:modules/products/services/persistence/product-accounting-setups.ts'
  - 'services-accounting:modules/products/services/rules/product-rules.ts'
  - 'services-accounting:modules/products/tests/e2e/product-accounting.e2e.spec.js'
  - >-
    services-accounting:modules/products/tests/integration/services/persistence/product-accounting-setups.integration.spec.js
  - 'services-accounting:modules/products/tests/unit/rules/product-rules.spec.js'
  - >-
    rhythm-v2-docs:specs/accounting/products/design/workflows/WF-ACC-PRD-002-save-a-product-and-its-accounting-setup-from.md
  - >-
    rhythm-v2-docs:specs/accounting/products/design/workflows/WF-ACC-PRD-005-save-many-accounting-setups-at-once.md
coverage:
  rule: 'gap: FND-ACC-PRD-065'
  transition: 'gap: FND-ACC-PRD-065'
  validation: covered
  permission: 'gap: FND-ACC-PRD-065'
  edge: covered
  failure: 'gap: FND-ACC-PRD-065'
  boundary: covered
  concurrency: 'gap: FND-ACC-PRD-065'
  invariant: covered
  interaction: covered
coverage_notes:
  rule:
    reason: No dedicated scenario isolates this category for the capability.
    provenance: unknown
    source: FND-ACC-PRD-065
  transition:
    reason: No dedicated scenario isolates this category for the capability.
    provenance: unknown
    source: FND-ACC-PRD-065
  permission:
    reason: No dedicated scenario isolates this category for the capability.
    provenance: unknown
    source: FND-ACC-PRD-065
  failure:
    reason: No dedicated scenario isolates this category for the capability.
    provenance: unknown
    source: FND-ACC-PRD-065
  concurrency:
    reason: No dedicated scenario isolates this category for the capability.
    provenance: unknown
    source: FND-ACC-PRD-065
  remaining_obligations:
    reason: >-
      Maximum child-collection successes and refusals, price-lowering effects on later setup saves, permission
      combinations and concurrent price/setup changes need execution. Workflow edges not named by a scenario
      remain in this finding rather than gaining a binding from shared workflow membership.
    provenance: unknown
    source: FND-ACC-PRD-065
  meaning:
    reason: >-
      Covered means a specification scenario exists in this category. Executable coverage and run results
      remain independent.
    provenance: documented
    source: 'rhythm-v2-docs:specs/CONVENTIONS.md#9.10 Capability Test Specification (`ATS`, under `design/tests/`)'
coverage_findings:
  - FND-ACC-PRD-065
related_capabilities:
  - CAP-ACC-PRD-008
  - CAP-ACC-PRD-011
workflows:
  - WF-ACC-PRD-002
  - WF-ACC-PRD-005
rule_coverage:
  - rule: BR-CAP-ACC-PRD-016-01
    scenarios:
      - ATS-ACC-PRD-016-01
  - rule: BR-CAP-ACC-PRD-016-02
    scenarios:
      - ATS-ACC-PRD-016-02
  - rule: BR-CAP-ACC-PRD-016-03
    scenarios:
      - ATS-ACC-PRD-016-03
  - rule: BR-CAP-ACC-PRD-016-05
    scenarios:
      - ATS-ACC-PRD-016-04
  - rule: BR-CAP-ACC-PRD-016-06
    scenarios:
      - ATS-ACC-PRD-016-05
      - ATS-ACC-PRD-016-09
  - rule: BR-CAP-ACC-PRD-016-07
    scenarios:
      - ATS-ACC-PRD-016-06
  - rule: BR-CAP-ACC-PRD-016-08
    scenarios:
      - ATS-ACC-PRD-016-07
  - rule: BR-CAP-ACC-PRD-016-09
    scenarios:
      - ATS-ACC-PRD-016-08
interaction_coverage:
  - scenario: ATS-ACC-PRD-016-09
    exercises:
      - CAP-ACC-PRD-016
      - CAP-ACC-PRD-008
      - CAP-ACC-PRD-011
    provenance: proposed
    source: >-
      services-accounting:modules/products/services/rules/product-rules.ts:listPrice;
      services-accounting:modules/products/services/rules/product-rules.ts:revenueSplitsProblem;
      services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
      more than 500 prices (the bound of the grid);
      services-accounting:modules/products/services/rules/product-rules.ts:listPrice;
      services-accounting:modules/products/services/rules/product-rules.ts:bundleTotalsProblem
permission_coverage:
  - key: accounting.product-accounting.update
    where_checked: api
    scope: tenant
    scenarios: []
    finding: FND-ACC-PRD-065
    provenance: unknown
    source: >-
      rhythm-v2-docs:specs/accounting/products/planning/capabilities/CAP-ACC-PRD-016-recognise-a-product-s-revenue-over-time-and-share-it.md#permissions
invariant_coverage:
  - invariant: INV-DOM-ACC-PRD-004-06
    scenarios:
      - ATS-ACC-PRD-016-02
    finding: null
    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
  - invariant: INV-DOM-ACC-PRD-004-07
    scenarios:
      - ATS-ACC-PRD-016-03
    finding: null
    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
  - invariant: INV-DOM-ACC-PRD-004-08
    scenarios:
      - ATS-ACC-PRD-016-09
    finding: FND-ACC-PRD-065
    provenance: proposed
    source: >-
      services-accounting:modules/products/services/persistence/product-accounting-setups.ts:replaceProductAccounting;
      services-accounting:modules/products/services/persistence/products.ts:updateProduct
    note: >-
      The mapped scenario exercises the related behavior; the complete invariant statement still needs
      dedicated proof.
---

# Allocate product revenue across dates and accounts: Capability Test Specification

## Coverage

The frontmatter lists a proof scenario or finding for every required rule and records each applicable category. Scenario coverage describes what to check; bindings identify the assertions that already exist, and execution results remain unverified. Maximum child-collection successes and refusals, price-lowering effects on later setup saves, permission combinations and concurrent price/setup changes need execution. Workflow edges not named by a scenario remain in this finding rather than gaining a binding from shared workflow membership.

## Interactions With Related Capabilities

A lower price affects the next revenue-share save. A bundle has a standard price and existing fixed shares. Lower the grid price with compatible component totals, inspect the existing shares, then resubmit those shares as a setup replacement. The product edit does not rewrite the setup; the later setup replacement rejects shares above its new price limit.
