---
id: CAP-ACC-PRD-012
title: Configure a customer purchase ceiling
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-010
  - react-console acceptance inventory RUL-ACC-PRD-026
source_sha:
  services-accounting: f47cb263875bbc0c5640fba7dae6785ec32695f8
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
intent_sources:
  - 'services-accounting:docs/milestones/ACCT-M1-books-and-invoices.md#R22'
purpose: An integrator records how many units a customer may buy.
outcomes:
  - Purchase ceilings provide explicit instructions for checkout.
concepts:
  - CON-ACC-PRD-001
actors:
  - ACT-ACC-006
  - ACT-ACC-011
surfaces:
  - api
permissions:
  - key: accounting.products.update
    where_checked: api
    scope: tenant
rules:
  - id: BR-CAP-ACC-PRD-012-01
    proved_by: [ATS-ACC-PRD-012-01, TST-ACC-PRD-027, TST-ACC-PRD-039]
    statement: >-
      A purchase ceiling stores a customer maximum of at least one, an all-time or positive rolling interval
      in days, weeks, months or years, and an optional refusal message.
    kind: validation
    enforced_at:
      - api
      - service
      - database
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/products/tests/integration/services/persistence/products.features.integration.spec.js#refuses
      a purchase limit of zero by the database’s check
    origin: none
  - id: BR-CAP-ACC-PRD-012-02
    proved_by: [ATS-ACC-PRD-012-01, TST-ACC-PRD-027, TST-ACC-PRD-039]
    statement: Rolling ceilings require an interval and all-time ceilings prohibit one.
    kind: validation
    enforced_at:
      - api
      - service
      - database
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/products/tests/integration/services/persistence/products.features.integration.spec.js#refuses
      an all-time purchase limit with a window
    origin: none
  - id: BR-CAP-ACC-PRD-012-03
    proved_by: [ATS-ACC-PRD-012-03]
    statement: Replacement clears the purchase ceiling when it is omitted or explicitly empty.
    kind: policy
    enforced_at:
      - api
      - service
    must_prove: false
    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-012-04
    proved_by: []
    statement: >-
      Documented responsibility assigns purchase-time enforcement to Orders and excludes the ceiling from 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-012-05
    proved_by: [ATS-ACC-PRD-012-02, ATS-ACC-PRD-012-04, TST-ACC-PRD-006]
    statement: The console hides purchase-ceiling controls while retaining API-configured values during saves.
    kind: policy
    enforced_at:
      - console
    must_prove: true
    provenance: test
    source: 'react-console:acceptance/accounting/playwright/journeys/products/ACT-ACC-0112.spec.ts#ACT-ACC-0112'
    origin: 'services-accounting:docs/milestones/ACCT-M1-books-and-invoices.md#R22'
scenarios:
  - id: SC-CAP-ACC-PRD-012-01
    given: A seminar has a stored purchase ceiling configured through the API.
    when: Finance renames it through the console.
    then: The saved ceiling remains available on the product.
    provenance: test
    source: 'react-console:acceptance/accounting/playwright/journeys/products/ACT-ACC-0112.spec.ts#ACT-ACC-0112'
edge_cases:
  - id: SC-CAP-ACC-PRD-012-02
    given: A rolling purchase ceiling is supplied.
    when: Its duration is omitted.
    then: Validation explains that the rolling interval is required.
    provenance: test
    source: >-
      services-accounting:modules/products/tests/e2e/product-features.e2e.spec.js#refuses a rolling purchase
      limit without its window
constraints: []
depends_on:
  - CAP-ACC-PRD-002
related:
  - CAP-ACC-PRD-004
journeys:
  - JNY-ACC-PRD-004
open_questions: []
evidence:
  - 'react-console:acceptance/accounting/playwright/journeys/products/ACT-ACC-0112.spec.ts'
  - 'react-console:components/accounting-config/products/product-section-types.ts'
  - '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/products.table.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
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-LOG-005, 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]
---

# Configure a customer purchase ceiling

## Purpose

An integrator records how many units a customer may buy.

## How It Works

An integrator records how many units a customer may buy. The ceiling can span all time or a rolling interval. A rolling interval also needs its duration and unit. An optional message describes the refusal a buyer should see. Accounting validates and stores this configuration during product saves. It does not count purchases or enforce the ceiling at checkout. The console currently hides these controls and preserves existing settings. Product should settle the Orders contract before treating stored ceilings as purchase protection.

## Relationships

This outcome uses create a product with a permanent identity.
