---
id: WF-COM-ORD-015
title: Receive stock and record its cost
trigger: A receiver submits keyed goods receipt against a purchase order or directly.
product_area: commerce
module: orders
revision: 1
status: draft
design_intent: proposed
implementation_evidence: observed
inference: []
source_sha:
  services-commerce: c8b66a98e2490617aec38ba5c8165dd9bd0a8f9b
implements:
  - CAP-COM-ORD-018
  - CAP-COM-ORD-017
moves:
  - STATE-COM-ORD-013
crosses:
  - SVC-COM-ORD-purchasing
  - SVC-ACC-PRD-products
idempotency: >-
  A receipt key identifies its existing recorded receipt; repeating it makes no additional movements, layers
  or allocations.
concurrency: >-
  The purchase-order lock serializes receipt quantities and lifecycle actions. Backorder allocation
  participates in the same receipt transaction.
hops:
  - 'n': 1
    actor_or_service: Purchasing route
    action: >-
      Replay an existing receipt key or lock an eligible purchase order, resolve defaults and line details,
      validate outstanding units and explain any cost deviation.
    anchor: 'services-commerce:modules/purchasing/services/receiving/receive-stock.ts:recordReceipt'
    seam: sync
    on_failure: 'Invalid state, excess quantity or unexplained cost change refuses before recording receipt effects.'
    left_inconsistent: No partial goods receipt commits.
    observer: Observed through the receiving operator.
    provenance: test
    source: >-
      services-commerce:modules/purchasing/tests/integration/services/receiving/purchasing-flow.integration.spec.js#refuses
      a receipt line whose cost differs from the order line’s without a reason, and takes one with a reason
  - 'n': 2
    actor_or_service: Receiving transaction
    action: >-
      Record numbered receipt, condition movements, rounded landed-cost shares, layers, capitalization facts
      and received quantities, then update order progress and allocate sellable stock to oldest backorders.
    anchor: 'services-commerce:modules/purchasing/services/receiving/receive-stock.ts:recordReceipt'
    seam: sync
    on_failure: Failure rolls back all receipt effects in the shared transaction.
    left_inconsistent: 'Stock, cost and backorder writes cannot commit independently.'
    observer: Observed through the receiving operator; inventory availability.
    provenance: test
    source: >-
      services-commerce:modules/purchasing/tests/integration/services/receiving/purchasing-flow.integration.spec.js#fills
      the two backorders at the first receipt, oldest first, converting them to committed; the shelf shows 58
      available after
  - 'n': 3
    actor_or_service: Accounting
    action: Expose dated unposted facts for Accounting and record its posting references.
    anchor: 'services-commerce:modules/purchasing/services/persistence/inventory-postings.ts:stampPostingsPosted'
    seam: sync
    on_failure: A repeated matching reference is accepted while a conflicting reference is refused.
    left_inconsistent: Facts remain pending until an external Accounting intake posts them.
    observer: Observed through observed through accounting's intake; the unposted list.
    provenance: test
    source: >-
      services-commerce:modules/purchasing/tests/e2e/purchasing.e2e.spec.js#lists the facts unposted (the two
      receipts’), stamps them posted under Accounting’s reference, and lists none unposted after
branches:
  - A receipt can acquire inventory without a purchase order.
  - Cost persistence resolves business-unit ownership from Accounting.
waits:
  - External posting intake must process the acquisition facts.
evidence:
  - >-
    services-commerce at c8b66a98: modules/purchasing/services/receiving/receive-stock.ts;
    services/cost/cost-accounting.ts; services/persistence/*.ts;
    tests/integration/services/receiving/purchasing-flow.integration.spec.js;
    tests/e2e/purchasing.e2e.spec.js.
controls: [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-CRY-001, TC-CRY-004, TC-DAT-001, TC-DAT-002, TC-DAT-003, TC-LOG-004, TC-LOG-005, TC-PI-001, TC-PI-002, TC-PI-003, TC-PI-005, TC-PRV-001, TC-PRV-002]
---

# Receive stock and record its cost

## What It Does

Receiving records goods and acquisition cost once per receipt key. Sellable arrivals also satisfy waiting backorders, and immutable facts support subsequent Accounting posting.

## The Flow

```mermaid
sequenceDiagram
  participant R as Receiver
  participant P as Purchasing
  participant I as Inventory ledger
  participant X as Accounting
  R->>P: receipt (key)
  P->>P: replay check; lock purchase order; validate
  P->>I: one transaction: movements, layers, capitalization facts, received quantities, backorder fill
  P-->>R: receipt
  X->>P: unposted facts
  X->>P: stamp posted (reference)
```

## When Something Fails

The stock movement, layer, financial fact, received quantities and backorder allocation roll back together on failure. Posting stamps reject conflicting references while accepting repeated matching ones.

## Open Design Questions

Purchasing administration has no live console screens. The facts and stamp API does not establish an implemented Accounting intake.
