---
id: TST-COM-ORD-038
title: 'Promotion codes, the preview breakdown and placement'
kind: api-lifecycle
product_area: commerce
module: orders
revision: 1
status: draft
source_sha:
  services-commerce: c8b66a98e2490617aec38ba5c8165dd9bd0a8f9b
repository: services-commerce
files:
  - modules/checkout/tests/e2e/promotions.e2e.spec.js
implements:
  - ATS-COM-ORD-004-01
  - ATS-COM-ORD-004-02
  - ATS-COM-ORD-004-03
  - ATS-COM-ORD-004-04
  - ATS-COM-ORD-004-05
  - ATS-COM-ORD-004-06
  - ATS-COM-ORD-004-08
  - ATS-COM-ORD-004-09
  - ATS-COM-ORD-004-11
environment: local
implementation_state: implemented
latest_result: not-run
latest_run_at: null
latest_run_ref: null
conformance: not-verified
estimated_minutes: 2
isolation: The suite creates its own test workspace records and removes them using the fixture cleanup.
evidence:
  - provenance: test
    source: 'services-commerce:modules/checkout/tests/e2e/promotions.e2e.spec.js'
    test_cases:
      - 'previews the line with its 2500 discount and 42500 net, and its discount row'
      - previews EARLY25 applied and nothing rejected or replaced
      - >-
        previews the totals: subtotal 45000, discount 2500, total 42500 (tax 0 until the tax adapter of
        P3-WP05)
      - records checkout.promotion_code_applied with the promotion and the discount
      - places the order with a discount of 2500 and the line net 42500 (tax 0 and total 42500 until P3-WP05)
      - records the redemption applied with one allocation of 2500
      - takes one use of the code and of the promotion
      - 'refuses the change of the amount, promotion_locked'
      - leaves the order’s lines and its pricing snapshot as they were
      - leaves the order’s allocations as they were
      - 'refuses the same code entered again, 409 already_applied with the customer’s message'
      - 'records the refusal on the trail as checkout.promotion_code_rejected, already_applied'
      - 'rejects a second code of the same promotion already_applied, the first still applied'
      - 'rejects the code nothing_qualifies, with the customer’s message, and takes nothing off'
      - records checkout.promotion_code_rejected with the reason code and no staff message
      - 'places the order at the full price, the code not applied'
      - 'keeps the code on the order’s pricing snapshot as not applied, with its reason'
      - writes no redemption and leaves the uses unchanged
      - 'previews TENTH as giving nothing, FREEALL taking the whole $100.00'
      - places the order at $0.00 with FREEALL applied
      - 'keeps TENTH on the order as not applied, with its reason'
      - consumes no use of TENTH
      - >-
        applies the one code to each, full-width letters and an ideographic space included (D-REC-12), shown
        by its display code, the entered code kept as typed (trimmed at the boundary)
      - rejects it nothing_qualifies
      - 'tells the console clerk the staff message, which says business unit'
      - 'tells the portal member the customer message alone, which does not say business unit'
      - keeps the staff message out of the price snapshot the portal member reads
      - 'keeps the code once, as first spelled'
      - 'places the order with the one discount, rather than refusing the second spelling as already applied'
      - 're-runs the preview without the code: nothing applied, the full price'
      - records checkout.promotion_code_removed naming the code as it was entered
      - answers the last preview’s breakdown to the checkout read
      - 'refuses removing a code the checkout does not carry, 404'
      - 'refuses a code with a slash and a percent sign, 400, with the sentence'
      - 'refuses a code with ß, 400, still after NFKC (D-REC-12)'
      - 'refuses a code of emoji, 400'
      - leaves the checkout without any code
      - 'refuses a body without a code, 400'
      - 'refuses another member entering a code on a checkout that is not theirs, 403'
scenario_coverage:
  - scenario: ATS-COM-ORD-004-01
    test_cases:
      - >-
        applies the one code to each, full-width letters and an ideographic space included (D-REC-12), shown
        by its display code, the entered code kept as typed (trimmed at the boundary)
    scope: >-
      The cited cases exercise the scenario’s listed fixture outcomes; this register makes no verified
      conformance claim.
  - scenario: ATS-COM-ORD-004-02
    test_cases:
      - 'refuses a code of emoji, 400'
    scope: >-
      The cited cases exercise the scenario’s listed fixture outcomes; this register makes no verified
      conformance claim.
  - scenario: ATS-COM-ORD-004-03
    test_cases:
      - 'refuses the same code entered again, 409 already_applied with the customer’s message'
      - 'records the refusal on the trail as checkout.promotion_code_rejected, already_applied'
      - 'rejects a second code of the same promotion already_applied, the first still applied'
    scope: >-
      The cited cases exercise the scenario’s listed fixture outcomes; this register makes no verified
      conformance claim.
  - scenario: ATS-COM-ORD-004-04
    test_cases:
      - 'rejects the code nothing_qualifies, with the customer’s message, and takes nothing off'
      - 'places the order at the full price, the code not applied'
      - 'keeps the code on the order’s pricing snapshot as not applied, with its reason'
      - writes no redemption and leaves the uses unchanged
    scope: >-
      The cited cases exercise the scenario’s listed fixture outcomes; this register makes no verified
      conformance claim.
  - scenario: ATS-COM-ORD-004-05
    test_cases:
      - 'previews TENTH as giving nothing, FREEALL taking the whole $100.00'
      - 'keeps TENTH on the order as not applied, with its reason'
      - consumes no use of TENTH
    scope: >-
      The cited cases exercise the scenario’s listed fixture outcomes; this register makes no verified
      conformance claim.
  - scenario: ATS-COM-ORD-004-06
    test_cases:
      - records the redemption applied with one allocation of 2500
      - takes one use of the code and of the promotion
    scope: >-
      The cited cases exercise the scenario’s listed fixture outcomes; this register makes no verified
      conformance claim.
  - scenario: ATS-COM-ORD-004-08
    test_cases:
      - 'tells the console clerk the staff message, which says business unit'
      - 'tells the portal member the customer message alone, which does not say business unit'
      - keeps the staff message out of the price snapshot the portal member reads
    scope: >-
      The cited cases exercise the scenario’s listed fixture outcomes; this register makes no verified
      conformance claim.
  - scenario: ATS-COM-ORD-004-09
    test_cases:
      - 're-runs the preview without the code: nothing applied, the full price'
      - records checkout.promotion_code_removed naming the code as it was entered
      - 'refuses removing a code the checkout does not carry, 404'
    scope: >-
      The cited cases exercise the scenario’s listed fixture outcomes; this register makes no verified
      conformance claim.
  - scenario: ATS-COM-ORD-004-11
    test_cases:
      - 'refuses another member entering a code on a checkout that is not theirs, 403'
    scope: >-
      The cited cases exercise the scenario’s listed fixture outcomes; this register makes no verified
      conformance claim.
dependency_evidence:
  provenance: test
  source: 'services-commerce:modules/checkout/tests/e2e/promotions.e2e.spec.js'
  declared_by_test: >-
    the composed handler, the routes, the workflows, the stub participant, the pricing engine, the promotions
    library and persistence, PostgreSQL. Doubled: the signing key pair and the other services' tables (local
    stand-ins).
---

# Promotion codes, the preview breakdown and placement

## Verification Boundary

The suite drives the composed local API dispatcher and its registered routes.

## What This Suite Proves

The registered cases check promotion codes, the preview breakdown and placement with their fixture records and assertions. Scenario bindings name only the examples those cases exercise.

## What It Does Not Prove

A registered file supplies no run result or verified conformance by itself. Local fixtures do not establish deployed cross-service behavior or complete browser journeys.

## Real Dependencies and Test Doubles

PostgreSQL and the exercised Commerce persistence or workflow code are real. Remote service records, clocks and transports follow the suite’s fixtures.

## Must Not Be Doubled

The database constraints, role restrictions, locks and transactions exercised by this suite must use PostgreSQL.
