Files
pedwfrontend/lib/domain/representation-policy/resolveRepresentationWindow.js
T
Robert Bond c39e4bcc9a Merged PR 2375: update representation policy
## Summary

Introduces a new `representation-policy` domain boundary and incrementally extracts low-risk representation entry policy logic while preserving existing behaviour.

This PR intentionally stops before extracting ROW and Advert entry rules because characterization uncovered behavioural differences between consumers that require a separate business decision.

## What Changed

Added:

```text
lib/domain/representation-policy/
```

Including:

- `resolveRepresentationWindow(...)`
- `isRepresentationWindowOpen(...)`
- `isRepresentationWindowClosed(...)`
- `canShowRepresentationButtonForAppealType(...)`
- `canStartHouseholderRepresentation(...)`
- `canStartCpoRepresentation(...)`

Updated consumers:

```text
components/case/summary/utils/representationEntry.js
components/search/repsonresults.js
```

## Extracted Behaviour

### Representation Window Calculation
Centralised shared representation window logic and adopted it in both consumers.

### Appeal Type Entry Gating
Centralised excluded appeal-type logic while preserving existing behaviour.

### Householder Rule
Centralised Householder (`846040004`) entry rule.

Preserved behaviour:

```text
Householder representations can only be started by LPAs.
```

### CPO Rule
Centralised CPO (`846040019`) entry rule.

Preserved behaviour using:

```text
pinswg_startdate
pinswg_statementduedate
```

No fallback date broadening introduced.

## Characterization Added

### ROW (`846040015`)
Documented:
- hearing vs non-hearing behaviour
- specialist-process field behaviour
- date gating
- appeal-type coercion behaviour

### Advert (`846040018`)
Documented:
- LPA/non-LPA behaviour
- specialist-process behaviour
- appeal-type coercion behaviour

## Important Findings

### ROW Divergence
Summary and Search consumers currently behave differently when only:

```text
pinswg_speacialistcaseprocess
```

exists.

### Advert Divergence
Summary and Search consumers currently use different specialist-process resolution paths.

### CRM Compatibility
Both fields remain in production use and must be preserved:

```text
pinswg_specialistcaseprocess
pinswg_speacialistcaseprocess
```

## Documentation

Added:

```text
lib/domain/representation-policy/README.md
```

Documenting:
- ownership
- non-goals
- CRM compatibility requirements
- ROW divergence
- Advert divergence
- future extraction constraints

## Validation

Executed during the slice series:

```bash
node tests/phase22/representation-window.test.cjs
node tests/phase22/representation-appeal-type-entry-gating.test.cjs
node tests/phase22/representation-householder-entry-rule.test.cjs
node tests/phase22/representation-cpo-entry-rule.test.cjs
node tests/phase22/representation-row-entry-rule.test.cjs
node tests/phase22/representation-advert-entry-rule.test.cjs
npm run lint
```

All passing.

## Out of Scope

No changes to:

- submission/finalisation
- uploads
- dashboards
- CRM/OData queries
- API routes
- Redux state
- translations
- blocked-message rendering
- CTA l...
2026-06-08 10:51:02 +00:00

58 lines
1.6 KiB
JavaScript

const startOfToday = (DateCtor = Date) =>
new DateCtor(new DateCtor().toDateString());
const toDate = (value, DateCtor = Date) => new DateCtor(value);
export function isRepresentationWindowOpen(
startDate,
endDate,
DateCtor = Date
) {
const date = startOfToday(DateCtor);
const start = toDate(startDate, DateCtor);
const end = toDate(endDate, DateCtor);
return date >= start && date <= end ? true : false;
}
export function isRepresentationWindowClosed(
startDate,
endDate,
DateCtor = Date
) {
const date = startOfToday(DateCtor);
const start = toDate(startDate, DateCtor);
const end = toDate(endDate, DateCtor);
return date > start && date > end ? true : false;
}
export function resolveRepresentationWindow(caseDetails, DateCtor = Date) {
const hasStartDate =
Object.prototype.hasOwnProperty.call(caseDetails, "pinswg_startdate") ||
Object.prototype.hasOwnProperty.call(
caseDetails,
"pinswg_applicationacceptedasvalid"
) ||
Object.prototype.hasOwnProperty.call(caseDetails, "pinswg_startdates");
const startDate =
caseDetails.pinswg_startdate ||
caseDetails.pinswg_startdates ||
caseDetails.pinswg_applicationacceptedasvalid;
const endDate =
caseDetails.pinswg_finalcommentsduedate ||
caseDetails.pinswg_endofrepresentationperiod;
return {
hasStartDate,
startDate,
endDate,
isOpen:
hasStartDate &&
isRepresentationWindowOpen(startDate, endDate, DateCtor),
isClosed: isRepresentationWindowClosed(startDate, endDate, DateCtor)
};
}