---
id: CAP-ACC-PRD-010
title: Configure discounts for quantity purchases
feature: FEAT-ACC-PRD-03
product_area: accounting
module: products
revision: 4
status: draft
product_intent: proposed
implementation_evidence: partially-observed
supersedes:
  - react-console acceptance inventory CAP-ACC-PRD-012
  - react-console acceptance inventory RUL-ACC-PRD-027
source_sha:
  services-accounting: f47cb263875bbc0c5640fba7dae6785ec32695f8
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
intent_sources:
  - 'services-accounting:docs/milestones/ACCT-M1-books-and-invoices.md#D12'
purpose: Finance describes quantity incentives as a set of bands.
outcomes:
  - Quantity incentives remain consistent across product saves.
concepts:
  - CON-ACC-PRD-001
actors:
  - ACT-ACC-006
  - ACT-ACC-011
surfaces:
  - console
  - api
permissions:
  - key: accounting.products.update
    where_checked: api
    scope: tenant
rules:
  - id: BR-CAP-ACC-PRD-010-01
    proved_by: [ATS-ACC-PRD-010-01, TST-ACC-PRD-039, TST-ACC-PRD-066]
    statement: >-
      A quantity band includes both endpoints or has no upper endpoint and reduces unit price by a
      zero-to-one-hundred percentage with two decimals or a nonnegative minor-unit amount.
    kind: validation
    enforced_at:
      - api
      - service
      - database
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/products/tests/unit/rules/product-rules.spec.js#refuses a percentage above
      100
    origin: 'services-accounting:docs/milestones/ACCT-M1-books-and-invoices.md#D12'
  - id: BR-CAP-ACC-PRD-010-02
    proved_by: [ATS-ACC-PRD-010-01, TST-ACC-PRD-039, TST-ACC-PRD-066]
    statement: A band’s final quantity cannot be smaller than its initial quantity.
    kind: validation
    enforced_at:
      - api
      - service
      - database
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/products/tests/unit/rules/product-rules.spec.js#refuses a range that ends
      before it starts, naming the row
    origin: 'services-accounting:docs/milestones/ACCT-M1-books-and-invoices.md#D12'
  - id: BR-CAP-ACC-PRD-010-03
    proved_by: [ATS-ACC-PRD-010-02, ATS-ACC-PRD-010-05, TST-ACC-PRD-027, TST-ACC-PRD-039, TST-ACC-PRD-066]
    statement: 'Quantity bands cannot overlap, and validation compares every pair and identifies the conflicting ranges.'
    kind: invariant
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/products/tests/integration/services/persistence/products.features.integration.spec.js#refuses
      overlapping bulk pricing ranges, naming the rows
    origin: 'services-accounting:docs/milestones/ACCT-M1-books-and-invoices.md#D12'
    examples:
      positive: A band ending at nine can precede an open-ended band starting at ten.
      negative: Bands from one to ten and from ten to twenty overlap at ten.
  - id: BR-CAP-ACC-PRD-010-04
    proved_by: [ATS-ACC-PRD-010-03, ATS-ACC-PRD-010-04, TST-ACC-PRD-006, TST-ACC-PRD-027]
    statement: >-
      Up to fifty bands replace the previous collection; empty feature arrays are rejected and an empty
      setting disables the feature.
    kind: validation
    enforced_at:
      - api
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/products/tests/e2e/product-features.e2e.spec.js#switches every feature off
      with null
    origin: 'services-accounting:docs/milestones/ACCT-M1-books-and-invoices.md#D12'
  - id: BR-CAP-ACC-PRD-010-05
    proved_by: []
    statement: >-
      Documented responsibility leaves purchase-time discount application to Orders while retaining discount
      information in the portal projection.
    kind: policy
    enforced_at: []
    must_prove: false
    provenance: documented
    source: 'services-accounting:docs/accounting/products.md#Features (2026-10-16)'
    origin: none
  - id: BR-CAP-ACC-PRD-010-06
    proved_by: []
    statement: The console offers Bulk Pricing only for kinds that permit quantity discounts.
    kind: policy
    enforced_at:
      - console
    must_prove: false
    provenance: observed
    source: 'react-console:components/accounting-config/products/product-common-sections.tsx:ProductCommonSections'
    origin: none
scenarios:
  - id: SC-CAP-ACC-PRD-010-01
    given: A publication offers quantity incentives.
    when: Staff configure ten percent for 10–49 copies and twenty percent above that.
    then: Both disjoint bands are accepted.
    provenance: test
    source: >-
      services-accounting:modules/products/tests/unit/rules/product-rules.spec.js#accepts rules that cover no
      quantity twice, in any order
edge_cases:
  - id: SC-CAP-ACC-PRD-010-02
    given: A flat band reduces price by 150 minor units.
    when: An administrator saves it.
    then: The amount is accepted without applying a percentage ceiling.
    provenance: test
    source: >-
      services-accounting:modules/products/tests/unit/rules/product-rules.spec.js#accepts a flat amount above
      100, which is minor units
constraints: []
depends_on:
  - CAP-ACC-PRD-002
related:
  - CAP-ACC-PRD-008
journeys:
  - JNY-ACC-PRD-004
open_questions: []
evidence:
  - 'react-console:components/accounting-config/products/product-bulk-pricing-section.tsx'
  - 'react-console:components/accounting-config/products/product-common-sections.tsx'
  - 'services-accounting:docs/accounting/products.md'
  - 'services-accounting:docs/milestones/ACCT-M1-books-and-invoices.md'
  - 'services-accounting:modules/products/aws/api/products.schemas.ts'
  - 'services-accounting:modules/products/db/product-bulk-pricing-rules.table.ts'
  - 'services-accounting:modules/products/services/persistence/products.ts'
  - 'services-accounting:modules/products/services/rules/product-rules.ts'
  - 'services-accounting:modules/products/tests/e2e/product-features.e2e.spec.js'
  - >-
    services-accounting:modules/products/tests/integration/services/persistence/products.features.integration.spec.js
  - 'services-accounting:modules/products/tests/unit/rules/product-rules.spec.js'
controls: [TC-IAM-001, TC-IAM-002, TC-IAM-004, TC-IAM-005, TC-AZ-001, TC-AZ-002, TC-AZ-003, TC-AZ-004, TC-AZ-005, TC-AZ-006, TC-TEN-001, TC-TEN-002, TC-TEN-003, TC-TEN-004, TC-DAT-001, TC-LOG-001, TC-LOG-002, TC-LOG-003, TC-LOG-004, TC-PI-001, TC-PI-003]
exercised_by: [FAS-ACC-PRD-03-01, FAS-ACC-PRD-03-02, FAS-ACC-PRD-03-03, FAS-ACC-PRD-03-04, FAS-ACC-PRD-03-05]
suites: [TST-ACC-PRD-006, TST-ACC-PRD-027, TST-ACC-PRD-039, TST-ACC-PRD-066]
---

# Configure discounts for quantity purchases

## Purpose

Finance describes quantity incentives as a set of bands.

## How It Works

Finance describes quantity incentives as a set of bands. Each band chooses a percentage or monetary reduction. The boundaries identify which quantities qualify. Saving rejects ranges that run backward or overlap. The console presents those problems before submission where possible. Replacing the product replaces the bands together. An empty setting removes the discount configuration. Accounting stores and validates the instructions; applying the discount to an order belongs to Orders.

## Relationships

This outcome uses create a product with a permanent identity.
