---
id: CAP-COM-CAT-014
title: Prepare and control a promotion’s lifecycle
feature: FEAT-COM-CAT-04
product_area: commerce
module: catalog
revision: 1
status: draft
product_intent: proposed
implementation_evidence: observed
source_sha:
  services-commerce: c8b66a98e2490617aec38ba5c8165dd9bd0a8f9b
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
intent_sources:
  - 'services-commerce:docs/milestones/plans/COMM-M1-plan.md#2. Scope (item 6)'
  - 'services-commerce:docs/milestones/COMM-M1-set-up-what-you-sell.md#D12'
  - >-
    services-commerce:docs/milestones/COMM-M1b-promotions-and-codes.md#Decisions
    (D-R1, D-R2, R6)
  - >-
    services-commerce:docs/milestones/plans/COMM-M1b-engine.md#1. Routes and
    shapes (for the console job)
purpose: Staff configure marketing offers and administrators authorize their launch.
outcomes:
  - An offer is fully described prior to it can go live.
  - 'Once used, an offer’s money terms does not permit silently change.'
  - Campaign preparation and activation require distinct authority.
concepts:
  - CON-COM-CAT-005
actors:
  - ACT-COM-001
  - ACT-COM-002
  - ACT-COM-004
  - ACT-COM-007
surfaces:
  - console
  - api
permissions:
  - key: commerce.promotions.read
    where_checked: api
    scope: tenant
  - key: commerce.promotions.manage
    where_checked: api
    scope: tenant
  - key: commerce.promotions.activate
    where_checked: api
    scope: tenant
rules:
  - id: BR-CAP-COM-CAT-014-01
    statement: >-
      Promotions are automatic or code-claimed; automatic promotions cannot hold
      codes and a coded draft cannot change to automatic.
    kind: policy
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-commerce:modules/promotions/tests/e2e/promotions.e2e.spec.js#refuses
      to make a draft with a code automatic, 409
      automatic_promotion_has_no_codes
    origin: COMM-M1 plan A16 (docs/milestones/plans/COMM-M1-plan.md)
  - id: BR-CAP-COM-CAT-014-02
    statement: >-
      An offer uses one to twenty selling-area parts or one order-level amount
      or shipping benefit, never both, and percentage or per-unit benefits
      require parts.
    kind: validation
    enforced_at:
      - api
      - service
    must_prove: true
    provenance: test
    source: >-
      services-commerce:modules/promotions/tests/e2e/promotions.e2e.spec.js#refuses
      parts together with an order-total offer, 400 promotion_invalid in plain
      words
    origin: COMM-M1b D-R1 (docs/milestones/COMM-M1b-promotions-and-codes.md)
  - id: BR-CAP-COM-CAT-014-03
    statement: >-
      Selling applications validate their parts’ areas and criteria, with
      percentages limited to one hundred percent and positive fixed amounts
      requiring currency.
    kind: validation
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-commerce:modules/promotions/tests/e2e/promotions.e2e.spec.js#refuses
      a product that is not merchandise, 400 promotion_invalid naming the part
      and the product
    origin: COMM-M1b D-R1 (docs/milestones/COMM-M1b-promotions-and-codes.md)
  - id: BR-CAP-COM-CAT-014-04
    statement: >-
      A stated discount cap is at least one minor unit and limits all parts
      together; minimum purchase uses qualifying lines and validation reports
      all discovered promotion problems together.
    kind: validation
    enforced_at:
      - api
      - service
      - database
    must_prove: true
    provenance: test
    source: >-
      services-commerce:modules/promotions/tests/e2e/promotions.e2e.spec.js#names
      every problem of a sloppy promotion in one 400 promotion_invalid, the zero
      cap among them (Q07, journey 0203)
    origin: COMM-M1 plan A19 (Q07) (docs/milestones/plans/COMM-M1-plan.md)
  - id: BR-CAP-COM-CAT-014-05
    statement: >-
      Code eligibility belongs to individual codes, promotion eligibility is
      limited to automatic promotions, and legacy scope values are accepted
      without effect.
    kind: validation
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-commerce:modules/promotions/tests/e2e/promotions.e2e.spec.js#refuses
      a promotion-level eligibility rule on a code-claimed promotion, 400 in the
      code’s words
    origin: COMM-M1b D-R2 (docs/milestones/COMM-M1b-promotions-and-codes.md)
  - id: BR-CAP-COM-CAT-014-06
    statement: >-
      Audience-price combination is enabled by default and remains changeable
      after redemption.
    kind: policy
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-commerce:modules/promotions/tests/e2e/promotions.e2e.spec.js#defaults
      "combine with audience prices" to yes when the body leaves it out (D12)
    origin: 'COMM-M1 D12, D12-F2 (docs/milestones/COMM-M1-set-up-what-you-sell.md)'
  - id: BR-CAP-COM-CAT-014-07
    statement: >-
      New promotions default to exclusive stacking, automatic priority one
      hundred and the internal name as their customer-facing name.
    kind: policy
    enforced_at:
      - service
      - console
    must_prove: false
    provenance: test
    source: >-
      services-commerce:modules/promotions/tests/e2e/promotions.e2e.spec.js#defaults
      public_name to the name
    origin: >-
      COMM-M1 plan A15, A16 (promotions D-02, Q03); COMM-M1b R6
      (docs/milestones/plans/COMM-M1-plan.md)
  - id: BR-CAP-COM-CAT-014-08
    statement: >-
      Promotion names are unique ignoring case, and each promotion receives a
      displayed promotion number.
    kind: validation
    enforced_at:
      - service
      - database
    must_prove: false
    provenance: test
    source: >-
      services-commerce:modules/promotions/tests/e2e/promotions.e2e.spec.js#refuses
      a name another promotion of the tenant has, whatever its case, 409
      promotion_name_taken
    origin: none
  - id: BR-CAP-COM-CAT-014-09
    statement: >-
      Permitted lifecycle moves are draft to active, active to paused and back,
      active or paused to ended, and draft or ended to archived; refused moves
      identify both states and successful moves retain reasons in history.
    kind: lifecycle
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-commerce:modules/promotions/tests/e2e/promotions.e2e.spec.js#refuses
      every operation from a state it does not move, 409 invalid_transition
    origin: COMM-M1 plan scope item 6 (docs/milestones/plans/COMM-M1-plan.md)
  - id: BR-CAP-COM-CAT-014-10
    statement: >-
      Activation requires an offer, currency for monetary benefits, a rule for
      selected eligibility and an active code for code-claimed promotions.
    kind: lifecycle
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-commerce:modules/promotions/tests/e2e/promotions.e2e.spec.js#refuses
      to activate a coded promotion with no active code, 409 no_active_code
    origin: none
  - id: BR-CAP-COM-CAT-014-11
    statement: >-
      Activation and resumption require launch permission separately from
      management permission for preparation, pausing, ending, archiving and
      duplication.
    kind: permission
    enforced_at:
      - api
      - console
    must_prove: true
    provenance: test
    source: >-
      services-commerce:modules/promotions/tests/e2e/promotions-security.e2e.spec.js#cannot
      activate a draft, 403 permission_missing
    origin: COMM-M1 plan A15 (promotions D-06) (docs/milestones/plans/COMM-M1-plan.md)
  - id: BR-CAP-COM-CAT-014-12
    statement: >-
      First redemption locks the promotion’s economic configuration, identifying
      changed locked fields and directing staff to end and duplicate it; names,
      dates and limits remain editable.
    kind: lifecycle
    enforced_at:
      - service
      - database
    must_prove: true
    provenance: test
    source: >-
      services-commerce:modules/promotions/tests/e2e/promotion-redemptions.e2e.spec.js#names
      the column and offers to end the promotion and duplicate it
    origin: none
  - id: BR-CAP-COM-CAT-014-13
    statement: >-
      Duplication creates a newly named and numbered draft with copied
      configuration, no codes or uses, and history identifying its source.
    kind: lifecycle
    enforced_at:
      - service
    must_prove: false
    provenance: test
    source: >-
      services-commerce:modules/promotions/tests/e2e/promotions.e2e.spec.js#copies
      no code and no use
    origin: none
  - id: BR-CAP-COM-CAT-014-14
    statement: >-
      Promotions remain retained through ending or archiving rather than
      deletion.
    kind: lifecycle
    enforced_at:
      - api
    must_prove: false
    provenance: observed
    source: 'react-console:lib/authz/backend-aliases.ts:COMMERCE_KEYS_WITHOUT_BACKEND'
    origin: none
scenarios:
  - id: SC-CAP-COM-CAT-014-01
    given: The coordinator holds management permission without launch authority
    when: Create a draft and request activation
    then: Preparation succeeds and activation fails permission evaluation
    provenance: test
    source: >-
      services-commerce:modules/promotions/tests/e2e/promotions-security.e2e.spec.js#cannot
      activate a draft, 403 permission_missing
  - id: SC-CAP-COM-CAT-014-02
    given: A promotion already has redemptions
    when: Change its benefit and then extend its dates
    then: The locked economic change fails while the date change saves
    provenance: test
    source: >-
      services-commerce:modules/promotions/tests/e2e/promotion-redemptions.e2e.spec.js#refuses
      the new benefit value, 409 promotion_locked
  - id: SC-CAP-COM-CAT-014-03
    given: A promotion has percentage Books and per-unit Apparel parts
    when: Read back the promotion
    then: >-
      Parts retain position order and the first part is mirrored in the
      promotion-level benefit fields
    provenance: test
    source: >-
      services-commerce:modules/promotions/tests/e2e/promotions.e2e.spec.js#repeats
      part 1 in the promotion’s own benefit
depends_on:
  - CAP-COM-CAT-005
related:
  - CAP-COM-CAT-015
  - CAP-COM-CAT-016
  - CAP-COM-CAT-017
journeys:
  - JNY-COM-CAT-004
evidence:
  - >-
    Pinned service inputs: modules/promotions/aws/api/promotions.routes.ts,
    promotion-areas.routes.ts, promotions.schemas.ts; services/promotions/**,
    services/areas/**, services/persistence/promotions.ts, promotion-parts.ts;
    db/promotions.table.ts, promotion-parts.table.ts, promotion-events.table.ts;
    tests (promotions e2e, security, persistence, table, parts, shape, areas)
  - >-
    Pinned console inputs: components/commerce/promotions/** (list, create,
    view, editor, parts editor, lifecycle actions), lib/commerce/promotions/**
    and tests, components/commerce/__tests__/permission-gating.test.tsx,
    e2e/mock/promotions.mock.spec.ts
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-DAT-001, TC-DAT-002, TC-DAT-003, TC-DAT-004, TC-LOG-004, TC-LOG-005, TC-PI-001, TC-PI-002, TC-PI-003, TC-PI-005, TC-PRV-001, TC-PRV-002]
---

# Prepare and control a promotion’s lifecycle

## Purpose

Staff configure marketing offers and administrators authorize their launch.

## How It Works

A coordinator creates a draft and chooses its claim mode and benefits. Parts refer to selling areas whose providers validate their criteria. The editor collects usage, dates, combination and eligibility choices for review. Activation has a separate permission and checks whether the offer is operationally complete. Subsequent lifecycle actions retain reasons in history. Redemption locks economic terms while allowing supported maintenance. Staff can end and duplicate an offer when its substance needs to change. The product should complete the revised milestone’s verification before approving these contracts.

## Relationships

The organize product shelves capability supplies related configuration or assessment used in this work.

The issue promotion codes with controlled access capability supplies related configuration or assessment used in this work.

The choose the best permitted promotional result capability supplies related configuration or assessment used in this work.

The retain and review promotion usage capability supplies related configuration or assessment used in this work.
