---
id: CAP-ACC-PRD-005
title: Withdraw a product from sale and restore it
feature: FEAT-ACC-PRD-01
product_area: accounting
module: products
revision: 3
status: draft
product_intent: proposed
implementation_evidence: observed
supersedes:
  - react-console acceptance inventory CAP-ACC-PRD-005
  - react-console acceptance inventory RUL-ACC-PRD-006
  - react-console acceptance inventory RUL-ACC-PRD-023
source_sha:
  services-accounting: f47cb263875bbc0c5640fba7dae6785ec32695f8
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
intent_sources:
  - 'services-accounting:docs/milestones/ACCT-M1-books-and-invoices.md#D4'
  - 'services-accounting:docs/milestones/ACCT-M1-books-and-invoices.md#D11'
purpose: Finance uses the row menu to withdraw or restore a product.
outcomes:
  - Finance can preserve withdrawn products and restore their use.
concepts:
  - CON-ACC-PRD-001
actors:
  - ACT-ACC-006
  - ACT-ACC-010
surfaces:
  - console
  - api
permissions:
  - key: accounting.products.update
    where_checked: api
    scope: tenant
rules:
  - id: BR-CAP-ACC-PRD-005-01
    proved_by: [ATS-ACC-PRD-005-01, TST-ACC-PRD-003]
    statement: >-
      Ordinary replacement changes active products to inactive and back; inactive products leave sale while
      existing invoices remain valid.
    kind: lifecycle
    enforced_at:
      - api
      - service
    must_prove: true
    provenance: test
    source: 'react-console:acceptance/accounting/playwright/journeys/products/ACT-ACC-0107.spec.ts#ACT-ACC-0107'
    origin: 'services-accounting:docs/milestones/ACCT-M1-books-and-invoices.md#D4'
  - id: BR-CAP-ACC-PRD-005-02
    proved_by: [ATS-ACC-PRD-005-02, ATS-ACC-PRD-005-07, ATS-ACC-PRD-005-09, ATS-ACC-PRD-007-10, ATS-ACC-PRD-011-09, TST-ACC-PRD-030, TST-ACC-PRD-040]
    statement: 'Retirement advances the read version and changes only status, rejecting an already retired product.'
    kind: lifecycle
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#retires
      the product at version 2, changing nothing else
    origin: 'services-accounting:docs/milestones/ACCT-M1-books-and-invoices.md#D4'
  - id: BR-CAP-ACC-PRD-005-03
    proved_by: [ATS-ACC-PRD-004-11, ATS-ACC-PRD-005-03, ATS-ACC-PRD-005-07, ATS-ACC-PRD-006-11, TST-ACC-PRD-040]
    statement: Reactivation makes inactive or retired products active and rejects products already active.
    kind: lifecycle
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#reactivates
      an inactive product
    origin: 'services-accounting:docs/milestones/ACCT-M1-books-and-invoices.md#D4'
  - id: BR-CAP-ACC-PRD-005-04
    proved_by: [ATS-ACC-PRD-005-04, TST-ACC-PRD-030, TST-ACC-PRD-040]
    statement: Retirement and reactivation reject requests missing the read version or carrying an obsolete version.
    kind: validation
    enforced_at:
      - api
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/products/tests/e2e/products.e2e.spec.js#answers 400 to a lifecycle request
      without the version read
    origin: none
  - id: BR-CAP-ACC-PRD-005-05
    proved_by: [ATS-ACC-PRD-005-05, ATS-ACC-PRD-005-07, TST-ACC-PRD-040, TST-ACC-PRD-066]
    statement: An update lock prevents both retirement and reactivation.
    kind: permission
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#names
      the lock when a locked product is retired
    origin: 'services-accounting:docs/milestones/ACCT-M1-books-and-invoices.md#D11'
  - id: BR-CAP-ACC-PRD-005-06
    proved_by: [ATS-ACC-PRD-005-06, ATS-ACC-PRD-005-08, TST-ACC-PRD-028]
    statement: Both lifecycle actions require product update permission.
    kind: permission
    enforced_at:
      - api
    must_prove: true
    provenance: test
    source: >-
      services-accounting:modules/products/tests/e2e/products-security.e2e.spec.js#is refused retiring a
      product
    origin: 'services-accounting:docs/milestones/ACCT-M1-books-and-invoices.md#D3'
  - id: BR-CAP-ACC-PRD-005-07
    proved_by: []
    statement: >-
      Recorded product intent excludes retired products from new invoice selection while preserving existing
      invoices.
    kind: policy
    enforced_at: []
    must_prove: false
    provenance: documented
    source: 'services-accounting:docs/milestones/plans/ACCT-M1-plan.md#D4'
    origin: 'services-accounting:docs/milestones/ACCT-M1-books-and-invoices.md#D4'
  - id: BR-CAP-ACC-PRD-005-08
    proved_by: []
    statement: >-
      Row actions ask for confirmation before activation, deactivation, retirement and reactivation; retired
      names do not open the editor.
    kind: policy
    enforced_at:
      - console
    must_prove: false
    provenance: observed
    source: 'react-console:components/accounting-config/products/product-row-actions.tsx:ProductRowActions'
    origin: none
scenarios:
  - id: SC-CAP-ACC-PRD-005-01
    given: A currently active workshop product is in the catalogue.
    when: 'Finance retires it, attempts correction and reactivates it.'
    then: Correction fails during retirement and succeeds after restoration to active.
    provenance: test
    source: 'react-console:acceptance/accounting/playwright/journeys/products/ACT-ACC-0107.spec.ts#ACT-ACC-0107'
edge_cases:
  - id: SC-CAP-ACC-PRD-005-02
    given: An inactive product remains in the catalogue.
    when: Finance requests reactivation.
    then: Its status becomes active directly.
    provenance: test
    source: >-
      services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#reactivates
      an inactive product
constraints: []
depends_on:
  - CAP-ACC-PRD-002
related:
  - CAP-ACC-PRD-004
  - CAP-ACC-PRD-006
  - CAP-ACC-PRD-011
journeys:
  - JNY-ACC-PRD-002
open_questions: []
evidence:
  - 'react-console:acceptance/accounting/playwright/journeys/products/ACT-ACC-0107.spec.ts'
  - 'react-console:components/accounting-config/products/product-row-actions.tsx'
  - 'react-console:components/accounting-config/products/use-products.ts'
  - 'services-accounting:docs/milestones/ACCT-M1-books-and-invoices.md'
  - 'services-accounting:docs/milestones/plans/ACCT-M1-plan.md'
  - 'services-accounting:modules/products/aws/api/products.routes.ts'
  - 'services-accounting:modules/products/services/persistence/products.ts'
  - 'services-accounting:modules/products/services/rules/product-rules.ts'
  - 'services-accounting:modules/products/tests/e2e/products-security.e2e.spec.js'
  - 'services-accounting:modules/products/tests/e2e/products.e2e.spec.js'
  - 'services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js'
controls: [TC-IAM-001, TC-IAM-002, TC-IAM-004, TC-IAM-005, 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-DAT-001, TC-LOG-001, TC-LOG-002, TC-LOG-003, TC-LOG-004, TC-LOG-005, TC-PI-001, TC-PI-003, TC-PI-005]
exercised_by: [FAS-ACC-PRD-01-03, FAS-ACC-PRD-01-04, FAS-ACC-PRD-03-05]
suites: [TST-ACC-PRD-003, TST-ACC-PRD-028, TST-ACC-PRD-030, TST-ACC-PRD-040, TST-ACC-PRD-066]
---

# Withdraw a product from sale and restore it

## Purpose

Finance uses the row menu to withdraw or restore a product.

## How It Works

Finance uses the row menu to withdraw or restore a product. Deactivation keeps the record available for correction while removing it from ordinary sale. Retirement preserves the record but prevents replacement. Reactivation returns either withdrawn state to active. Each lifecycle action checks the version read and product update authority. An update lock stops the action. The console confirms the choice before submitting it. Existing-invoice preservation is recorded product intent and needs the transaction module’s proof as well as catalogue state checks.

## Relationships

This outcome uses create a product with a permanent identity.
