---
id: ATS-ACC-PRD-008
scope: CAP-ACC-PRD-008
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-008-01
    title: Kind-specific pricing rejects missing or forbidden rows
    level: unit
    proves:
      - BR-CAP-ACC-PRD-008-01
      - BR-CAP-ACC-PRD-008-02
      - INV-DOM-ACC-PRD-002-01
      - INV-DOM-ACC-PRD-002-02
    preconditions: 'A US-dollar unit supports Accounting, Legacy and Donation fixtures.'
    steps: Create fixed-priced products without standard base prices and a donation with prices.
    expected: Each invalid configuration fails.
    negative: true
    data_needs: 'A US-dollar unit supports Accounting, Legacy and Donation fixtures.'
    bound_to:
      - >-
        services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
        an Accounting Product without a standard price in the base currency
      - >-
        services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
        a Donation Product with prices
      - >-
        services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
        a Legacy Product without prices
      - >-
        services-accounting:modules/products/tests/e2e/products.e2e.spec.js#answers 400 to prices on a
        Donation Product
      - >-
        services-accounting:modules/products/tests/unit/rules/product-rules.spec.js#refuses any price on a
        variable-priced type
      - 'react-console:acceptance/accounting/playwright/journeys/products/ACT-ACC-0136.spec.ts#ACT-ACC-0136'
      - TST-ACC-PRD-040
      - TST-ACC-PRD-030
      - TST-ACC-PRD-066
      - TST-ACC-PRD-014
    provenance: test
    source: >-
      services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
      an Accounting Product without a standard price in the base currency
    category: rule
    binding_scope:
      - suite: TST-ACC-PRD-040
        assertions:
          - >-
            services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
            an Accounting Product without a standard price in the base currency
          - >-
            services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
            a Donation Product with prices
          - >-
            services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
            a Legacy Product without prices
        provenance: test
        source: >-
          services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
          an Accounting Product without a standard price in the base currency;
          services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
          a Donation Product with prices;
          services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
          a Legacy Product without prices;
          services-accounting:modules/products/tests/e2e/products.e2e.spec.js#answers 400 to prices on a
          Donation Product;
          services-accounting:modules/products/tests/unit/rules/product-rules.spec.js#refuses any price on a
          variable-priced type;
          react-console:acceptance/accounting/playwright/journeys/products/ACT-ACC-0136.spec.ts#ACT-ACC-0136
      - suite: TST-ACC-PRD-030
        assertions:
          - >-
            services-accounting:modules/products/tests/e2e/products.e2e.spec.js#answers 400 to prices on a
            Donation Product
        provenance: test
        source: >-
          services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
          an Accounting Product without a standard price in the base currency;
          services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
          a Donation Product with prices;
          services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
          a Legacy Product without prices;
          services-accounting:modules/products/tests/e2e/products.e2e.spec.js#answers 400 to prices on a
          Donation Product;
          services-accounting:modules/products/tests/unit/rules/product-rules.spec.js#refuses any price on a
          variable-priced type;
          react-console:acceptance/accounting/playwright/journeys/products/ACT-ACC-0136.spec.ts#ACT-ACC-0136
      - suite: TST-ACC-PRD-066
        assertions:
          - >-
            services-accounting:modules/products/tests/unit/rules/product-rules.spec.js#refuses any price on a
            variable-priced type
        provenance: test
        source: >-
          services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
          an Accounting Product without a standard price in the base currency;
          services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
          a Donation Product with prices;
          services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
          a Legacy Product without prices;
          services-accounting:modules/products/tests/e2e/products.e2e.spec.js#answers 400 to prices on a
          Donation Product;
          services-accounting:modules/products/tests/unit/rules/product-rules.spec.js#refuses any price on a
          variable-priced type;
          react-console:acceptance/accounting/playwright/journeys/products/ACT-ACC-0136.spec.ts#ACT-ACC-0136
      - suite: TST-ACC-PRD-014
        assertions:
          - 'react-console:acceptance/accounting/playwright/journeys/products/ACT-ACC-0136.spec.ts#ACT-ACC-0136'
        provenance: test
        source: >-
          services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
          an Accounting Product without a standard price in the base currency;
          services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
          a Donation Product with prices;
          services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
          a Legacy Product without prices;
          services-accounting:modules/products/tests/e2e/products.e2e.spec.js#answers 400 to prices on a
          Donation Product;
          services-accounting:modules/products/tests/unit/rules/product-rules.spec.js#refuses any price on a
          variable-priced type;
          react-console:acceptance/accounting/playwright/journeys/products/ACT-ACC-0136.spec.ts#ACT-ACC-0136
  - id: ATS-ACC-PRD-008-02
    title: Unit currency settings restrict pricing
    level: unit
    proves:
      - BR-CAP-ACC-PRD-008-03
    preconditions: Two units support euros but only one enables multicurrency.
    steps: Try Canadian-dollar pricing and euro pricing in each unit.
    expected: Unsupported currency fails and euros succeed only when multicurrency is enabled.
    negative: true
    data_needs: Two units support euros but only one enables multicurrency.
    bound_to:
      - >-
        services-accounting:modules/products/tests/unit/rules/product-rules.spec.js#refuses a supported
        currency when the unit has Enable Multicurrency off (1.0: off is a single-currency unit)
      - >-
        services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
        a price in a currency the business unit is not enabled for
      - >-
        services-accounting:modules/products/tests/unit/rules/product-rules.spec.js#refuses a currency that is
        neither the business unit’s base nor one of its supported currencies
      - TST-ACC-PRD-066
      - TST-ACC-PRD-040
    provenance: test
    source: >-
      services-accounting:modules/products/tests/unit/rules/product-rules.spec.js#refuses a supported currency
      when the unit has Enable Multicurrency off (1.0: off is a single-currency unit)
    category: validation
    binding_scope:
      - suite: TST-ACC-PRD-066
        assertions:
          - >-
            services-accounting:modules/products/tests/unit/rules/product-rules.spec.js#refuses a supported
            currency when the unit has Enable Multicurrency off (1.0: off is a single-currency unit)
          - >-
            services-accounting:modules/products/tests/unit/rules/product-rules.spec.js#refuses a currency
            that is neither the business unit’s base nor one of its supported currencies
        provenance: test
        source: >-
          services-accounting:modules/products/tests/unit/rules/product-rules.spec.js#refuses a supported
          currency when the unit has Enable Multicurrency off (1.0: off is a single-currency unit);
          services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
          a price in a currency the business unit is not enabled for;
          services-accounting:modules/products/tests/unit/rules/product-rules.spec.js#refuses a currency that
          is neither the business unit’s base nor one of its supported currencies
      - suite: TST-ACC-PRD-040
        assertions:
          - >-
            services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
            a price in a currency the business unit is not enabled for
        provenance: test
        source: >-
          services-accounting:modules/products/tests/unit/rules/product-rules.spec.js#refuses a supported
          currency when the unit has Enable Multicurrency off (1.0: off is a single-currency unit);
          services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
          a price in a currency the business unit is not enabled for;
          services-accounting:modules/products/tests/unit/rules/product-rules.spec.js#refuses a currency that
          is neither the business unit’s base nor one of its supported currencies
  - id: ATS-ACC-PRD-008-03
    title: Price modes require matching values
    level: unit
    proves:
      - BR-CAP-ACC-PRD-008-04
    preconditions: A multicurrency unit supports grid fixtures.
    steps: 'Submit missing amounts, misplaced percentages, invalid percentages and conversion with an amount.'
    expected: Every inconsistent cell fails.
    negative: true
    data_needs: A multicurrency unit supports grid fixtures.
    bound_to:
      - >-
        services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
        a percentage cell without a percent, and a set cell with one
      - >-
        services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
        a set price without an amount
      - >-
        services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
        a percentage above 100 or with more than two decimals
      - >-
        services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
        a calculated cell with an amount
      - >-
        services-accounting:modules/products/tests/integration/db/products.table.integration.spec.js#refuses a
        percent_of_standard row without its percent, and a set row with one
      - TST-ACC-PRD-040
      - TST-ACC-PRD-031
    provenance: test
    source: >-
      services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
      a percentage cell without a percent, and a set cell with one
    category: validation
    binding_scope:
      - suite: TST-ACC-PRD-040
        assertions:
          - >-
            services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
            a percentage cell without a percent, and a set cell with one
          - >-
            services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
            a set price without an amount
          - >-
            services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
            a percentage above 100 or with more than two decimals
          - >-
            services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
            a calculated cell with an amount
        provenance: test
        source: >-
          services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
          a percentage cell without a percent, and a set cell with one;
          services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
          a set price without an amount;
          services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
          a percentage above 100 or with more than two decimals;
          services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
          a calculated cell with an amount;
          services-accounting:modules/products/tests/integration/db/products.table.integration.spec.js#refuses
          a percent_of_standard row without its percent, and a set row with one
      - suite: TST-ACC-PRD-031
        assertions:
          - >-
            services-accounting:modules/products/tests/integration/db/products.table.integration.spec.js#refuses
            a percent_of_standard row without its percent, and a set row with one
        provenance: test
        source: >-
          services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
          a percentage cell without a percent, and a set cell with one;
          services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
          a set price without an amount;
          services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
          a percentage above 100 or with more than two decimals;
          services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
          a calculated cell with an amount;
          services-accounting:modules/products/tests/integration/db/products.table.integration.spec.js#refuses
          a percent_of_standard row without its percent, and a set row with one
  - id: ATS-ACC-PRD-008-04
    title: The base currency cannot be converted or prohibited
    level: unit
    proves:
      - BR-CAP-ACC-PRD-008-05
    preconditions: A unit enables a foreign currency.
    steps: Try conversion and prohibition in base currency and prohibition in the foreign currency.
    expected: Base-currency choices fail and foreign prohibition succeeds.
    negative: true
    data_needs: A unit enables a foreign currency.
    bound_to:
      - >-
        services-accounting:modules/products/tests/unit/rules/product-rules.spec.js#refuses prohibiting the
        base currency
      - >-
        services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
        prohibiting purchases in the base currency
      - >-
        services-accounting:modules/products/tests/unit/rules/product-rules.spec.js#accepts a standard price
        in the base currency and a prohibited supported currency
      - TST-ACC-PRD-066
      - TST-ACC-PRD-040
    provenance: test
    source: >-
      services-accounting:modules/products/tests/unit/rules/product-rules.spec.js#refuses prohibiting the base
      currency
    category: validation
    binding_scope:
      - suite: TST-ACC-PRD-066
        assertions:
          - >-
            services-accounting:modules/products/tests/unit/rules/product-rules.spec.js#refuses prohibiting
            the base currency
          - >-
            services-accounting:modules/products/tests/unit/rules/product-rules.spec.js#accepts a standard
            price in the base currency and a prohibited supported currency
        provenance: test
        source: >-
          services-accounting:modules/products/tests/unit/rules/product-rules.spec.js#refuses prohibiting the
          base currency;
          services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
          prohibiting purchases in the base currency;
          services-accounting:modules/products/tests/unit/rules/product-rules.spec.js#accepts a standard price
          in the base currency and a prohibited supported currency
      - suite: TST-ACC-PRD-040
        assertions:
          - >-
            services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
            prohibiting purchases in the base currency
        provenance: test
        source: >-
          services-accounting:modules/products/tests/unit/rules/product-rules.spec.js#refuses prohibiting the
          base currency;
          services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
          prohibiting purchases in the base currency;
          services-accounting:modules/products/tests/unit/rules/product-rules.spec.js#accepts a standard price
          in the base currency and a prohibited supported currency
  - id: ATS-ACC-PRD-008-05
    title: Percentage backing stays in the right period
    level: unit
    proves:
      - BR-CAP-ACC-PRD-008-06
      - BR-CAP-ACC-PRD-008-08
      - INV-DOM-ACC-PRD-002-05
    preconditions: The grid has currencies and named periods.
    steps: >-
      Try percentage on standard, missing currency backing, always backing and backing only from a different
      period.
    expected: Only valid same-period or always backing succeeds.
    negative: true
    data_needs: The grid has currencies and named periods.
    bound_to:
      - >-
        services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
        a percentage cell on the standard audience, and one with no standard price to be a percentage of
      - >-
        services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#lets
        a period cell inherit the always cell of its audience (a percentage in a period needs a standard price
        in that period or always)
      - >-
        services-accounting:modules/products/tests/unit/rules/product-rules.spec.js#accepts a percentage cell
        backed by the standard price of its currency, in its period or always (A12)
      - >-
        services-accounting:modules/products/tests/unit/rules/product-rules.spec.js#refuses a percentage cell
        whose period has no standard price and no always row to inherit
      - TST-ACC-PRD-040
      - TST-ACC-PRD-066
    provenance: test
    source: >-
      services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
      a percentage cell on the standard audience, and one with no standard price to be a percentage of
    category: rule
    binding_scope:
      - suite: TST-ACC-PRD-040
        assertions:
          - >-
            services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
            a percentage cell on the standard audience, and one with no standard price to be a percentage of
          - >-
            services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#lets
            a period cell inherit the always cell of its audience (a percentage in a period needs a standard
            price in that period or always)
        provenance: test
        source: >-
          services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
          a percentage cell on the standard audience, and one with no standard price to be a percentage of;
          services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#lets
          a period cell inherit the always cell of its audience (a percentage in a period needs a standard
          price in that period or always);
          services-accounting:modules/products/tests/unit/rules/product-rules.spec.js#accepts a percentage
          cell backed by the standard price of its currency, in its period or always (A12);
          services-accounting:modules/products/tests/unit/rules/product-rules.spec.js#refuses a percentage
          cell whose period has no standard price and no always row to inherit
      - suite: TST-ACC-PRD-066
        assertions:
          - >-
            services-accounting:modules/products/tests/unit/rules/product-rules.spec.js#accepts a percentage
            cell backed by the standard price of its currency, in its period or always (A12)
          - >-
            services-accounting:modules/products/tests/unit/rules/product-rules.spec.js#refuses a percentage
            cell whose period has no standard price and no always row to inherit
        provenance: test
        source: >-
          services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
          a percentage cell on the standard audience, and one with no standard price to be a percentage of;
          services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#lets
          a period cell inherit the always cell of its audience (a percentage in a period needs a standard
          price in that period or always);
          services-accounting:modules/products/tests/unit/rules/product-rules.spec.js#accepts a percentage
          cell backed by the standard price of its currency, in its period or always (A12);
          services-accounting:modules/products/tests/unit/rules/product-rules.spec.js#refuses a percentage
          cell whose period has no standard price and no always row to inherit
  - id: ATS-ACC-PRD-008-06
    title: Conversion uses the same audience
    level: unit
    proves:
      - BR-CAP-ACC-PRD-008-07
    preconditions: A member euro conversion row is proposed.
    steps: 'Supply only standard dollars, then supply member dollars.'
    expected: The first grid fails and the second succeeds.
    negative: true
    data_needs: A member euro conversion row is proposed.
    bound_to:
      - >-
        services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
        a calculated cell in the base currency, and one whose audience has no base-currency price to convert
      - >-
        services-accounting:modules/products/tests/unit/rules/product-rules.spec.js#accepts a calculated cell
        backed by its audience’s base-currency price, and refuses one in the base currency (A13)
      - TST-ACC-PRD-040
      - TST-ACC-PRD-066
    provenance: test
    source: >-
      services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
      a calculated cell in the base currency, and one whose audience has no base-currency price to convert
    category: rule
    binding_scope:
      - suite: TST-ACC-PRD-040
        assertions:
          - >-
            services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
            a calculated cell in the base currency, and one whose audience has no base-currency price to
            convert
        provenance: test
        source: >-
          services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
          a calculated cell in the base currency, and one whose audience has no base-currency price to
          convert; services-accounting:modules/products/tests/unit/rules/product-rules.spec.js#accepts a
          calculated cell backed by its audience’s base-currency price, and refuses one in the base currency
          (A13)
      - suite: TST-ACC-PRD-066
        assertions:
          - >-
            services-accounting:modules/products/tests/unit/rules/product-rules.spec.js#accepts a calculated
            cell backed by its audience’s base-currency price, and refuses one in the base currency (A13)
        provenance: test
        source: >-
          services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
          a calculated cell in the base currency, and one whose audience has no base-currency price to
          convert; services-accounting:modules/products/tests/unit/rules/product-rules.spec.js#accepts a
          calculated cell backed by its audience’s base-currency price, and refuses one in the base currency
          (A13)
  - id: ATS-ACC-PRD-008-07
    title: Applicability windows cannot overlap
    level: unit
    proves:
      - BR-CAP-ACC-PRD-008-09
    preconditions: A unit supports dated grid fixtures.
    steps: 'Try overlaps, an undated row with a dated row, meeting windows and separate periods or audiences.'
    expected: Overlaps fail while exclusive-end boundaries and distinct cell coordinates succeed.
    negative: true
    data_needs: A unit supports dated grid fixtures.
    bound_to:
      - >-
        services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
        a dated price beside one that applies always, in the same audience and currency
      - >-
        services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
        two standard prices in one currency whose periods overlap
      - >-
        services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#accepts
        two periods of one audience and currency that meet without overlapping
      - >-
        services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#accepts
        the same period in two audiences
      - >-
        services-accounting:modules/products/tests/unit/rules/product-rules.spec.js#judges overlap per period:
        the same window in two periods never meets
      - >-
        services-accounting:modules/products/tests/e2e/products.e2e.spec.js#answers 400 to overlapping price
        periods, leaving the prices as they were
      - TST-ACC-PRD-040
      - TST-ACC-PRD-066
      - TST-ACC-PRD-030
    provenance: test
    source: >-
      services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
      a dated price beside one that applies always, in the same audience and currency
    category: boundary
    binding_scope:
      - suite: TST-ACC-PRD-040
        assertions:
          - >-
            services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
            a dated price beside one that applies always, in the same audience and currency
          - >-
            services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
            two standard prices in one currency whose periods overlap
          - >-
            services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#accepts
            two periods of one audience and currency that meet without overlapping
          - >-
            services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#accepts
            the same period in two audiences
        provenance: test
        source: >-
          services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
          a dated price beside one that applies always, in the same audience and currency;
          services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
          two standard prices in one currency whose periods overlap;
          services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#accepts
          two periods of one audience and currency that meet without overlapping;
          services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#accepts
          the same period in two audiences;
          services-accounting:modules/products/tests/unit/rules/product-rules.spec.js#judges overlap per
          period: the same window in two periods never meets;
          services-accounting:modules/products/tests/e2e/products.e2e.spec.js#answers 400 to overlapping price
          periods, leaving the prices as they were
      - suite: TST-ACC-PRD-066
        assertions:
          - >-
            services-accounting:modules/products/tests/unit/rules/product-rules.spec.js#judges overlap per
            period: the same window in two periods never meets
        provenance: test
        source: >-
          services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
          a dated price beside one that applies always, in the same audience and currency;
          services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
          two standard prices in one currency whose periods overlap;
          services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#accepts
          two periods of one audience and currency that meet without overlapping;
          services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#accepts
          the same period in two audiences;
          services-accounting:modules/products/tests/unit/rules/product-rules.spec.js#judges overlap per
          period: the same window in two periods never meets;
          services-accounting:modules/products/tests/e2e/products.e2e.spec.js#answers 400 to overlapping price
          periods, leaving the prices as they were
      - suite: TST-ACC-PRD-030
        assertions:
          - >-
            services-accounting:modules/products/tests/e2e/products.e2e.spec.js#answers 400 to overlapping
            price periods, leaving the prices as they were
        provenance: test
        source: >-
          services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
          a dated price beside one that applies always, in the same audience and currency;
          services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
          two standard prices in one currency whose periods overlap;
          services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#accepts
          two periods of one audience and currency that meet without overlapping;
          services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#accepts
          the same period in two audiences;
          services-accounting:modules/products/tests/unit/rules/product-rules.spec.js#judges overlap per
          period: the same window in two periods never meets;
          services-accounting:modules/products/tests/e2e/products.e2e.spec.js#answers 400 to overlapping price
          periods, leaving the prices as they were
  - id: ATS-ACC-PRD-008-08
    title: Audience admission follows vocabulary availability
    level: unit
    proves:
      - BR-CAP-ACC-PRD-008-10
    preconditions: 'Commerce vocabulary is absent then present with active, inactive and foreign-workspace audiences.'
    steps: 'Save grids for built-ins, held audiences and vocabulary audiences.'
    expected: Admission follows the recorded rules in each vocabulary state.
    negative: true
    data_needs: 'Commerce vocabulary is absent then present with active, inactive and foreign-workspace audiences.'
    bound_to:
      - >-
        services-accounting:modules/products/tests/integration/services/persistence/pricing-audiences.integration.spec.js#refuses
        an inactive audience and an unknown one, naming the vocabulary
      - >-
        services-accounting:modules/products/tests/integration/services/persistence/pricing-audiences.integration.spec.js#admits
        a built-in with no row of its own, and an inactive built-in row
      - >-
        services-accounting:modules/products/tests/integration/services/persistence/pricing-audiences.integration.spec.js#lets
        a product price a vocabulary audience
      - >-
        services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
        an audience the vocabulary does not know while Commerce’s pricing audiences do not exist (the
        built-ins are admitted)
      - TST-ACC-PRD-035
      - TST-ACC-PRD-040
    provenance: test
    source: >-
      services-accounting:modules/products/tests/integration/services/persistence/pricing-audiences.integration.spec.js#refuses
      an inactive audience and an unknown one, naming the vocabulary
    category: edge
    binding_scope:
      - suite: TST-ACC-PRD-035
        assertions:
          - >-
            services-accounting:modules/products/tests/integration/services/persistence/pricing-audiences.integration.spec.js#refuses
            an inactive audience and an unknown one, naming the vocabulary
          - >-
            services-accounting:modules/products/tests/integration/services/persistence/pricing-audiences.integration.spec.js#admits
            a built-in with no row of its own, and an inactive built-in row
          - >-
            services-accounting:modules/products/tests/integration/services/persistence/pricing-audiences.integration.spec.js#lets
            a product price a vocabulary audience
        provenance: test
        source: >-
          services-accounting:modules/products/tests/integration/services/persistence/pricing-audiences.integration.spec.js#refuses
          an inactive audience and an unknown one, naming the vocabulary;
          services-accounting:modules/products/tests/integration/services/persistence/pricing-audiences.integration.spec.js#admits
          a built-in with no row of its own, and an inactive built-in row;
          services-accounting:modules/products/tests/integration/services/persistence/pricing-audiences.integration.spec.js#lets
          a product price a vocabulary audience;
          services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
          an audience the vocabulary does not know while Commerce’s pricing audiences do not exist (the
          built-ins are admitted)
      - suite: TST-ACC-PRD-040
        assertions:
          - >-
            services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
            an audience the vocabulary does not know while Commerce’s pricing audiences do not exist (the
            built-ins are admitted)
        provenance: test
        source: >-
          services-accounting:modules/products/tests/integration/services/persistence/pricing-audiences.integration.spec.js#refuses
          an inactive audience and an unknown one, naming the vocabulary;
          services-accounting:modules/products/tests/integration/services/persistence/pricing-audiences.integration.spec.js#admits
          a built-in with no row of its own, and an inactive built-in row;
          services-accounting:modules/products/tests/integration/services/persistence/pricing-audiences.integration.spec.js#lets
          a product price a vocabulary audience;
          services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
          an audience the vocabulary does not know while Commerce’s pricing audiences do not exist (the
          built-ins are admitted)
  - id: ATS-ACC-PRD-008-09
    title: Grid replacement respects the collection limit
    level: unit
    proves:
      - BR-CAP-ACC-PRD-008-12
      - INV-DOM-ACC-PRD-002-08
    preconditions: A product is available for pricing.
    steps: Submit 501 rows and then replace a smaller valid grid.
    expected: The excessive grid fails and valid replacement removes previous rows.
    negative: true
    data_needs: A product is available for pricing.
    bound_to:
      - >-
        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/tests/e2e/products.e2e.spec.js#replaces the prices as a whole,
        with their effective periods
      - TST-ACC-PRD-040
      - TST-ACC-PRD-030
    provenance: test
    source: >-
      services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
      more than 500 prices (the bound of the grid)
    category: boundary
    binding_scope:
      - suite: TST-ACC-PRD-040
        assertions:
          - >-
            services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
            more than 500 prices (the bound of the grid)
        provenance: test
        source: >-
          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/tests/e2e/products.e2e.spec.js#replaces the prices as a whole,
          with their effective periods
      - suite: TST-ACC-PRD-030
        assertions:
          - >-
            services-accounting:modules/products/tests/e2e/products.e2e.spec.js#replaces the prices as a
            whole, with their effective periods
        provenance: test
        source: >-
          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/tests/e2e/products.e2e.spec.js#replaces the prices as a whole,
          with their effective periods
  - id: ATS-ACC-PRD-008-10
    title: Storage rejects negative and fractional price money
    category: invariant
    level: api
    proves:
      - BR-CAP-ACC-PRD-008-11
      - INV-DOM-ACC-PRD-002-09
    preconditions: A fixed-priced product has an otherwise valid base-currency grid.
    steps: Attempt storage writes with negative and fractional minor-unit amounts.
    expected: Both writes are refused and the committed grid remains unchanged.
    negative: true
    data_needs: A fixed-priced product has an otherwise valid base-currency grid.
    bound_to: []
    provenance: proposed
    source: >-
      services-accounting:modules/products/db/product-prices.table.ts;
      services-accounting:modules/products/tests/integration/db/products.table.integration.spec.js#refuses a
      negative amount
    binding_scope: []
  - id: ATS-ACC-PRD-008-11
    title: Price changes affect later component and revenue-allocation validation
    category: interaction
    level: api
    proves:
      - BR-CAP-ACC-PRD-008-01
      - BR-CAP-ACC-PRD-009-05
      - BR-CAP-ACC-PRD-011-06
      - BR-CAP-ACC-PRD-016-06
    preconditions: 'A product holds migrated audience rows, components and fixed revenue shares.'
    steps: >-
      Resubmit after Commerce vocabulary activation; once the audience is admitted, lower the standard price
      and attempt component and setup allocations above that price.
    expected: >-
      Audience admission gates the edit; subsequent component and setup saves use the new applicable price,
      without claiming automatic revalidation of existing shares.
    negative: true
    data_needs: 'A product holds migrated audience rows, components and fixed revenue shares.'
    bound_to: []
    provenance: proposed
    source: >-
      services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
      an Accounting Product without a standard price in the base currency;
      services-accounting:modules/products/tests/integration/services/persistence/pricing-audiences.integration.spec.js#answers
      the built-ins and the tenant’s active audiences among the ids asked: not an inactive one, not another
      tenant’s, not the ids held;
      services-accounting:modules/products/services/rules/product-rules.ts:listPrice;
      services-accounting:modules/products/services/rules/product-rules.ts:bundleTotalsProblem;
      services-accounting:modules/products/services/rules/product-rules.ts:listPrice;
      services-accounting:modules/products/services/rules/product-rules.ts:revenueSplitsProblem
    exercises:
      - CAP-ACC-PRD-008
      - CAP-ACC-PRD-009
      - CAP-ACC-PRD-011
      - CAP-ACC-PRD-016
    binding_scope: []
evidence:
  - 'react-console:acceptance/accounting/playwright/journeys/products/ACT-ACC-0136.spec.ts'
  - 'services-accounting:modules/products/db/product-prices.table.ts'
  - 'services-accounting:modules/products/services/persistence/pricing-audiences.ts'
  - 'services-accounting:modules/products/services/persistence/products.ts'
  - 'services-accounting:modules/products/services/rules/product-rules.ts'
  - 'services-accounting:modules/products/tests/e2e/products.e2e.spec.js'
  - 'services-accounting:modules/products/tests/integration/db/products.table.integration.spec.js'
  - >-
    services-accounting:modules/products/tests/integration/services/persistence/pricing-audiences.integration.spec.js
  - 'services-accounting:modules/products/tests/integration/services/persistence/products.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-001-create-or-replace-a-product-with-its-owned-settings.md
  - >-
    rhythm-v2-docs:specs/accounting/products/design/workflows/WF-ACC-PRD-006-hand-migrated-special-prices-over-to-commerce.md
coverage:
  rule: covered
  transition: 'gap: FND-ACC-PRD-057'
  validation: covered
  permission: 'gap: FND-ACC-PRD-057'
  edge: covered
  failure: 'gap: FND-ACC-PRD-057'
  boundary: covered
  concurrency: 'gap: FND-ACC-PRD-057'
  invariant: covered
  interaction: covered
coverage_notes:
  transition:
    reason: No dedicated scenario isolates this category for the capability.
    provenance: unknown
    source: FND-ACC-PRD-057
  permission:
    reason: No dedicated scenario isolates this category for the capability.
    provenance: unknown
    source: FND-ACC-PRD-057
  failure:
    reason: No dedicated scenario isolates this category for the capability.
    provenance: unknown
    source: FND-ACC-PRD-057
  concurrency:
    reason: No dedicated scenario isolates this category for the capability.
    provenance: unknown
    source: FND-ACC-PRD-057
  remaining_obligations:
    reason: >-
      Precision limits, all amount endpoints, concurrent replacements and full cross-capability allocation
      scenarios require 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-057
  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-057
related_capabilities:
  - CAP-ACC-PRD-009
  - CAP-ACC-PRD-011
  - CAP-ACC-PRD-016
workflows:
  - WF-ACC-PRD-001
  - WF-ACC-PRD-006
rule_coverage:
  - rule: BR-CAP-ACC-PRD-008-01
    scenarios:
      - ATS-ACC-PRD-008-01
      - ATS-ACC-PRD-008-11
  - rule: BR-CAP-ACC-PRD-008-02
    scenarios:
      - ATS-ACC-PRD-008-01
  - rule: BR-CAP-ACC-PRD-008-03
    scenarios:
      - ATS-ACC-PRD-008-02
  - rule: BR-CAP-ACC-PRD-008-04
    scenarios:
      - ATS-ACC-PRD-008-03
  - rule: BR-CAP-ACC-PRD-008-05
    scenarios:
      - ATS-ACC-PRD-008-04
  - rule: BR-CAP-ACC-PRD-008-06
    scenarios:
      - ATS-ACC-PRD-008-05
  - rule: BR-CAP-ACC-PRD-008-07
    scenarios:
      - ATS-ACC-PRD-008-06
  - rule: BR-CAP-ACC-PRD-008-08
    scenarios:
      - ATS-ACC-PRD-008-05
  - rule: BR-CAP-ACC-PRD-008-09
    scenarios:
      - ATS-ACC-PRD-008-07
  - rule: BR-CAP-ACC-PRD-008-10
    scenarios:
      - ATS-ACC-PRD-008-08
  - rule: BR-CAP-ACC-PRD-008-12
    scenarios:
      - ATS-ACC-PRD-008-09
interaction_coverage:
  - scenario: ATS-ACC-PRD-008-11
    exercises:
      - CAP-ACC-PRD-008
      - CAP-ACC-PRD-009
      - CAP-ACC-PRD-011
      - CAP-ACC-PRD-016
    provenance: proposed
    source: >-
      services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
      an Accounting Product without a standard price in the base currency;
      services-accounting:modules/products/tests/integration/services/persistence/pricing-audiences.integration.spec.js#answers
      the built-ins and the tenant’s active audiences among the ids asked: not an inactive one, not another
      tenant’s, not the ids held;
      services-accounting:modules/products/services/rules/product-rules.ts:listPrice;
      services-accounting:modules/products/services/rules/product-rules.ts:bundleTotalsProblem;
      services-accounting:modules/products/services/rules/product-rules.ts:listPrice;
      services-accounting:modules/products/services/rules/product-rules.ts:revenueSplitsProblem
permission_coverage:
  - key: accounting.products.create
    where_checked: api
    scope: tenant
    scenarios: []
    finding: FND-ACC-PRD-057
    provenance: unknown
    source: >-
      rhythm-v2-docs:specs/accounting/products/planning/capabilities/CAP-ACC-PRD-008-price-a-product-for-each-audience-period-and-currency.md#permissions
  - key: accounting.products.update
    where_checked: api
    scope: tenant
    scenarios: []
    finding: FND-ACC-PRD-057
    provenance: unknown
    source: >-
      rhythm-v2-docs:specs/accounting/products/planning/capabilities/CAP-ACC-PRD-008-price-a-product-for-each-audience-period-and-currency.md#permissions
invariant_coverage:
  - invariant: INV-DOM-ACC-PRD-002-01
    scenarios:
      - ATS-ACC-PRD-008-01
    finding: null
    provenance: test
    source: >-
      services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
      an Accounting Product without a standard price in the base currency
  - invariant: INV-DOM-ACC-PRD-002-02
    scenarios:
      - ATS-ACC-PRD-008-01
    finding: null
    provenance: test
    source: >-
      services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
      a Donation Product with prices
  - invariant: INV-DOM-ACC-PRD-002-03
    scenarios:
      - ATS-ACC-PRD-008-02
    finding: FND-ACC-PRD-057
    provenance: proposed
    source: >-
      services-accounting:modules/products/tests/integration/db/products.table.integration.spec.js#refuses a
      currency the product’s business unit is not enabled for
    note: >-
      The mapped scenario exercises the related behavior; the complete invariant statement still needs
      dedicated proof.
  - invariant: INV-DOM-ACC-PRD-002-04
    scenarios:
      - ATS-ACC-PRD-008-03
    finding: FND-ACC-PRD-057
    provenance: proposed
    source: 'services-accounting:modules/products/services/rules/product-rules.ts:pricesProblem'
    note: >-
      The mapped scenario exercises the related behavior; the complete invariant statement still needs
      dedicated proof.
  - invariant: INV-DOM-ACC-PRD-002-05
    scenarios:
      - ATS-ACC-PRD-008-05
    finding: null
    provenance: test
    source: >-
      services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
      a percentage cell on the standard audience, and one with no standard price to be a percentage of
  - invariant: INV-DOM-ACC-PRD-002-06
    scenarios:
      - ATS-ACC-PRD-008-07
    finding: FND-ACC-PRD-057
    provenance: proposed
    source: >-
      services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
      two cells of one audience, currency and period applying at once, and accepts the same window in another
      period
    note: >-
      The mapped scenario exercises the related behavior; the complete invariant statement still needs
      dedicated proof.
  - invariant: INV-DOM-ACC-PRD-002-07
    scenarios:
      - ATS-ACC-PRD-008-08
    finding: FND-ACC-PRD-057
    provenance: proposed
    source: >-
      services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#admits
      an audience the product already holds on a replacement (a migrated special price), even without the
      vocabulary
    note: >-
      The mapped scenario exercises the related behavior; the complete invariant statement still needs
      dedicated proof.
  - invariant: INV-DOM-ACC-PRD-002-08
    scenarios:
      - ATS-ACC-PRD-008-09
    finding: null
    provenance: test
    source: >-
      services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#refuses
      more than 500 prices (the bound of the grid)
  - invariant: INV-DOM-ACC-PRD-002-09
    scenarios:
      - ATS-ACC-PRD-008-10
    finding: FND-ACC-PRD-057
    provenance: proposed
    source: >-
      services-accounting:modules/products/tests/integration/db/products.table.integration.spec.js#refuses a
      negative amount
    note: >-
      The mapped scenario exercises the related behavior; the complete invariant statement still needs
      dedicated proof.
---

# Configure prices by audience, period and currency: 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. Precision limits, all amount endpoints, concurrent replacements and full cross-capability allocation scenarios require 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

Price changes affect later component and revenue-allocation validation. A product holds migrated audience rows, components and fixed revenue shares. Resubmit after Commerce vocabulary activation; once the audience is admitted, lower the standard price and attempt component and setup allocations above that price. Audience admission gates the edit; subsequent component and setup saves use the new applicable price, without claiming automatic revalidation of existing shares.
