---
id: CAP-COM-FUL-012
title: Prepare an order's goods for dispatch
feature: FEAT-COM-FUL-03
product_area: commerce
module: fulfillment
revision: 1
status: draft
product_intent: proposed
implementation_evidence: partially-observed
supersedes:
  - CAP-COM-SHP-005
  - CAP-COM-SHP-006
  - CAP-COM-SHP-007
  - CAP-COM-SHP-008
  - CAP-COM-SHP-009
  - CAP-COM-SHP-010
  - CAP-COM-SHP-013
  - CAP-COM-SHP-016
  - CAP-COM-SHP-026
  - CAP-COM-SHP-027
  - CAP-COM-SHP-028
  - CAP-COM-SHP-030
  - CAP-COM-REG-039
  - CAP-COM-REG-045
source_sha:
  services-commerce: c8b66a98e2490617aec38ba5c8165dd9bd0a8f9b
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
intent_sources: []
purpose: Warehouse staff organize committed units into shipments and parcels.
outcomes:
  - Warehouse work follows the order's committed goods at their stock locations.
  - Shipment history explains its warehouse progression.
concepts:
  - CON-COM-FUL-004
  - CON-COM-FUL-005
actors:
  - ACT-COM-010
surfaces:
  - api
  - console
preconditions: []
postconditions: []
permissions:
  - key: commerce.shipments.read
    where_checked: api
    scope: tenant
  - key: commerce.shipments.create
    where_checked: api
    scope: tenant
  - key: commerce.shipments.update
    where_checked: api
    scope: tenant
  - key: commerce.shipments.cancel
    where_checked: api
    scope: tenant
  - key: commerce.pick-lists.read
    where_checked: api
    scope: tenant
  - key: commerce.pick-lists.create
    where_checked: api
    scope: tenant
  - key: commerce.pick-lists.update
    where_checked: api
    scope: tenant
  - key: orders.orders.ship
    where_checked: console
    scope: tenant
rules:
  - id: BR-CAP-COM-FUL-012-01
    proved_by: [ATS-COM-FUL-012-01, TST-COM-FUL-075, TST-COM-FUL-078]
    statement: >-
      Shipment creation groups committed and picked units not already assigned
      to a shipment into contiguous line ranges at the requested warehouse or
      the warehouse holding most units, using the order's destination, charge,
      strategy, carrier and service; an empty candidate set is rejected.
    kind: validation
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-commerce:modules/shipping/tests/integration/services/fulfillment/shipping-flow.integration.spec.js#makes
      the shipment from the order’s three picked units as one line (units 0..2)
      at the warehouse, numbered, addressed from the order, charged what the
      order paid, on the strategy’s carrier and service
    origin: none
  - id: BR-CAP-COM-FUL-012-02
    proved_by: [ATS-COM-FUL-012-02, ATS-COM-FUL-012-11, ATS-COM-FUL-014-08, ATS-COM-FUL-017-07, ATS-COM-FUL-018-09, TST-COM-FUL-075]
    statement: >-
      A later shipping wave can pick replenished backorders under their
      obligations and place those units on a new shipment.
    kind: lifecycle
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-commerce:modules/shipping/tests/e2e/shipping.e2e.spec.js#fills
      the two backorders at the receipt, and the second wave picks the filled
      units at its creation (3..4) and ships them
    origin: none
  - id: BR-CAP-COM-FUL-012-03
    proved_by: [ATS-COM-FUL-011-11, ATS-COM-FUL-012-03, ATS-COM-FUL-012-09, TST-COM-FUL-075, TST-COM-FUL-078]
    statement: >-
      A pickup choice creates a shipment at the selected collection warehouse
      with no carrier or shipping charge.
    kind: policy
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-commerce:modules/shipping/tests/integration/services/fulfillment/shipping-flow.integration.spec.js#makes
      a pickup shipment of the order at the pick-up warehouse, on no carrier,
      charged nothing
    origin: >-
      Decision L, Andrew 2026-10-18 ("add it now"):
      services-commerce:docs/migrations/shipping/README.md#D-P8S-14
  - id: BR-CAP-COM-FUL-012-04
    proved_by: [ATS-COM-FUL-012-04, ATS-COM-FUL-012-10, ATS-COM-FUL-013-10, ATS-COM-FUL-014-07, TST-COM-FUL-077, TST-COM-FUL-078]
    statement: >-
      Releasing a shipment queues its lines for picking, and a warehouse pick
      list gathers released lines absent from another open list at their
      recorded stock locations.
    kind: lifecycle
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-commerce:modules/shipping/tests/integration/services/fulfillment/shipping-flow.integration.spec.js#releases
      the shipment to the floor and lists its line for picking at the bin the
      ledger names, the shipment picking
    origin: none
  - id: BR-CAP-COM-FUL-012-05
    proved_by: [ATS-COM-FUL-012-04, ATS-COM-FUL-012-05, TST-COM-FUL-077, TST-COM-FUL-078]
    statement: >-
      Claimed pick lists identify the picker, accept full or short picks, raise
      SKU findings for shortages, complete after every line is decided and
      return unpicked cancelled-list lines to the queue.
    kind: lifecycle
    enforced_at:
      - service
      - database
    must_prove: true
    provenance: test
    source: >-
      services-commerce:modules/shipping/tests/integration/db/shipping-tables.table.integration.spec.js#holds
      a picked line to its whole quantity and a short one to less, by
      pick_list_lines_picked_check, and a claimed list to its picker, by
      pick_lists_claimed_check
    origin: none
  - id: BR-CAP-COM-FUL-012-06
    proved_by: [ATS-COM-FUL-012-04, ATS-COM-FUL-012-10, ATS-COM-FUL-013-10, ATS-COM-FUL-014-07, TST-COM-FUL-077, TST-COM-FUL-078]
    statement: >-
      Packing assigns picked, unpacked quantities to parcels, derives unstated
      parcel weights from their contents and marks the shipment packed when all
      live lines are packed.
    kind: calculation
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-commerce:modules/shipping/tests/integration/services/fulfillment/shipping-flow.integration.spec.js#packs
      the three units into two parcels, the second weighed from nothing (the
      shirt has no weight), the line packed, the shipment packed with two
      packages
    origin: none
  - id: BR-CAP-COM-FUL-012-07
    proved_by: [ATS-COM-FUL-012-10, ATS-COM-FUL-013-10, ATS-COM-FUL-014-07, TST-COM-FUL-078]
    statement: >-
      Manifesting a labelled shipment closes its carrier manifest and advances
      the shipment, lines and parcels together.
    kind: lifecycle
    enforced_at:
      - service
    must_prove: false
    provenance: test
    source: >-
      services-commerce:modules/shipping/tests/integration/services/fulfillment/shipping-flow.integration.spec.js#manifests
      the labelled shipment, its line and packages with it
    origin: none
  - id: BR-CAP-COM-FUL-012-08
    proved_by: [ATS-COM-FUL-012-06, ATS-COM-FUL-012-12, ATS-COM-FUL-012-13, ATS-COM-FUL-014-09, ATS-COM-FUL-018-10, TST-COM-FUL-074, TST-COM-FUL-078]
    statement: >-
      Cancellation before handover cancels lines, releases shipment stamps while
      retaining order ownership, voids labels and pulls parcels; shipped or
      collected shipments reject cancellation.
    kind: lifecycle
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-commerce:modules/shipping/tests/integration/services/fulfillment/shipping-flow.integration.spec.js#refuses
      a second handover (not packed any more) and the cancellation of a
      collected shipment
    origin: none
  - id: BR-CAP-COM-FUL-012-09
    proved_by: [ATS-COM-FUL-012-07, TST-COM-FUL-077, TST-COM-FUL-080]
    statement: Shipment events are immutable and presented from oldest to newest.
    kind: invariant
    enforced_at:
      - database
    must_prove: true
    provenance: test
    source: >-
      services-commerce:modules/shipping/tests/integration/db/shipping-tables.table.integration.spec.js#lets
      the application role insert an event and refuses it UPDATE, DELETE and
      TRUNCATE, 42501
    origin: none
  - id: BR-CAP-COM-FUL-012-10
    proved_by: []
    statement: >-
      Shipment numbers and tracking numbers are unique within a workspace,
      parcel sequences are unique within a shipment, and line quantity agrees
      with its unit range.
    kind: invariant
    enforced_at:
      - database
    must_prove: false
    provenance: test
    source: >-
      services-commerce:modules/shipping/tests/integration/db/shipping-tables.table.integration.spec.js#writes
      a shipment of the order with a line of two units (premise), and refuses a
      second shipment with the same number, by shipments_number_uq
    origin: none
  - id: BR-CAP-COM-FUL-012-11
    proved_by: [ATS-COM-FUL-012-08]
    statement: >-
      Shipment creation requires create authority, warehouse progression
      requires update authority and cancellation requires sensitive
      administrator authority.
    kind: permission
    enforced_at:
      - api
    must_prove: true
    provenance: observed
    source: 'services-commerce:aws/commerce.service.ts:ShipmentsPermissions'
    origin: none
  - id: BR-CAP-COM-FUL-012-12
    proved_by: []
    statement: >-
      Order 360 offers shipment creation and label printing under their action
      permissions without exposing the remaining warehouse progression steps.
    kind: policy
    enforced_at:
      - console
    must_prove: false
    provenance: test
    source: >-
      react-console:lib/commerce/order-flows/__tests__/live.test.ts#offers the
      active carriers and Manual, and creates the shipment from the chosen lines
    origin: none
scenarios:
  - id: SC-CAP-COM-FUL-012-01
    given: Three paid shirts are ready at one warehouse.
    when: >-
      Create and release shipment work, pick, pack two parcels, label and
      manifest.
    then: >-
      The manifested shipment retains both parcels and a chronological record of
      its progression.
    provenance: test
    source: >-
      services-commerce:modules/shipping/tests/integration/services/fulfillment/shipping-flow.integration.spec.js#keeps
      the whole history on the shipment, oldest first
edge_cases:
  - id: SC-CAP-COM-FUL-012-02
    given: Every ordered unit has already been shipped.
    when: Request an additional wave.
    then: The service reports that no units remain to ship.
    provenance: test
    source: >-
      services-commerce:modules/shipping/tests/e2e/shipping.e2e.spec.js#refuses
      a third wave: nothing is left to ship (409 nothing_to_ship)
constraints: []
depends_on:
  - CAP-COM-FUL-018
related:
  - CAP-COM-FUL-013
  - CAP-COM-FUL-014
journeys:
  - JNY-COM-FUL-003
open_questions: []
evidence:
  - repository: services-commerce
    paths:
      - >-
        modules/shipping/tests/integration/services/fulfillment/shipping-flow.integration.spec.js
      - modules/shipping/tests/e2e/shipping.e2e.spec.js
      - >-
        modules/shipping/tests/integration/db/shipping-tables.table.integration.spec.js
      - aws/commerce.service.ts
  - repository: react-console
    paths:
      - lib/commerce/order-flows/__tests__/live.test.ts
controls: [TC-IAM-006, 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-DAT-001, TC-DAT-002, TC-DAT-003, TC-DAT-004, TC-LOG-001, TC-LOG-002, TC-LOG-003, TC-LOG-004, TC-LOG-005, TC-AVL-004, TC-MON-001, TC-MON-002, TC-MON-004, TC-PI-001, TC-PI-002, TC-PI-003, TC-PI-004, TC-PI-005, TC-VEN-001, TC-VEN-002, TC-VEN-003, TC-PRV-001, TC-PRV-002]
exercised_by: [FAS-COM-FUL-03-01, FAS-COM-FUL-03-03, FAS-COM-FUL-03-04, FAS-COM-FUL-03-05]
suites: [TST-COM-FUL-074, TST-COM-FUL-075, TST-COM-FUL-077, TST-COM-FUL-078, TST-COM-FUL-080]
---

# Prepare an order's goods for dispatch

## Purpose

Warehouse staff organize committed units into shipments and parcels.

## How It Works

Staff create a shipment for an order at a warehouse. Released shipment lines become picking work, which a picker claims and records. Packing turns the picked quantities into parcels. Carrier shipments continue through labels and manifesting, while pickup follows its collection path. Replenished backorders can form a later shipping wave. Cancellation removes the shipment's assignment while preserving the underlying order. The product should provide the warehouse screens needed to complete this sequence without direct service calls.

## Relationships

- Allocate stock and explain what buyers can obtain supplies or consumes related delivery records.
- Purchase and follow carrier labels safely supplies or consumes related delivery records.
- Record goods leaving with a carrier or collector supplies or consumes related delivery records.
