Files
pedwfrontend/lib/domain/case-lifecycle
Robert Bond 9595ad86df Merged PR 2374: addeding domain layer extrraction
# Summary

This PR introduces a **Case Lifecycle Domain Boundary** to centralize lifecycle decision logic and reduce coupling within the appeals application.

The work is **behaviour-preserving** and introduces no intentional changes to business rules, CRM integrations, translations, dashboards, API routes, or user-facing functionality.

## What was added

New lifecycle boundary:

```text
lib/domain/case-lifecycle/
```

Key responsibilities extracted:

- Specialist process normalization
- Appeal type mapping
- Specialist process stage override mapping
- Stage case-type resolution
- Stage catalogue lookup
- Closed-case status recognition
- Lifecycle stage index resolution
- Lifecycle stage status assignment

## Behaviour preserved

Characterization tests were added before each extraction to preserve:

- Appeal type mapping and aliases
- Specialist process handling
- Lifecycle stage progression
- Closed-case handling
- Status assignment (`complete`, `in-progress`, `not-started`)
- Existing ROW behaviour
- Existing `statuscode` lifecycle semantics

Closed-case recognition remains unchanged for:

```text
1000
5
6
846040013
846040059
846040060
```

## Documentation

Added:

```text
lib/domain/case-lifecycle/README.md
```

Documenting:

- Boundary ownership
- Non-goals
- Lifecycle invariants
- Known architectural constraints
- Future extraction roadmap

## Testing

Added lifecycle characterization coverage for:

- Stage wrapper behaviour
- Specialist process normalization
- Appeal type mapping
- Specialist process stage mapping
- Stage case-type resolution
- Stage catalogue lookup
- Progress behaviour
- Closed-case status handling
- Stage index resolution
- Stage status assignment

## Validation

- Lifecycle characterization tests passed
- `npm run lint` passed with no errors

## Out of Scope

No changes to:

- Stage catalogue ownership
- Representation eligibility
- Dashboard calculations
- CRM/OData queries
- API routes
- Redux state
- EN/CY translations
- Event visibility logic

## Risk

**Low risk**

The refactor was delivered through small, characterization-first slices with no functional changes intended.

Related work items: #23527
2026-06-08 09:34:30 +00:00
..

Case Lifecycle Domain Boundary

Purpose

This directory contains a narrow case lifecycle decision boundary, not a full domain model.

Its current purpose is to centralise behaviour-preserving interpretation logic that was previously embedded in UI-adjacent helpers, while keeping live behaviour unchanged during refactor.

This boundary should be treated as an incremental extraction seam for read-only lifecycle interpretation, not as a place to redesign lifecycle behaviour.

Current ownership

getLifecycleStagesForCase(...)

  • thin wrapper around the existing stage/progress helper
  • preserves existing output shape for current consumers
  • does not define new lifecycle semantics

normalizeSpecialistProcess(...)

  • raw CRM field fallback only
  • preserves current canonical and misspelled field fallback behaviour
  • does not validate or reinterpret CRM values

mapAppealType(...)

  • current appeal-type-to-case-type mapping
  • current alias handling
  • current unknown input behaviour

mapSpecialistProcessStageType(...)

  • specialist-process stage override mapping
  • preserves current placeholder-like CRM specialist process values
  • preserves current override target keys and fallback behaviour

getStageCaseTypeKey(...)

  • current stage case-type resolution decision
  • combines:
    • appeal type mapping
    • specialist-process stage override mapping
    • alias normalization
    • current fallback behaviour

getStagesForCaseTypeKey(...)

  • current stage catalogue lookup only
  • preserves:
    • direct key lookup
    • string indirection resolution
    • fallback to []
  • does not own stage catalogue contents

Stage catalogue ownership and lookup

Stage catalogue arrays still live in:

  • components/case/summary/utils/caseStagesByAppealType.js

The domain boundary currently owns lookup behaviour only:

  • direct key lookup
  • string indirection resolution
  • fallback to []

getStagesForCaseTypeKey(...) must not be treated as stage catalogue ownership yet.

Lazy access in getStagesForCaseTypeKey(...) is intentional:

  • it avoids circular dependency issues while stage arrays remain in the legacy helper
  • the domain helper must not eagerly import catalogue contents while ownership remains outside the domain boundary

Any future catalogue migration must be a separate, explicitly scoped slice.

Until catalogue ownership moves:

  • stage array contents remain the source of truth in the legacy helper
  • the domain lookup helper must preserve reference identity
  • the domain lookup helper must preserve current fallback behaviour

Explicit non-goals

This boundary does not currently own:

  • stage catalogue arrays
  • progress/status calculation
  • closed-case handling
  • representation eligibility
  • dashboard layout or calculations
  • translations / EN-CY labels
  • CRM/OData query construction
  • API routes
  • Redux state shape
  • upload, submit, finalisation, or notification logic

Behaviour-preservation invariants

Future slices must preserve:

  • current stage IDs
  • translation keys
  • alias behaviour
  • unknown input behaviour
  • current fallback semantics
  • current specialist-process override semantics
  • status-vs-stage ambiguity
  • current closed-case behaviour

Known oddities to preserve

  1. statuscode is currently passed into stage/progress logic.

    • Do not rename or reinterpret this without a separate behaviour-change decision.
  2. Specialist-process overrides are intentionally narrow.

    • They currently apply only through the existing appeal-type-based resolution path.
    • Do not broaden this behaviour during refactor.
  3. Some specialist process values appear placeholder-like.

    • Do not “correct” them without CRM/product confirmation.
  4. Some ROW inputs currently produce non-intuitive stage output.

    • Preserve characterized behaviour unless explicitly changing business rules.
  5. The test harnesses are VM-based and import-sensitive.

    • Future extractions must update harness injections carefully and avoid broad rewrites.

Testing expectations

Future slices should run:

node tests/phase22/case-lifecycle-stage-case-type-resolution.test.cjs
node tests/phase22/case-lifecycle-specialist-process-stage-mapping.test.cjs
node tests/phase22/case-lifecycle-appeal-type-mapping.test.cjs
node tests/phase22/case-lifecycle-specialist-process-normalization.test.cjs
node tests/phase22/case-lifecycle-stage-wrapper.test.cjs
node tests/phase22/representation-build-reps-arr-rules.test.cjs
npm run lint

Future extraction order

Recommended future order:

  1. stage catalogue lookup helper
  2. stage catalogue ownership only after enough characterization coverage
  3. progress/status calculation extraction
  4. additional read-only consumers
  5. representation eligibility only as a separate policy slice after characterization