---
id: ATS-COM-ORD-001
scope: CAP-COM-ORD-001
product_area: commerce
module: orders
revision: 1
status: proposed
approved_by: null
approved_at: null
source_sha:
  services-commerce: c8b66a98e2490617aec38ba5c8165dd9bd0a8f9b
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
scenarios:
  - id: ATS-COM-ORD-001-01
    title: Portal purchase cannot name another contact
    level: api
    proves:
      - BR-CAP-COM-ORD-001-01
    preconditions: The signed-in member and a different contact share a workspace.
    steps: Attempt creation with the different contact as buyer.
    expected: The response is 403 and creation does not proceed.
    negative: true
    data_needs: Use the controlled records and transports established by the cited tests.
    bound_to:
      - >-
        services-commerce:modules/checkout/tests/e2e/checkouts.e2e.spec.js#refuses a member opening a checkout
        for another contact, 403
    provenance: test
    source: >-
      services-commerce:modules/checkout/tests/e2e/checkouts.e2e.spec.js#refuses a member opening a checkout
      for another contact, 403
  - id: ATS-COM-ORD-001-02
    title: Invalid items leave the cart unchanged
    level: api
    proves:
      - BR-CAP-COM-ORD-001-02
    preconditions: >-
      The fixtures include retired and unsellable products, a two-unit limit, a required payload and USD-only
      support.
    steps: 'Submit the invalid product, excessive quantity, malformed details and unsupported currency cases.'
    expected: Each request returns 400 with the relevant item or currency problem and no accepted item write.
    negative: true
    data_needs: Use the controlled records and transports established by the cited tests.
    bound_to:
      - >-
        services-commerce:modules/checkout/tests/e2e/checkouts.e2e.spec.js#refuses a product the tenant does
        not have: product_not_sellable
      - >-
        services-commerce:modules/checkout/tests/e2e/checkouts.e2e.spec.js#refuses a retired product and an
        unsellable product type: product_not_sellable
      - >-
        services-commerce:modules/checkout/tests/e2e/checkouts.e2e.spec.js#refuses a quantity past the
        product’s purchase limit: quantity_out_of_limits
      - >-
        services-commerce:modules/checkout/tests/e2e/checkouts.e2e.spec.js#refuses a payload that does not
        parse as the participant’s schema: payload_does_not_parse
      - >-
        services-commerce:modules/checkout/tests/e2e/checkouts.e2e.spec.js#refuses a currency the business
        unit does not support: currency_not_supported
    provenance: test
    source: >-
      services-commerce:modules/checkout/tests/e2e/checkouts.e2e.spec.js#refuses a product the tenant does not
      have: product_not_sellable
  - id: ATS-COM-ORD-001-03
    title: Party references require record identities
    level: api
    proves:
      - BR-CAP-COM-ORD-001-03
    preconditions: Contact records have both internal identities and alternative text labels.
    steps: 'Use alternative labels for the buyer, acting contact, bill-to and recipient.'
    expected: Validation returns 400 identifying the offending field before saving.
    negative: true
    data_needs: Use the controlled records and transports established by the cited tests.
    bound_to:
      - >-
        services-commerce:modules/checkout/tests/e2e/checkout-record-ids.e2e.spec.js#refuses a buyer that is a
        slug when the checkout is opened, 400 naming buyer_id, and writes nothing
      - >-
        services-commerce:modules/checkout/tests/e2e/checkout-record-ids.e2e.spec.js#refuses an acting
        contact, a bill-to and a recipient that are slugs, each naming its field
    provenance: test
    source: >-
      services-commerce:modules/checkout/tests/e2e/checkout-record-ids.e2e.spec.js#refuses a buyer that is a
      slug when the checkout is opened, 400 naming buyer_id, and writes nothing
  - id: ATS-COM-ORD-001-04
    title: Organization authority can be overridden by permitted staff
    level: api
    proves:
      - BR-CAP-COM-ORD-001-04
    preconditions: A contact lacks the organization’s required role; two staff contexts differ in placement authority.
    steps: Attempt the organization purchase as the member and each staff context.
    expected: The authorized staff case records an override; the other cases return buyer_may_not_act.
    negative: false
    data_needs: Use the controlled records and transports established by the cited tests.
    bound_to:
      - >-
        services-commerce:modules/checkout/tests/e2e/checkouts.e2e.spec.js#accepts a member who holds the
        store’s purchasing role at the organization
      - >-
        services-commerce:modules/checkout/tests/e2e/checkouts.e2e.spec.js#refuses a member affiliated without
        the role: buyer_may_not_act, NOT_AUTHORIZED_FOR_ORGANIZATION
      - >-
        services-commerce:modules/checkout/tests/e2e/checkouts.e2e.spec.js#lets a console user with
        commerce.orders.create buy for the organization naming any acting contact, and audits the override
      - >-
        services-commerce:modules/checkout/tests/e2e/checkouts.e2e.spec.js#refuses a console clerk without
        commerce.orders.create the same purchase, 400 buyer_may_not_act
    provenance: test
    source: >-
      services-commerce:modules/checkout/tests/e2e/checkouts.e2e.spec.js#accepts a member who holds the
      store’s purchasing role at the organization
  - id: ATS-COM-ORD-001-05
    title: Public assortment checks permit staff exceptions
    level: api
    proves:
      - BR-CAP-COM-ORD-001-05
    preconditions: One fixture product is unpublished and another falls outside the selected assortment.
    steps: Try both products as a portal buyer and as authorized console staff.
    expected: Portal requests return publication or assortment problems; staff can retain both items.
    negative: false
    data_needs: Use the controlled records and transports established by the cited tests.
    bound_to:
      - >-
        services-commerce:modules/checkout/tests/e2e/checkout-public-sale.e2e.spec.js#refuses a portal member
        opening a checkout with a draft product: 400 product_not_published, naming the store, nothing written
      - >-
        services-commerce:modules/checkout/tests/e2e/checkout-public-sale.e2e.spec.js#refuses a portal member
        a published product the store does not admit: 400 product_not_in_store_assortment
      - >-
        services-commerce:modules/checkout/tests/e2e/checkout-public-sale.e2e.spec.js#lets a console user
        holding commerce.orders.create open a checkout with the draft product and add the one outside the
        assortment
    provenance: test
    source: >-
      services-commerce:modules/checkout/tests/e2e/checkout-public-sale.e2e.spec.js#refuses a portal member
      opening a checkout with a draft product: 400 product_not_published, naming the store, nothing written
  - id: ATS-COM-ORD-001-06
    title: Cart changes retain version and actor evidence
    level: api
    proves:
      - BR-CAP-COM-ORD-001-06
    preconditions: An open cart and a stand-in support identity are available.
    steps: 'Add, replace and remove items, then inspect version and event data.'
    expected: Versions advance and the event helper records the supplied support actor.
    negative: false
    data_needs: Use the controlled records and transports established by the cited tests.
    bound_to:
      - >-
        services-commerce:modules/checkout/tests/e2e/checkouts.e2e.spec.js#adds after the last, changes the
        intent and clears what was advised, removes, each bumping the version
      - 'services-commerce:modules/checkout/tests/e2e/checkouts.e2e.spec.js#leaves an event for every change'
      - >-
        services-commerce:modules/checkout/tests/unit/checkout/checkout-event-actor.spec.js#names the support
        identity as the actor of the event
    provenance: test
    source: >-
      services-commerce:modules/checkout/tests/e2e/checkouts.e2e.spec.js#adds after the last, changes the
      intent and clears what was advised, removes, each bumping the version
  - id: ATS-COM-ORD-001-07
    title: Expiry processing respects limits and workspace ownership
    level: api
    proves:
      - BR-CAP-COM-ORD-001-07
    preconditions: Expired carts span two workspaces alongside live and placed records.
    steps: 'Run expiry selection and abandonment with a bounded limit, then run again.'
    expected: Expired records are processed in expiry order within their workspace; other states remain untouched.
    negative: false
    data_needs: Use the controlled records and transports established by the cited tests.
    bound_to:
      - >-
        services-commerce:modules/checkout/tests/integration/services/checkout/checkout-sweeper.integration.spec.js#abandoned
        each expired open checkout in its own tenant, with the system as the actor and expired as the reason
      - >-
        services-commerce:modules/checkout/tests/integration/services/checkout/checkout-sweeper.integration.spec.js#takes
        at most the limit, oldest expiry first, and leaves the rest to the next run; a cancelled checkout is
        not found
      - >-
        services-commerce:modules/checkout/tests/e2e/checkouts.e2e.spec.js#expires seven days out, and the
        first item carries the participant’s current schema version, unvalidated
    provenance: test
    source: >-
      services-commerce:modules/checkout/tests/integration/services/checkout/checkout-sweeper.integration.spec.js#abandoned
      each expired open checkout in its own tenant, with the system as the actor and expired as the reason
  - id: ATS-COM-ORD-001-08
    title: Abandonment releases the held item
    level: api
    proves:
      - BR-CAP-COM-ORD-001-08
    preconditions: A cart has an application-held scarce resource.
    steps: Abandon it and attempt a later item addition.
    expected: The hold is released with history and the later addition returns checkout_not_open.
    negative: true
    data_needs: Use the controlled records and transports established by the cited tests.
    bound_to:
      - >-
        services-commerce:modules/checkout/tests/e2e/checkouts.e2e.spec.js#moves an open checkout to
        abandoned, after which it no longer changes (409 checkout_not_open)
      - >-
        services-commerce:modules/checkout/tests/e2e/holds-and-claims.e2e.spec.js#releases every hold when the
        checkout is abandoned
    provenance: test
    source: >-
      services-commerce:modules/checkout/tests/e2e/checkouts.e2e.spec.js#moves an open checkout to abandoned,
      after which it no longer changes (409 checkout_not_open)
  - id: ATS-COM-ORD-001-09
    title: Scarce holds reject competing or excessive requests
    level: api
    proves:
      - BR-CAP-COM-ORD-001-09
    preconditions: The last booth is reserved for one buyer.
    steps: 'Request it as a second buyer, extend beyond the allowed ceiling and remove the held item.'
    expected: >-
      The competing and excessive requests return hold_unavailable and hold_not_extendable; removal releases
      the resource.
    negative: true
    data_needs: Use the controlled records and transports established by the cited tests.
    bound_to:
      - >-
        services-commerce:modules/checkout/tests/e2e/holds-and-claims.e2e.spec.js#acquires the hold: 200 with
        the reservation held, the item prepared with it, the participant’s row held, hold_acquired on the
        trail
      - >-
        services-commerce:modules/checkout/tests/e2e/holds-and-claims.e2e.spec.js#refuses another buyer the
        booth: 409 hold_unavailable with the participant’s reason, and their preview marks the item
        unavailable
      - >-
        services-commerce:modules/checkout/tests/e2e/holds-and-claims.e2e.spec.js#refuses an extension past
        the policy’s ceiling, 409 hold_not_extendable with the participant’s problem
      - >-
        services-commerce:modules/checkout/tests/e2e/holds-and-claims.e2e.spec.js#releases an item’s hold
        through the participant when the item is removed, with holds_released on the trail
    provenance: test
    source: >-
      services-commerce:modules/checkout/tests/e2e/holds-and-claims.e2e.spec.js#acquires the hold: 200 with
      the reservation held, the item prepared with it, the participant’s row held, hold_acquired on the trail
  - id: ATS-COM-ORD-001-10
    title: Cart transitions reject skipped and terminal moves
    level: api
    proves:
      - BR-CAP-COM-ORD-001-14
    preconditions: An open cart exists and a separate cart has completed placement.
    steps: >-
      Attempt direct placement without preparation, place without an order link and transition the placed
      cart; also exercise permitted preparation and cancellation transitions.
    expected: Invalid moves are refused and allowed moves preserve their required order linkage.
    negative: true
    data_needs: Use the isolated checkout records prepared by the persistence suite.
    bound_to:
      - >-
        services-commerce:modules/checkout/tests/integration/services/persistence/checkouts.integration.spec.js#refuses
        open to placed (preparing comes first), and lets open go abandoned or cancelled
      - >-
        services-commerce:modules/checkout/tests/integration/services/persistence/checkouts.integration.spec.js#refuses
        placed without an order, and any other status with one, 409
      - >-
        services-commerce:modules/checkout/tests/integration/services/persistence/checkouts.integration.spec.js#refuses
        every move out of placed, 409
    provenance: test
    source: >-
      services-commerce:modules/checkout/tests/integration/services/persistence/checkouts.integration.spec.js#refuses
      open to placed (preparing comes first), and lets open go abandoned or cancelled
evidence:
  - >-
    Examined reference: services-commerce:modules/checkout/tests/e2e/checkout-public-sale.e2e.spec.js#lets a
    console user holding commerce.orders.create open a checkout with the draft product and add the one outside
    the assortment
  - >-
    Examined reference: services-commerce:modules/checkout/tests/e2e/checkout-public-sale.e2e.spec.js#refuses
    a portal member a published product the store does not admit: 400 product_not_in_store_assortment
  - >-
    Examined reference: services-commerce:modules/checkout/tests/e2e/checkout-public-sale.e2e.spec.js#refuses
    a portal member opening a checkout with a draft product: 400 product_not_published, naming the store,
    nothing written
  - >-
    Examined reference: services-commerce:modules/checkout/tests/e2e/checkout-record-ids.e2e.spec.js#refuses a
    buyer that is a slug when the checkout is opened, 400 naming buyer_id, and writes nothing
  - >-
    Examined reference: services-commerce:modules/checkout/tests/e2e/checkout-record-ids.e2e.spec.js#refuses
    an acting contact, a bill-to and a recipient that are slugs, each naming its field
  - >-
    Examined reference: services-commerce:modules/checkout/tests/e2e/checkouts.e2e.spec.js#accepts a member
    who holds the store’s purchasing role at the organization
  - >-
    Examined reference: services-commerce:modules/checkout/tests/e2e/checkouts.e2e.spec.js#adds after the
    last, changes the intent and clears what was advised, removes, each bumping the version
  - >-
    Examined reference: services-commerce:modules/checkout/tests/e2e/checkouts.e2e.spec.js#expires seven days
    out, and the first item carries the participant’s current schema version, unvalidated
  - >-
    Examined reference: services-commerce:modules/checkout/tests/e2e/checkouts.e2e.spec.js#leaves an event for
    every change
  - >-
    Examined reference: services-commerce:modules/checkout/tests/e2e/checkouts.e2e.spec.js#lets a console user
    with commerce.orders.create buy for the organization naming any acting contact, and audits the override
  - >-
    Examined reference: services-commerce:modules/checkout/tests/e2e/checkouts.e2e.spec.js#moves an open
    checkout to abandoned, after which it no longer changes (409 checkout_not_open)
  - >-
    Examined reference: services-commerce:modules/checkout/tests/e2e/checkouts.e2e.spec.js#refuses a console
    clerk without commerce.orders.create the same purchase, 400 buyer_may_not_act
  - >-
    Examined reference: services-commerce:modules/checkout/tests/e2e/checkouts.e2e.spec.js#refuses a currency
    the business unit does not support: currency_not_supported
  - >-
    Examined reference: services-commerce:modules/checkout/tests/e2e/checkouts.e2e.spec.js#refuses a member
    affiliated without the role: buyer_may_not_act, NOT_AUTHORIZED_FOR_ORGANIZATION
  - >-
    Examined reference: services-commerce:modules/checkout/tests/e2e/checkouts.e2e.spec.js#refuses a member
    opening a checkout for another contact, 403
  - >-
    Examined reference: services-commerce:modules/checkout/tests/e2e/checkouts.e2e.spec.js#refuses a payload
    that does not parse as the participant’s schema: payload_does_not_parse
  - >-
    Examined reference: services-commerce:modules/checkout/tests/e2e/checkouts.e2e.spec.js#refuses a product
    the tenant does not have: product_not_sellable
  - >-
    Examined reference: services-commerce:modules/checkout/tests/e2e/checkouts.e2e.spec.js#refuses a quantity
    past the product’s purchase limit: quantity_out_of_limits
  - >-
    Examined reference: services-commerce:modules/checkout/tests/e2e/checkouts.e2e.spec.js#refuses a retired
    product and an unsellable product type: product_not_sellable
  - >-
    Examined reference: services-commerce:modules/checkout/tests/e2e/holds-and-claims.e2e.spec.js#acquires the
    hold: 200 with the reservation held, the item prepared with it, the participant’s row held, hold_acquired
    on the trail
  - >-
    Examined reference: services-commerce:modules/checkout/tests/e2e/holds-and-claims.e2e.spec.js#refuses an
    extension past the policy’s ceiling, 409 hold_not_extendable with the participant’s problem
  - >-
    Examined reference: services-commerce:modules/checkout/tests/e2e/holds-and-claims.e2e.spec.js#refuses
    another buyer the booth: 409 hold_unavailable with the participant’s reason, and their preview marks the
    item unavailable
  - >-
    Examined reference: services-commerce:modules/checkout/tests/e2e/holds-and-claims.e2e.spec.js#releases an
    item’s hold through the participant when the item is removed, with holds_released on the trail
  - >-
    Examined reference: services-commerce:modules/checkout/tests/e2e/holds-and-claims.e2e.spec.js#releases
    every hold when the checkout is abandoned
  - >-
    Examined reference:
    services-commerce:modules/checkout/tests/integration/services/checkout/checkout-sweeper.integration.spec.js#abandoned
    each expired open checkout in its own tenant, with the system as the actor and expired as the reason
  - >-
    Examined reference:
    services-commerce:modules/checkout/tests/integration/services/checkout/checkout-sweeper.integration.spec.js#takes
    at most the limit, oldest expiry first, and leaves the rest to the next run; a cancelled checkout is not
    found
  - >-
    Examined reference:
    services-commerce:modules/checkout/tests/unit/checkout/checkout-event-actor.spec.js#names the support
    identity as the actor of the event
---

# Build a buyer’s cart: Acceptance Test Set

## Coverage

| Rule | Scenario or Finding |
|---|---|
| `BR-CAP-COM-ORD-001-01` | `ATS-COM-ORD-001-01` |
| `BR-CAP-COM-ORD-001-02` | `ATS-COM-ORD-001-02` |
| `BR-CAP-COM-ORD-001-03` | `ATS-COM-ORD-001-03` |
| `BR-CAP-COM-ORD-001-04` | `ATS-COM-ORD-001-04` |
| `BR-CAP-COM-ORD-001-05` | `ATS-COM-ORD-001-05` |
| `BR-CAP-COM-ORD-001-06` | `ATS-COM-ORD-001-06` |
| `BR-CAP-COM-ORD-001-07` | `ATS-COM-ORD-001-07` |
| `BR-CAP-COM-ORD-001-08` | `ATS-COM-ORD-001-08` |
| `BR-CAP-COM-ORD-001-09` | `ATS-COM-ORD-001-09` |
| `BR-CAP-COM-ORD-001-10` | no scenario: `FND-COM-ORD-033` |
| `BR-CAP-COM-ORD-001-11` | no scenario: `FND-COM-ORD-033` |
| `BR-CAP-COM-ORD-001-12` | no scenario: `FND-COM-ORD-033` |
| `BR-CAP-COM-ORD-001-13` | no scenario: `FND-COM-ORD-033` |

| `BR-CAP-COM-ORD-001-14` | `ATS-COM-ORD-001-10` |
