---
id: TST-COM-FUL-064
title: Inventory transfers
kind: integration
product_area: commerce
module: fulfillment
revision: 1
status: draft
source_sha:
  services-commerce: c8b66a98e2490617aec38ba5c8165dd9bd0a8f9b
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
repository: services-commerce
files:
  - modules/inventory/tests/integration/services/stock/inventory-transfers.integration.spec.js
implements:
  - ATS-COM-FUL-017-05
  - ATS-COM-FUL-017-06
environment: local
implementation_state: implemented
latest_result: not-run
latest_run_at: null
latest_run_ref: null
conformance: not-verified
estimated_minutes: 3
isolation: >-
  Run-created workspace identifiers and fixture records in the prepared test database; concurrency
  cases own their extra connections.
evidence:
  - repository: services-commerce
    path: modules/inventory/tests/integration/services/stock/inventory-transfers.integration.spec.js
    test_titles:
      - >-
        writes the pair in one transfer: a transfer_out of five on A1’s item and a transfer_in of
        five on A2’s, one id, each naming the other
      - 'makes the destination item, and moves on-hand on both: A1 seven to two, A2 none to five'
      - >-
        relieves the source’s layers oldest first under transfer_out (four at 1000, one at 1301),
        naming the transfer_out movement
      - >-
        makes the destination’s transfer_in layers at the weighted cost, the remainder one minor
        unit dearer, Σ exact
      - 'writes no posting fact for the transfer: nothing leaves the books'
      - >-
        leaves the valuation unchanged in total, both items reconciled, and the nightly cost pass
        finding nothing on the pair
      - answers a retry under the key with the same transfer and moves nothing twice
      - refuses the key reused for another transfer 409 idempotency_key_reused
      - 'refuses more than the source has available 409 insufficient_available, and writes nothing'
      - >-
        never moves an allocated unit: the two caps left on A1 claimed by an order, a transfer of
        one is refused
      - >-
        refuses the same location twice 400 same_location and a quantity of zero 400
        quantity_not_positive
      - refuses a SKU the source location does not hold 400 no_source_item
      - leaves the backorders waiting while the stock sits on the quarantine shelf (premise)
      - >-
        fills the two backorders in the transfer’s transaction, the units allocated on A1 at their
        cost
      - >-
        refuses a second transfer of the filled units 409 insufficient_available: they are the
        buyer’s now
      - >-
        finds a transfer_out no relief names relief_missing (the bare ledger pair, the cost never
        moved)
    scenario_anchors:
      - >-
        services-commerce:modules/inventory/tests/integration/services/stock/inventory-transfers.integration.spec.js#writes
        the pair in one transfer: a transfer_out of five on A1’s item and a transfer_in of five on
        A2’s, one id, each naming the other
      - >-
        services-commerce:modules/inventory/tests/integration/services/stock/inventory-transfers.integration.spec.js#makes
        the destination item, and moves on-hand on both: A1 seven to two, A2 none to five
      - >-
        services-commerce:modules/inventory/tests/integration/services/stock/inventory-transfers.integration.spec.js#relieves
        the source’s layers oldest first under transfer_out (four at 1000, one at 1301), naming the
        transfer_out movement
      - >-
        services-commerce:modules/inventory/tests/integration/services/stock/inventory-transfers.integration.spec.js#writes
        no posting fact for the transfer: nothing leaves the books
      - >-
        services-commerce:modules/inventory/tests/integration/services/stock/inventory-transfers.integration.spec.js#answers
        a retry under the key with the same transfer and moves nothing twice
      - >-
        services-commerce:modules/inventory/tests/integration/services/stock/inventory-transfers.integration.spec.js#refuses
        more than the source has available 409 insufficient_available, and writes nothing
      - >-
        services-commerce:modules/inventory/tests/integration/services/stock/inventory-transfers.integration.spec.js#never
        moves an allocated unit: the two caps left on A1 claimed by an order, a transfer of one is
        refused
      - >-
        services-commerce:modules/inventory/tests/integration/services/stock/inventory-transfers.integration.spec.js#refuses
        the same location twice 400 same_location and a quantity of zero 400 quantity_not_positive
      - >-
        services-commerce:modules/inventory/tests/integration/services/stock/inventory-transfers.integration.spec.js#refuses
        a SKU the source location does not hold 400 no_source_item
      - >-
        services-commerce:modules/inventory/tests/integration/services/stock/inventory-transfers.integration.spec.js#refuses
        the key reused for another transfer 409 idempotency_key_reused
      - >-
        services-commerce:modules/inventory/tests/integration/services/stock/inventory-transfers.integration.spec.js#refuses
        a second transfer of the filled units 409 insufficient_available: they are the buyer’s now
---

# Inventory transfers

## Verification Boundary

This suite checks inventory transfers against the prepared PostgreSQL database. Its entry points are the persistence and service functions used by the tests.

## What This Suite Proves

The bound scenarios identify the assertions this suite contributes. Source anchors retain the exact test cases; where a capability scenario has several contributing suites, a single binding does not imply that every branch runs here.

## What It Does Not Prove

Direct service and persistence calls do not establish the full HTTP permission contract, deployed scheduling or browser behavior. No execution result is claimed by this register.

## Real Dependencies and Test Doubles

The database and imported Commerce persistence services are real. Fixtures create the records owned by this run. Time-sensitive cases use a controlled clock where the source fixture supplies one.

## Must Not Be Doubled

Keep the database constraints, row visibility and persistence writes real when claiming this integration coverage. A canned repository response cannot replace the boundary being checked.
