---
id: ATS-COM-FUL-019
scope: CAP-COM-FUL-019
product_area: commerce
module: fulfillment
revision: 1
status: proposed
approved_by: null
approved_at: null
source_sha:
  services-commerce: c8b66a98e2490617aec38ba5c8165dd9bd0a8f9b
scenarios:
  - id: ATS-COM-FUL-019-01
    title: Completed counts retain corrections and refuse reopening
    level: api
    proves:
      - BR-CAP-COM-FUL-019-01
      - BR-CAP-COM-FUL-019-02
    preconditions: Two count items include one discrepancy.
    steps: >-
      Record and complete a count, then edit or complete again and cancel
      another count.
    expected: >-
      One correction and count timestamps remain, repeated changes fail and
      cancellation adds no correction.
    negative: true
    data_needs: Fixtures for completed counts retain corrections and refuse reopening.
    bound_to:
      - >-
        services-commerce:modules/inventory/tests/integration/services/stock/staff-movements.integration.spec.js#opens
        the count open with no lines, records the lines with what the shelf
        expected, and completes it with one correction for the variance
      - >-
        services-commerce:modules/inventory/tests/integration/services/stock/staff-movements.integration.spec.js#leaves
        the shelf as counted, stamped last_counted_at on both items
      - >-
        services-commerce:modules/inventory/tests/integration/services/stock/staff-movements.integration.spec.js#refuses
        lines on a completed count and a second completion (409), and the
        cancelled count wrote nothing
      - >-
        services-commerce:modules/inventory/tests/e2e/inventory.e2e.spec.js#opens
        a count, records what was counted, completes it with one correction, and
        cancels another; lines on a completed count 409
    provenance: test
    source: >-
      services-commerce:modules/inventory/tests/integration/services/stock/staff-movements.integration.spec.js#opens
      the count open with no lines, records the lines with what the shelf
      expected, and completes it with one correction for the variance
  - id: ATS-COM-FUL-019-02
    title: Finding resolution requires a result and allows later recurrence
    level: api
    proves:
      - BR-CAP-COM-FUL-019-03
    preconditions: A stock finding is open.
    steps: >-
      Acknowledge, try reasonless result, resolve properly, repeat and raise
      again.
    expected: >-
      Missing resolution and repeated closure fail, while later recurrence opens
      a fresh finding.
    negative: true
    data_needs: >-
      Fixtures for finding resolution requires a result and allows later
      recurrence.
    bound_to:
      - >-
        services-commerce:modules/inventory/tests/integration/services/stock/staff-movements.integration.spec.js#is
        raised open, acknowledged, resolved with its resolution, and raised
        again as a new row once resolved
      - >-
        services-commerce:modules/inventory/tests/e2e/inventory.e2e.spec.js#is
        listed and read, acknowledged, then resolved with its resolution (a
        second resolve 409; a resolution missing 400)
      - >-
        services-commerce:modules/inventory/tests/integration/db/inventory-tables.table.integration.spec.js#refuses
        two open findings of one kind about one subject, by
        inventory_exceptions_open_uidx, and a kind outside the six
    provenance: test
    source: >-
      services-commerce:modules/inventory/tests/integration/services/stock/staff-movements.integration.spec.js#is
      raised open, acknowledged, resolved with its resolution, and raised again
      as a new row once resolved
  - id: ATS-COM-FUL-019-03
    title: Nightly reconciliation reports discrepancies and expires holds
    level: api
    proves:
      - BR-CAP-COM-FUL-019-04
      - BR-CAP-COM-FUL-019-05
      - BR-CAP-COM-FUL-019-06
      - BR-CAP-COM-FUL-019-07
      - BR-CAP-COM-FUL-019-10
    preconditions: >-
      Fixtures include expired hold, balance mismatch, terminal allocation and
      low stock.
    steps: Run reconciliation twice.
    expected: >-
      Only expiry releases stock automatically and repeated discrepancies
      increment their open findings.
    negative: false
    data_needs: >-
      Fixtures for nightly reconciliation reports discrepancies and expires
      holds.
    bound_to:
      - >-
        services-commerce:modules/inventory/tests/integration/services/reconciliation/nightly-inventory.integration.spec.js#counts
        what it did: the tenant, one hold expired, three items checked, one
        mismatch, one stale unit, one low-stock SKU of two with a point, and the
        cost pass: three items whose stock no layer costs (the fixture’s bare
        receipts), no handoff without a relief
      - >-
        services-commerce:modules/inventory/tests/integration/services/reconciliation/nightly-inventory.integration.spec.js#releases
        the expired hold (reason expiry) and raises expired_hold on it, giving
        the unit back
      - >-
        services-commerce:modules/inventory/tests/integration/services/reconciliation/nightly-inventory.integration.spec.js#raises
        balance_mismatch on the item knocked out of line, with what was kept and
        what the ledgers say, and corrects nothing
      - >-
        services-commerce:modules/inventory/tests/integration/services/reconciliation/nightly-inventory.integration.spec.js#raises
        low_stock on shirt L at its own reorder point with the product’s reorder
        quantity, and nothing on the cap above its point
      - >-
        services-commerce:modules/inventory/tests/integration/services/reconciliation/nightly-inventory.integration.spec.js#raises
        stale_allocation on the committed unit whose obligation is cancelled
      - >-
        services-commerce:modules/inventory/tests/integration/services/reconciliation/nightly-inventory.integration.spec.js#finds
        the same on a second run and adds an occurrence to each open finding
        rather than another row
    provenance: test
    source: >-
      services-commerce:modules/inventory/tests/integration/services/reconciliation/nightly-inventory.integration.spec.js#counts
      what it did: the tenant, one hold expired, three items checked, one
      mismatch, one stale unit, one low-stock SKU of two with a point, and the
      cost pass: three items whose stock no layer costs (the fixture’s bare
      receipts), no handoff without a relief
  - id: ATS-COM-FUL-019-04
    title: Paged reconciliation reports a time-limited run honestly
    level: api
    proves:
      - BR-CAP-COM-FUL-019-08
    preconditions: Items and tracked products exceed one page.
    steps: Run with sufficient time and then with an exhausted time budget.
    expected: >-
      The full scan reaches later pages and the exhausted scan stops with
      incomplete coverage.
    negative: false
    data_needs: Fixtures for paged reconciliation reports a time-limited run honestly.
    bound_to:
      - >-
        services-commerce:modules/inventory/tests/integration/services/reconciliation/nightly-inventory-paging.integration.spec.js#checks
        every tracked SKU with a reorder point and raises each one at or below
        it, the last page’s included
      - >-
        services-commerce:modules/inventory/tests/integration/services/reconciliation/nightly-inventory-paging.integration.spec.js#re-derives
        every item, following the cursor past its first page
      - >-
        services-commerce:modules/inventory/tests/integration/services/reconciliation/nightly-inventory-paging.integration.spec.js#stops
        before it reads anything when the run has no time left, and answers that
        it is incomplete
    provenance: test
    source: >-
      services-commerce:modules/inventory/tests/integration/services/reconciliation/nightly-inventory-paging.integration.spec.js#checks
      every tracked SKU with a reorder point and raises each one at or below it,
      the last page’s included
  - id: ATS-COM-FUL-019-05
    title: Stock discovery rejects an existing transaction
    level: api
    proves:
      - BR-CAP-COM-FUL-019-11
    preconditions: A caller owns an open transaction.
    steps: Discover workspaces with stock within that transaction.
    expected: The sweep read fails rather than joining the caller's transaction.
    negative: true
    data_needs: Fixtures for stock discovery rejects an existing transaction.
    bound_to:
      - >-
        services-commerce:modules/inventory/tests/integration/services/reconciliation/nightly-inventory.integration.spec.js#finds
        the tenants that hold stock across tenants, under the sweep policy, this
        one among them, and refuses that read inside another transaction
    provenance: test
    source: >-
      services-commerce:modules/inventory/tests/integration/services/reconciliation/nightly-inventory.integration.spec.js#finds
      the tenants that hold stock across tenants, under the sweep policy, this
      one among them, and refuses that read inside another transaction
  - id: ATS-COM-FUL-019-06
    title: Counts and findings require mutation authority
    level: api
    proves:
      - BR-CAP-COM-FUL-019-12
    preconditions: A read-only inventory identity is available.
    steps: 'Try count creation and finding resolution, then read the records.'
    expected: Mutations fail while authorized inspection succeeds.
    negative: true
    data_needs: Fixtures for counts and findings require mutation authority.
    bound_to:
      - >-
        services-commerce:modules/inventory/tests/e2e/inventory.e2e.spec.js#lets
        a reader list and read everything, and refuses it every write 403
        permission_missing
    provenance: test
    source: >-
      services-commerce:modules/inventory/tests/e2e/inventory.e2e.spec.js#lets a
      reader list and read everything, and refuses it every write 403
      permission_missing
evidence:
  - repository: services-commerce
    tests:
      - >-
        services-commerce:modules/inventory/tests/integration/services/stock/staff-movements.integration.spec.js#opens
        the count open with no lines, records the lines with what the shelf
        expected, and completes it with one correction for the variance
      - >-
        services-commerce:modules/inventory/tests/integration/services/stock/staff-movements.integration.spec.js#leaves
        the shelf as counted, stamped last_counted_at on both items
      - >-
        services-commerce:modules/inventory/tests/integration/services/stock/staff-movements.integration.spec.js#refuses
        lines on a completed count and a second completion (409), and the
        cancelled count wrote nothing
      - >-
        services-commerce:modules/inventory/tests/e2e/inventory.e2e.spec.js#opens
        a count, records what was counted, completes it with one correction, and
        cancels another; lines on a completed count 409
      - >-
        services-commerce:modules/inventory/tests/integration/services/stock/staff-movements.integration.spec.js#is
        raised open, acknowledged, resolved with its resolution, and raised
        again as a new row once resolved
      - >-
        services-commerce:modules/inventory/tests/e2e/inventory.e2e.spec.js#is
        listed and read, acknowledged, then resolved with its resolution (a
        second resolve 409; a resolution missing 400)
      - >-
        services-commerce:modules/inventory/tests/integration/db/inventory-tables.table.integration.spec.js#refuses
        two open findings of one kind about one subject, by
        inventory_exceptions_open_uidx, and a kind outside the six
      - >-
        services-commerce:modules/inventory/tests/integration/services/reconciliation/nightly-inventory.integration.spec.js#counts
        what it did: the tenant, one hold expired, three items checked, one
        mismatch, one stale unit, one low-stock SKU of two with a point, and the
        cost pass: three items whose stock no layer costs (the fixture’s bare
        receipts), no handoff without a relief
      - >-
        services-commerce:modules/inventory/tests/integration/services/reconciliation/nightly-inventory.integration.spec.js#releases
        the expired hold (reason expiry) and raises expired_hold on it, giving
        the unit back
      - >-
        services-commerce:modules/inventory/tests/integration/services/reconciliation/nightly-inventory.integration.spec.js#raises
        balance_mismatch on the item knocked out of line, with what was kept and
        what the ledgers say, and corrects nothing
      - >-
        services-commerce:modules/inventory/tests/integration/services/reconciliation/nightly-inventory.integration.spec.js#raises
        low_stock on shirt L at its own reorder point with the product’s reorder
        quantity, and nothing on the cap above its point
      - >-
        services-commerce:modules/inventory/tests/integration/services/reconciliation/nightly-inventory.integration.spec.js#raises
        stale_allocation on the committed unit whose obligation is cancelled
      - >-
        services-commerce:modules/inventory/tests/integration/services/reconciliation/nightly-inventory.integration.spec.js#finds
        the same on a second run and adds an occurrence to each open finding
        rather than another row
      - >-
        services-commerce:modules/inventory/tests/integration/services/reconciliation/nightly-inventory-paging.integration.spec.js#checks
        every tracked SKU with a reorder point and raises each one at or below
        it, the last page’s included
      - >-
        services-commerce:modules/inventory/tests/integration/services/reconciliation/nightly-inventory-paging.integration.spec.js#re-derives
        every item, following the cursor past its first page
      - >-
        services-commerce:modules/inventory/tests/integration/services/reconciliation/nightly-inventory-paging.integration.spec.js#stops
        before it reads anything when the run has no time left, and answers that
        it is incomplete
      - >-
        services-commerce:modules/inventory/tests/integration/services/reconciliation/nightly-inventory.integration.spec.js#finds
        the tenants that hold stock across tenants, under the sweep policy, this
        one among them, and refuses that read inside another transaction
      - >-
        services-commerce:modules/inventory/tests/e2e/inventory.e2e.spec.js#lets
        a reader list and read everything, and refuses it every write 403
        permission_missing
---

# Reconcile shelf counts and stock findings: Acceptance Test Set

## Coverage

| Rule | Acceptance Scenarios |
|---|---|
| `BR-CAP-COM-FUL-019-01` | `ATS-COM-FUL-019-01` |
| `BR-CAP-COM-FUL-019-02` | `ATS-COM-FUL-019-01` |
| `BR-CAP-COM-FUL-019-03` | `ATS-COM-FUL-019-02` |
| `BR-CAP-COM-FUL-019-04` | `ATS-COM-FUL-019-03` |
| `BR-CAP-COM-FUL-019-05` | `ATS-COM-FUL-019-03` |
| `BR-CAP-COM-FUL-019-06` | `ATS-COM-FUL-019-03` |
| `BR-CAP-COM-FUL-019-07` | `ATS-COM-FUL-019-03` |
| `BR-CAP-COM-FUL-019-08` | `ATS-COM-FUL-019-04` |
| `BR-CAP-COM-FUL-019-09` | Not required for approval |
| `BR-CAP-COM-FUL-019-10` | `ATS-COM-FUL-019-03` |
| `BR-CAP-COM-FUL-019-11` | `ATS-COM-FUL-019-05` |
| `BR-CAP-COM-FUL-019-12` | `ATS-COM-FUL-019-06` |
