---
id: CAP-COM-FUL-018
title: Allocate stock and explain what buyers can obtain
feature: FEAT-COM-FUL-04
product_area: commerce
module: fulfillment
revision: 1
status: draft
product_intent: proposed
implementation_evidence: observed
supersedes:
  - CAP-COM-INV-005
  - CAP-COM-INV-006
  - CAP-COM-INV-007
  - CAP-COM-INV-012
  - CAP-COM-INV-015
  - CAP-COM-REG-035
source_sha:
  services-commerce: c8b66a98e2490617aec38ba5c8165dd9bd0a8f9b
intent_sources: []
purpose: Commerce reserves stock for checkout and commits units to accepted purchases.
outcomes:
  - Product policy controls whether shortage can become backorder.
  - Shared availability logic supplies storefront and staff views.
concepts:
  - CON-COM-FUL-005
actors:
  - ACT-COM-011
  - ACT-COM-010
surfaces:
  - api
  - job
preconditions: []
postconditions: []
permissions:
  - key: commerce.inventory.read
    where_checked: api
    scope: tenant
rules:
  - id: BR-CAP-COM-FUL-018-01
    proved_by: [ATS-COM-FUL-016-06, ATS-COM-FUL-016-07, ATS-COM-FUL-017-09, ATS-COM-FUL-017-10, ATS-COM-FUL-018-01, ATS-COM-FUL-018-12, ATS-COM-FUL-018-13, TST-COM-FUL-065]
    statement: >-
      Placement commits one allocation per ordered unit in sellable-location
      order with order and line references, and repeating the line claim creates
      no duplicate units.
    kind: calculation
    enforced_at:
      - service
      - database
    must_prove: true
    provenance: test
    source: >-
      services-commerce:modules/inventory/tests/integration/services/stock/merchandise-claims.integration.spec.js#writes
      one committed unit per unit on the first location in allocation order,
      unit 0 and 1, each stamped with the order and the line
    origin: none
  - id: BR-CAP-COM-FUL-018-02
    proved_by: [ATS-COM-FUL-012-11, ATS-COM-FUL-014-08, ATS-COM-FUL-017-07, ATS-COM-FUL-018-02, ATS-COM-FUL-018-09, TST-COM-FUL-065, TST-COM-FUL-075]
    statement: >-
      A short claim either rejects insufficient stock or commits available units
      and backorders the remainder according to product policy, creating a
      first-location item when needed and excluding backorders from
      available-stock consumption.
    kind: policy
    enforced_at:
      - service
      - database
    must_prove: true
    provenance: test
    source: >-
      services-commerce:modules/inventory/tests/integration/services/stock/merchandise-claims.integration.spec.js#commits
      what exists and backorders the rest when the product allows it (A12), the
      shortfall counting as backordered, never against available
    origin: none
  - id: BR-CAP-COM-FUL-018-03
    proved_by: [ATS-COM-FUL-018-03, TST-COM-FUL-058, TST-COM-FUL-065]
    statement: >-
      Concurrent placements for the final stock permit one winner and reject the
      others as insufficient-stock claim conflicts without placing their orders.
    kind: invariant
    enforced_at:
      - database
    must_prove: true
    provenance: test
    source: >-
      services-commerce:modules/inventory/tests/e2e/merchandise-placement.e2e.spec.js#lets
      exactly one placement win and refuses the nine others 409 claim_conflict
      naming the item, the SKU and insufficient_stock
    origin: >-
      D-P8I-21 (build decision, not a product ruling):
      services-commerce:docs/migrations/inventory/README.md#D-P8I-21
  - id: BR-CAP-COM-FUL-018-04
    proved_by: [ATS-COM-FUL-018-04, ATS-COM-FUL-018-15, ATS-COM-FUL-019-08, TST-COM-FUL-058, TST-COM-FUL-063, TST-COM-FUL-065]
    statement: >-
      Limited stock can be held for checkout until expiry, extended only within
      the product window, committed at placement and released on order void.
    kind: lifecycle
    enforced_at:
      - service
      - database
    must_prove: true
    provenance: test
    source: >-
      services-commerce:modules/inventory/tests/e2e/merchandise-placement.e2e.spec.js#extends
      the hold within the window and refuses one past it, 409
      hold_not_extendable
    origin: none
  - id: BR-CAP-COM-FUL-018-05
    proved_by: [ATS-COM-FUL-004-12, ATS-COM-FUL-014-06, ATS-COM-FUL-018-05, ATS-COM-FUL-018-08, TST-COM-FUL-059, TST-COM-FUL-078]
    statement: >-
      Held units consume held balance and committed or picked units consume
      allocated balance; each row represents one unit, requires its
      state-specific references and cannot change item or duplicate a live
      checkout-unit hold.
    kind: invariant
    enforced_at:
      - database
    must_prove: true
    provenance: test
    source: >-
      services-commerce:modules/inventory/tests/integration/db/inventory-tables.table.integration.spec.js#counts
      a held row against held, a committed one against allocated and a released
      one against nothing, through the trigger
    origin: none
  - id: BR-CAP-COM-FUL-018-06
    proved_by: [ATS-COM-FUL-015-09, ATS-COM-FUL-017-08, ATS-COM-FUL-017-11, ATS-COM-FUL-018-06, ATS-COM-FUL-018-11, ATS-COM-FUL-018-14, ATS-COM-FUL-019-07, TST-COM-FUL-057, TST-COM-FUL-066]
    statement: >-
      One availability rule supplies storefront states and console counts,
      reporting untracked products available without stock numbers.
    kind: calculation
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-commerce:modules/inventory/tests/e2e/inventory.e2e.spec.js#answers
      the availability in the storefront’s words: limited with what is left,
      unavailable for more than the shelf has, backorder for the shirt,
      available for a product it does not track
    origin: none
  - id: BR-CAP-COM-FUL-018-07
    proved_by: [ATS-COM-FUL-012-12, ATS-COM-FUL-014-09, ATS-COM-FUL-018-07, ATS-COM-FUL-018-10, TST-COM-FUL-065, TST-COM-FUL-074]
    statement: >-
      Authorized delivery picks committed units, void and delivered cancellation
      release units with reasons, and partial cancellation releases only its
      selected units.
    kind: lifecycle
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-commerce:modules/inventory/tests/integration/services/stock/merchandise-claims.integration.spec.js#releases
      a line’s committed units on a void, giving the stock back; a release
      naming nothing live answers released: []
    origin: none
  - id: BR-CAP-COM-FUL-018-08
    proved_by: [ATS-COM-FUL-018-03, TST-COM-FUL-058, TST-COM-FUL-065]
    statement: >-
      A shipment and claim contending for the same item cannot consume the same
      unit.
    kind: invariant
    enforced_at:
      - database
    must_prove: true
    provenance: test
    source: >-
      services-commerce:modules/inventory/tests/integration/services/stock/merchandise-claims.integration.spec.js#answers
      the claim, once it gets the row, insufficient_stock: the unit the shipment
      took is not claimed twice
    origin: none
  - id: BR-CAP-COM-FUL-018-09
    proved_by: [ATS-COM-FUL-018-04, TST-COM-FUL-058, TST-COM-FUL-065]
    statement: 'Once checkout becomes an order, its checkout-item holds are released.'
    kind: lifecycle
    enforced_at:
      - service
    must_prove: false
    provenance: test
    source: >-
      services-commerce:modules/inventory/tests/integration/services/stock/merchandise-claims.integration.spec.js#releases
      a checkout item’s held units when the checkout stands as the order
      (D-P2-03)
    origin: none
  - id: BR-CAP-COM-FUL-018-10
    proved_by: []
    statement: >-
      Inventory-read authority permits allocation inspection by order, line,
      item, checkout item and state.
    kind: permission
    enforced_at:
      - api
    must_prove: false
    provenance: observed
    source: >-
      services-commerce:modules/inventory/aws/api/inventory.routes.ts:listInventoryAllocations
    origin: none
scenarios:
  - id: SC-CAP-COM-FUL-018-01
    given: Ten carts compete for a single remaining cap.
    when: Place all carts concurrently.
    then: 'One order succeeds, nine conflict and no stock remains available.'
    provenance: test
    source: >-
      services-commerce:modules/inventory/tests/e2e/merchandise-placement.e2e.spec.js#placed
      nothing for the losers (their checkouts open, the refusal on their trail)
      and left the shelf with the winner’s unit allocated and nothing available
edge_cases:
  - id: SC-CAP-COM-FUL-018-02
    given: Backorders are allowed and one unit is available.
    when: Place a two-unit purchase.
    then: >-
      One unit is committed and another backordered, with backorder availability
      for the next buyer.
    provenance: test
    source: >-
      services-commerce:modules/inventory/tests/e2e/merchandise-placement.e2e.spec.js#advised
      the two as a backorder of one, and placed them: one unit committed, one
      backordered, the SKU showing backorder to the next buyer
constraints: []
depends_on:
  - CAP-COM-FUL-016
related:
  - CAP-COM-FUL-012
  - CAP-COM-FUL-017
  - CAP-COM-FUL-019
journeys:
  - JNY-COM-FUL-003
open_questions: []
evidence:
  - repository: services-commerce
    paths:
      - >-
        modules/inventory/tests/integration/services/stock/merchandise-claims.integration.spec.js
      - modules/inventory/tests/e2e/merchandise-placement.e2e.spec.js
      - >-
        modules/inventory/tests/integration/db/inventory-tables.table.integration.spec.js
      - modules/inventory/tests/e2e/inventory.e2e.spec.js
      - modules/inventory/aws/api/inventory.routes.ts
controls: [TC-AZ-001, TC-AZ-002, TC-AZ-003, TC-AZ-004, TC-AZ-006, TC-TEN-001, TC-TEN-002, TC-TEN-003, TC-CRY-001, TC-DAT-001, TC-DAT-002, TC-DAT-003, TC-DAT-004, TC-LOG-004, TC-LOG-005, TC-PI-001, TC-PI-002, TC-PI-003, TC-PI-005, TC-PRV-001, TC-PRV-002]
exercised_by: [FAS-COM-FUL-04-01, FAS-COM-FUL-04-02, FAS-COM-FUL-04-03, FAS-COM-FUL-04-05]
suites: [TST-COM-FUL-057, TST-COM-FUL-058, TST-COM-FUL-059, TST-COM-FUL-063, TST-COM-FUL-065, TST-COM-FUL-066, TST-COM-FUL-074, TST-COM-FUL-075, TST-COM-FUL-078]
---

# Allocate stock and explain what buyers can obtain

## Purpose

Commerce reserves stock for checkout and commits units to accepted purchases.

## How It Works

Stock-aware selling begins with availability across sellable locations. A product's policy determines whether a shortage can become a backorder. Limited goods can be held while checkout is under way. Placement commits individual units, and later delivery and cancellation change their allocation state. The same records supply storefront availability and staff counts. Concurrent buyers contend through the stock safeguards rather than relying on the earlier availability display. The product should show which order or checkout holds each unavailable unit.

## Relationships

- Organize warehouses and stock locations supplies or consumes related delivery records.
- Prepare an order's goods for dispatch supplies or consumes related delivery records.
- Keep stock movements and transfers accountable supplies or consumes related delivery records.
- Reconcile shelf counts and stock findings supplies or consumes related delivery records.
