diff --git a/context/current-platform-state.md b/context/current-platform-state.md index f9223de4..29138fbd 100644 --- a/context/current-platform-state.md +++ b/context/current-platform-state.md @@ -17,6 +17,8 @@ PEDW is in a **late-stage refactor stabilization** phase. - Broad endpoint contract hardening completed across key clusters. - Representation Participation Availability investigation completed from a technical discovery/documentation perspective. - Representation participation behaviour is now documented as one coherent decision model with layered appeal-type, specialist-process, participant-type, consultation, and date-window exceptions. +- CRM Case Progress Display investigation completed from a technical discovery/documentation perspective. +- Case Status tab behaviour is now understood as a portal-owned journey interpretation layer driven by CRM `statuscode`, appeal type, and Rights of Way specialist-process routing. - Source documents added: - `docs/representation-participation-availability.md` (developers / architects / maintainers) - `docs/representation-participation-business-review.md` (business / product / SME validation) @@ -51,8 +53,28 @@ Top active risks: - Known divergences and compatibility-sensitive behaviours are documented and should be preserved unless an explicit business decision authorizes change. - Current state: awaiting business validation of `docs/representation-participation-business-review.md` before any further representation-policy adoption, expansion, or behavioural change work. -## Next likely discovery candidate +## CRM Case Progress Display — Current State -- **Case Lifecycle / Status Decision Model Discovery** - - Investigate how the portal interprets case progress, stages, statuses, closed states, dashboard grouping, and user-facing lifecycle messaging. - - Treat this as discovery only until the new representation participation documentation has been reviewed and business validation feedback is available. +- Technical investigation stream is complete. +- Current architectural conclusion: do **not** treat this area as a new business-policy domain boundary. +- The Case Status tab is best understood as a **portal-owned journey interpretation layer**: + - inputs: CRM `statuscode`, appeal type, specialist process (Rights of Way only) + - resolution model: journey catalogue selection -> user-facing journey representation +- `pinswg_casestage` is not a significant active input to the current status-tab model: + - it was historically associated with DNS/SIPS summary support + - it is not part of active lifecycle resolution for the status tab +- Stage catalogues are best understood as: + - user-facing journey models + - appeal-type interpretation models + - presentation-layer progress visualisation +- Shared catalogue families exist (`PLANNING_S78`, `ENFORCEMENT`, `DNS/SIP`, Rights of Way specialist-process variants) and represent a mixture of: + - genuine shared journey structures + - presentation reuse + - historical consolidation + +## Discovery candidate update + +- Case Lifecycle / Status Decision Model Discovery is no longer an open next-candidate investigation. +- Current conclusion from the completed CRM Case Progress Display stream: + - this area is primarily presentation architecture + journey interpretation + - further work should only be reopened if a new business-validation or behavioural-change question emerges diff --git a/memory-bank/change-log.md b/memory-bank/change-log.md index e6072dbf..40275d09 100644 --- a/memory-bank/change-log.md +++ b/memory-bank/change-log.md @@ -18,6 +18,44 @@ Follow-ups: --- +### CL-2026-06-18-CRM-CASE-PROGRESS-CONTEXT: record CRM Case Progress Display investigation conclusions + +date: 2026-06-18 +author: Cline +scope: `context/current-platform-state.md`, `memory-bank/{techContext,productContext,change-log}.md` +type: change +rationale: Preserve the completed CRM Case Progress Display investigation conclusions in project context so future contributors do not re-open the same status/lifecycle ambiguity without need. +impact: Documentation/context only; improves architectural clarity around case status display ownership and inputs; no runtime, auth, i18n, API, or behaviour change. +status: completed + +Summary: + +- Updated project context to record that the Case Status tab is a portal-owned journey interpretation layer. +- Recorded the active input model as: + - CRM `statuscode` + - appeal type + - specialist process (Rights of Way only) +- Recorded that `pinswg_casestage` is not a significant active input to current status-tab lifecycle resolution. +- Recorded that stage catalogues are best understood as: + - user-facing journey models + - appeal-type interpretation models + - presentation-layer progress visualization +- Recorded that shared catalogue families (`PLANNING_S78`, `ENFORCEMENT`, `DNS/SIP`, Rights of Way specialist-process variants) reflect a mixture of shared journey structures, presentation reuse, and historical consolidation. +- Recorded the architectural conclusion that this area is presentation architecture / journey interpretation, not a new business-policy domain boundary candidate. + +Validation: + +- Documentation/context update only. +- No application code changed. +- No tests changed. +- Lint/tests skipped because this was documentation-only work. + +Follow-ups: + +- Reopen only if a future business-validation or behaviour-change initiative requires deeper lifecycle/status decision work. + +--- + ### CL-2026-06-18-RPA-DOCS: representation participation availability documentation + context update date: 2026-06-18 diff --git a/memory-bank/productContext.md b/memory-bank/productContext.md index 1919c65b..88836721 100644 --- a/memory-bank/productContext.md +++ b/memory-bank/productContext.md @@ -26,6 +26,7 @@ ## Business logic patterns visible in code - Case summary UI varies by appeal type and case attributes. +- Case status/progress display is portal-shaped rather than a raw CRM passthrough: the portal selects a journey catalogue from CRM `statuscode`, appeal type, and limited Rights of Way specialist-process input to present user-facing progress. - Representation actions are conditionally shown by appeal type, role, and date windows. - Representation participation now appears to form one broader business decision model: whether a participant can engage in representation or consultation activity for a case at that point in the process. - Locale-sensitive behavior affects links, routes, labels, and email template choice. @@ -40,11 +41,24 @@ - `docs/representation-participation-availability.md` - `docs/representation-participation-business-review.md` +## Current case progress display state + +- Technical investigation for CRM Case Progress Display is complete. +- Current behaviour is best understood as a **user-facing journey representation**, not a business-policy decision model. +- The Case Status tab is driven by: + - CRM `statuscode` + - appeal type + - specialist process for Rights of Way variants only +- `pinswg_casestage` should not currently be treated as a significant input to status-tab lifecycle behaviour. +- Shared catalogue families exist and reflect a mixture of: + - genuine shared journey structures + - presentation reuse + - historical consolidation + ## Likely next discovery candidate -- Case Lifecycle / Status Decision Model Discovery - - expected focus: case progress, stages, statuses, closed states, dashboard grouping, and lifecycle messaging - - should be treated as discovery-only pending review of the new representation participation documentation +- No immediate successor discovery candidate is implied by the completed CRM Case Progress Display stream. +- If reopened later, work should focus on business validation or future behavioural change questions rather than first-pass technical characterization. ## Important user-facing behaviors diff --git a/memory-bank/techContext.md b/memory-bank/techContext.md index 359dd29d..30d0c955 100644 --- a/memory-bank/techContext.md +++ b/memory-bank/techContext.md @@ -54,6 +54,15 @@ - representation participation is best understood as one coherent decision model with layered exceptions - known consumer divergences and CRM compatibility behaviours are part of the current live contract - future technical adoption/expansion work should wait for business validation before changing behaviour or broadening policy boundaries +- CRM Case Progress Display investigation has now been concluded as a technical characterization stream. +- Current technical conclusion: + - the Case Status tab is a portal-owned journey interpretation layer + - active inputs are CRM `statuscode`, appeal type, and Rights of Way specialist-process routing only + - `pinswg_casestage` is not a significant active input to status-tab lifecycle resolution + - stage catalogues are not raw CRM lifecycle states and not business-policy decision models + - stage catalogues are best understood as user-facing journey models plus appeal-type interpretation plus presentation-layer progress visualization + - shared catalogue families (`PLANNING_S78`, `ENFORCEMENT`, `DNS/SIP`, Rights of Way specialist-process variants) reflect a mixture of shared journey semantics, presentation reuse, and historical consolidation + - this area is not currently a candidate for a new business-policy domain boundary ## CI/CD and deployment artifacts diff --git a/reports/case-status-tab-stage-display-characterization.md b/reports/case-status-tab-stage-display-characterization.md new file mode 100644 index 00000000..cdd06140 --- /dev/null +++ b/reports/case-status-tab-stage-display-characterization.md @@ -0,0 +1,564 @@ +## Case Status Tab Stage Display Characterization + +### 1. Purpose + +This report characterizes how the portal determines and renders the visual case progress journey shown on the **Case Status** tab. + +Scope is limited to the case status tab and directly related stage-display behaviour. + +This is discovery/documentation only. It does not propose implementation changes, refactoring, field normalization, or new domain policy. + +--- + +### 2. Business context + +- `statuscode` is the standard CRM/Dataverse Incident status field. +- `pinswg_casestage` is a PEDW custom field used to represent more detailed PEDW case-stage information than the standard CRM status model alone provides. +- The portal presents visual case progression to users through the **Case Status** tab. +- The same broader area also exposes status/stage information elsewhere, including summary/details and search-result consumers. +- Current repository evidence shows these consumers do **not** all use the same source field or the same interpretation model. + +--- + +### 3. Status tab rendering flow + +#### 3.1 CRM inputs fetched on case page load + +The public case page loader in `pages/case/[ticketnumber].js` fetches: + +1. `searchResultsObj` via `getBasicSearch(...)` +2. `searchDetailsObj` via `getSearchDetails(searchResultsObj)` + +Relevant CRM-derived inputs then get stored into `currentView.caseReference` using `setCurrentReference(...)`: + +- `statuscode` +- `ticketnumber` +- `incidentid` +- `pinswg_appealcasetype` as `appealType` +- normalized specialist process from `searchDetailsObj[0].value[0]` + +Code reference: + +- `pages/case/[ticketnumber].js:213-229` + +This means the status-tab journey is seeded primarily from: + +- CRM `statuscode` +- CRM appeal type +- CRM specialist-process fields after portal-side normalization + +#### 3.2 Specialist-process normalization before rendering + +`pages/case/[ticketnumber].js` calls: + +```js +normalizeSpecialistProcess(searchDetailsObj[0].value[0]); +``` + +`normalizeSpecialistProcess(...)` resolves specialist process by preferring: + +1. `pinswg_specialistcaseprocess` +2. `pinswg_speacialistcaseprocess` +3. empty string fallback + +Code references: + +- `pages/case/[ticketnumber].js:225-227` +- `lib/domain/case-lifecycle/normalizeSpecialistProcess.js:1-7` + +This is a CRM compatibility step, not a semantic reinterpretation step. + +#### 3.3 Case summary hosts the Case Status tab + +`components/case/summary.js` owns the tab structure and mounts the status-tab component. + +- The tab key is `case-status` +- The tab panel renders `` + +Code evidence: + +- `components/case/summary.js` contains the selected tab state `whichTab == "case-status"` +- `components/case/summary.js` renders `` + +#### 3.4 StatusDetails builds the stage journey + +`components/case/status.js` reads from Redux/currentView and invokes: + +```js +getLifecycleStagesForCase( + props.currentView?.caseReference?.appealType, + props.currentView?.caseReference?.statuscode, + specialistProcess +); +``` + +Important points: + +- The second argument is named `currentStageId` in the lifecycle seam, but the actual caller passes **CRM `statuscode`**. +- The component does **not** use `pinswg_casestage`. +- `specialistProcess` is read again from `props.searchResultsObj?.searchDetailsObj[0]?.value[0]?.pinswg_specialistcaseprocess`, i.e. only the canonical field in this component. + +Code reference: + +- `components/case/status.js:26-36` + +#### 3.5 Lifecycle seam delegates to legacy stage-catalogue helper + +`getLifecycleStagesForCase(...)` is a thin wrapper: + +```js +return getStagesForAppealType(caseType, currentStageId, specialistProcess); +``` + +Code reference: + +- `lib/domain/case-lifecycle/getLifecycleStagesForCase.js:1-9` + +This confirms the lifecycle seam is currently a read-only indirection layer, not an independently owned lifecycle engine. + +#### 3.6 Stage catalogue selection + +`getStagesForAppealType(...)` in `components/case/summary/utils/caseStagesByAppealType.js`: + +1. resolves a stage key using `getStageCaseTypeKey(...)` +2. loads the stage array with `getStagesForCaseTypeKey(...)` +3. finds the current stage index with `getLifecycleStageIndex(...)` +4. marks each stage `complete`, `in-progress`, or `not-started` with `getLifecycleStageStatus(...)` + +Code references: + +- `components/case/summary/utils/caseStagesByAppealType.js:779-796` + +#### 3.7 Stage journey rendering + +`components/case/status.js` renders the returned stage array as a GOV.UK task-list style visual journey: + +- each stage renders translated `titleKey` +- each stage can show `descriptionKey` in expandable details +- each stage gets a status tag: + - `complete` + - `in-progress` + - `not-started` + - `blocked` is defined in the map, though current lifecycle helper path does not produce it + +Code references: + +- `components/case/status.js:9-21` +- `components/case/status.js:80-137` + +#### Rendering-flow summary + +CRM data flow to rendered journey is: + +```text +CRM incident/search query + -> searchResultsObj.statuscode + -> searchResultsObj.pinswg_appealcasetype + -> searchDetailsObj specialist-process field(s) + -> setCurrentReference(...) on case page + -> StatusDetails reads currentView.caseReference + -> getLifecycleStagesForCase(...) + -> getStagesForAppealType(...) + -> getStageCaseTypeKey(...) + -> getStagesForCaseTypeKey(...) + -> getLifecycleStageIndex(...) + -> getLifecycleStageStatus(...) + -> rendered task-list stage journey +``` + +--- + +### 4. Field role assessment + +#### `statuscode` + +**Where used** + +- stored into `currentView.caseReference` on case page load (`pages/case/[ticketnumber].js`) +- used as the current stage input for `getLifecycleStagesForCase(...)` (`components/case/status.js`) +- displayed directly as formatted status labels in search results, summary-type components, my portal, and admin/reporting consumers +- mapped in `components/utils/caseStagesObj.js` + +**Purpose** + +- operational CRM status field +- primary input for status-tab current-stage resolution +- direct formatted label source for many non-status-tab consumers + +**Display impact** + +- determines which step in the visual stage journey is marked as current/completed/future +- also appears directly as human-readable status labels outside the journey UI + +#### `pinswg_casestage` + +**Where used** + +- displayed in `components/case/summary.js` as a summary row labelled `summary-case-stage-label` + +**Purpose** + +- PEDW custom case-stage field +- summary/details informational display field + +**Display impact** + +- affects the summary/details panel only in the reviewed path +- does **not** drive the Case Status tab journey in the current implementation + +#### Appeal type fields + +**Where used** + +- `pinswg_appealcasetype` stored as `appealType` in `currentView.caseReference` +- mapped through `mapAppealType(...)` +- used to choose the stage catalogue and, in some cases, specialist-process override logic + +**Purpose** + +- primary selector of the stage-journey family/catalogue + +**Display impact** + +- determines which stage list the user sees +- appeal types can share or diverge in stage journeys depending on mappings/aliases + +#### Specialist process fields + +**Where used** + +- normalized in `pages/case/[ticketnumber].js` from canonical/misspelled CRM fields +- re-read in `components/case/status.js` from canonical field only +- passed to `getStageCaseTypeKey(...)` +- used by `mapSpecialistProcessStageType(...)` for stage-journey override + +**Purpose** + +- refine stage-journey selection for selected appeal types, especially Rights of Way variants + +**Display impact** + +- can switch the status-tab journey from one stage catalogue to another +- affects selection, not just labels + +#### Closed/terminal status fields + +**Where used** + +- `isClosedCaseStatus(...)` treats these values as closed/terminal: + - `1000` + - `5` + - `6` + - `846040013` + - `846040060` + - `846040059` + +**Purpose** + +- fallback mechanism when the current numeric input does not exactly match a stage in the selected catalogue + +**Display impact** + +- if the supplied `statuscode` is considered closed, current stage resolves to the stage whose `titleKey === "case-closed"` +- otherwise unmatched values produce `currentIndex === -1`, making all stages render as `not-started` + +--- + +### 5. Stage journey selection + +#### 5.1 Appeal-type selection + +The portal selects a stage journey first through `mapAppealType(...)` and `caseTypeKeyByAppealTypeId`. + +Examples: + +- `846040000` -> `PLANNING_S78` +- `846040010` -> `CALL_INS` +- `846040018` -> `ADVERTS` +- `846040019` -> `COMPULSORY_PURCHASE_ORDERS` +- `846040002` -> `SIP` +- `846040011` -> `DNS` + +Code reference: + +- `lib/domain/case-lifecycle/mapAppealType.js:35-80` + +#### 5.2 Appeal-family / alias behaviour + +Some stage journeys are shared by alias or indirection rather than unique arrays. + +Examples: + +- `SIP` resolves by string indirection to `DNS` +- `CONDITIONS_73_79`, `LBCAC`, `LDCS`, `PLANNING_OBLIGATIONS_S106`, `PRIOR_NOTIFICATION` all share `PLANNING_S78` +- `ENFORCEMENT_LISTED_BUILDING` and `MAINTENANCE_OF_LAND` share `ENFORCEMENT` + +This is handled by: + +- alias mapping in `mapAppealType.js` +- string indirection in `getStagesForCaseTypeKey.js` + +#### 5.3 Specialist-process selection + +`getStageCaseTypeKey(...)` only applies specialist-process override when the numeric appeal-type mapping is the one in play: + +```js +caseTypeKeyByAppealTypeId[appealTypeId] === mappedCaseType + ? mapSpecialistProcessStageType(mappedCaseType, specialistProcess) + : undefined; +``` + +Current override table only exists for `RIGHTS_OF_WAY_SCHEDULE_14`, mapping specialist-process values into: + +- `RIGHTS_OF_WAY_ORDERS` +- `RIGHTS_OF_WAY_SCHEDULE_14` +- `REQUESTS_FOR_DIRECTION` + +Code references: + +- `lib/domain/case-lifecycle/getStageCaseTypeKey.js:9-25` +- `lib/domain/case-lifecycle/mapSpecialistProcessStageType.js:1-19` + +#### 5.4 Fallback behaviour + +Fallback order in `getStageCaseTypeKey(...)` is: + +1. specialist-process-derived stage key +2. mapped appeal type key +3. alias lookup from normalized input +4. normalized raw input + +Then `getStagesForCaseTypeKey(...)`: + +- returns `[]` when no entry exists +- resolves string indirection to another catalogue +- otherwise returns the array directly + +#### Selection classification + +Selection appears **mixed**: + +- **CRM-driven:** because appeal type and specialist process are CRM inputs +- **presentation-driven:** because the output is selection of a visual journey catalogue with title/description text +- **business-driven:** partially, because different appeal types and specialist processes are clearly treated as meaningfully different journeys +- **not purely CRM status display:** because the portal constructs a catalogue-driven journey rather than simply displaying a single CRM status value + +--- + +### 6. Current stage resolution + +#### 6.1 Exact status matching + +`getLifecycleStageIndex(...)` converts the incoming current value to a number and tries to find a stage whose `stageId` exactly matches it. + +```js +const exactIndex = stages.findIndex( + (stage) => Number(stage.stageId) === currentStageNumber +); +``` + +This means the status-tab journey currently treats the passed `statuscode` as the numeric identifier to align with stage-catalogue `stageId` values. + +#### 6.2 Closed-stage fallback + +If exact matching fails, `isClosedCaseStatus(...)` is consulted. + +If true, current index becomes the index of the stage whose `titleKey` is `case-closed`. + +This is a special fallback path for terminal/closed values rather than exact stage matching. + +#### 6.3 Unmatched status handling + +If there is no exact match and the value is not recognized as closed, `getLifecycleStageIndex(...)` returns `-1`. + +Then `getLifecycleStageStatus(...)` marks **all** stages as `not-started`. + +That is important characterized behaviour. + +#### 6.4 Completed/current/future stage calculation + +`getLifecycleStageStatus(index, currentIndex)` returns: + +- `complete` when `index < currentIndex` +- `in-progress` when `index === currentIndex` +- `not-started` when `index > currentIndex` +- `not-started` for all stages when `currentIndex === -1` + +#### 6.5 Blocked behaviour + +`components/case/status.js` includes `blocked` style/text mappings, but the lifecycle calculation path reviewed here never returns `blocked`. + +This suggests either legacy/future intent or another non-reviewed path, but not active current-stage calculation from the status-tab helper chain. + +--- + +### 7. Consumer comparison + +#### Case Status Tab + +Displays: + +- **stage journey:** yes +- **CRM status:** indirectly, as the input driving current stage selection +- **custom case stage (`pinswg_casestage`):** no +- **formatted labels:** yes, but as translated stage titles/descriptions and progress tags, not CRM formatted status labels +- **derived values:** yes, complete/in-progress/not-started status is portal-derived + +Primary inputs: + +- `statuscode` +- appeal type +- specialist process + +#### Case Details / Summary + +Displays: + +- **CRM status:** yes, via summary-type components using `statuscode@OData.Community.Display.V1.FormattedValue` +- **custom case stage:** yes, in `components/case/summary.js` via `pinswg_casestage@OData.Community.Display.V1.FormattedValue` +- **stage journey:** yes, but only through the separate Case Status tab component +- **formatted labels:** yes +- **derived values:** limited; mostly direct display of CRM formatted values + +Important distinction: + +- summary/details panel uses `pinswg_casestage` directly for one row +- status tab uses `statuscode`-driven stage-journey derivation + +#### Search Results + +Displays: + +- **CRM status:** yes, direct formatted value via `statuscode@OData.Community.Display.V1.FormattedValue` +- **custom case stage:** no evidence in reviewed search results path +- **stage journey:** no +- **formatted labels:** yes +- **derived values:** no stage derivation; mostly direct CRM-formatted display + +Additional role: + +- clicking a search result seeds `currentView.caseReference.statuscode`, appeal type, and specialist process for downstream case-page/status-tab behaviour + +--- + +### 8. Divergence catalogue + +#### Divergence 1: Status tab uses `statuscode`, summary row uses `pinswg_casestage` + +- **Behaviour:** summary/details can display PEDW custom case stage while the Case Status tab derives its journey from `statuscode`. +- **Likely reason:** summary row is informational display of a custom PEDW field; status tab is a portal-constructed journey over a separate stage catalogue. +- **Appears intentional?** **No / unclear**. It is clearly implemented, but the repository does not prove this distinction is consciously documented as an intentional model boundary. + +#### Divergence 2: Status tab renders derived journey; search results render direct formatted status label + +- **Behaviour:** search results show `statuscode@OData.Community.Display.V1.FormattedValue`, while the case status tab shows a multi-step journey. +- **Likely reason:** search results need compact list display; case page gives richer progress visualization. +- **Appears intentional?** **Yes**, at presentation level. + +#### Divergence 3: Specialist-process normalization differs between case page and status tab component + +- **Behaviour:** + - case page uses `normalizeSpecialistProcess(...)` with canonical + misspelled fallback + - `components/case/status.js` reads only `pinswg_specialistcaseprocess` +- **Likely reason:** partial refactor / mixed old-new access patterns. +- **Appears intentional?** **No** based on current evidence. + +#### Divergence 4: Summary/status consumers display different concepts under similar “status/stage” area + +- **Behaviour:** summary-type components use formatted `statuscode`; summary row separately uses `pinswg_casestage`; status tab ignores `pinswg_casestage` and derives stage journey from `statuscode`. +- **Likely reason:** mixture of CRM operational status display and PEDW custom stage display without one unified presentation model. +- **Appears intentional?** **Unclear**. + +#### Divergence 5: Closed-state handling is explicit in journey logic but not equivalent in direct status consumers + +- **Behaviour:** status tab has a special closed-case fallback through `isClosedCaseStatus(...)`; direct status-label consumers simply display CRM formatted values. +- **Likely reason:** journey UI requires a terminal visual state even when exact stage IDs do not match. +- **Appears intentional?** **Probably yes** for the journey component, though the exact closed-value set may be compatibility-driven. + +#### Divergence 6: Unmatched status values collapse whole journey to `not-started` + +- **Behaviour:** if a `statuscode` does not match any stage ID and is not considered closed, every stage renders as `not-started`. +- **Likely reason:** simple index-based implementation with no fallback “unknown current stage” state. +- **Appears intentional?** **No / unclear**; more likely inherited behaviour. + +--- + +### 9. Characterization test candidates + +#### High Priority + +1. **Case page seeds status tab inputs correctly** + - protect that `statuscode`, appeal type, and normalized specialist process are placed into `currentView.caseReference` + +2. **Stage catalogue selection by appeal type** + - representative coverage for shared and distinct catalogues (e.g. S78, Call-in, DNS, Advert, CPO) + +3. **Specialist-process override selection** + - protect current Rights of Way specialist-process remapping into alternate stage journeys + +4. **Exact status-to-stage matching** + - prove that matching `statuscode` selects the expected current stage index + +5. **Closed-case fallback behaviour** + - prove unmatched closed values map to `case-closed` + +6. **Unmatched non-closed status behaviour** + - prove all stages become `not-started` + +7. **Status tab ignores `pinswg_casestage`** + - protect current separation between status-tab journey logic and custom case-stage summary display + +#### Medium Priority + +1. **String vs numeric appeal type handling in stage selection** +2. **Alias/indirection resolution** + - e.g. `SIP -> DNS`, `ENFORCEMENT_LISTED_BUILDING -> ENFORCEMENT` +3. **Specialist-process normalization divergence coverage** + - protect current canonical vs misspelled field handling at case-page input stage +4. **Representative summary/status/search comparison tests** + - prove summary row uses `pinswg_casestage`, search uses formatted `statuscode`, status tab uses derived journey + +#### Low Priority + +1. **Expand-all/default-open UI behaviour on the status tab** +2. **Presence/absence of description keys in journey rendering** +3. **Translation-key coverage for representative stage catalogues** + +--- + +### 10. Initial conclusion + +**Answer: C. Portal-constructed visual journey based on CRM inputs** + +#### Supporting evidence + +- The Case Status tab does **not** directly display `pinswg_casestage`. +- It does **not** simply render CRM formatted `statuscode` labels. +- Instead, it uses CRM `statuscode`, appeal type, and specialist process to select a portal-owned stage catalogue and then derive progress state across that catalogue. +- The selected catalogue contains portal presentation metadata (`titleKey`, `descriptionKey`) and is rendered as a visual journey/task list. +- `pinswg_casestage` is displayed elsewhere in summary/details as a separate PEDW custom field, which further shows that the Case Status tab is a constructed layer rather than a simple raw-field display. + +Therefore the Case Status tab is best understood as: + +> a portal-constructed visual journey that uses CRM operational inputs and portal stage catalogues to present case progression to the user. + +It is **not** a pure CRM status display, and it is **not** currently a pure PEDW custom case-stage display either. + +--- + +### 11. Recommended next step + +Keep the next slice narrow and characterization-focused. + +The strongest follow-on is: + +1. characterize **summary/details/search divergence** around: + - `statuscode` + - `pinswg_casestage` + - formatted labels + - specialist-process field usage + +Reason: + +- this slice established how the Case Status tab works internally +- the remaining ambiguity now sits at the cross-consumer boundary, especially where summary/details and search display different lifecycle/status concepts from the status-tab journey diff --git a/reports/crm-case-progress-display-assessment.md b/reports/crm-case-progress-display-assessment.md new file mode 100644 index 00000000..f1b1f6b2 --- /dev/null +++ b/reports/crm-case-progress-display-assessment.md @@ -0,0 +1,287 @@ +## CRM Case Progress Display – Planning Review Assessment + +Active branch: `feature/crm-case-progress-display-planning` + +Assessment scope: planning-only review of existing repository evidence to assess whether CRM Case Progress Display should become a formal investigation stream. + +--- + +## 1. What has already been discovered? + +### Known facts + +- CRM is the system of record for case progression and status; the portal consumes CRM state through relay-backed API queries rather than owning the operational progression itself. +- The portal already uses CRM-owned `statuscode` widely across public search, case summary, my portal, watched cases, admin dashboards, and lifecycle display. +- The portal also reads `pinswg_casestage` directly in case summary presentation, indicating that both stage-like and status-like CRM fields already influence the UI. +- The portal contains a read-only lifecycle interpretation seam in `lib/domain/case-lifecycle`, but that boundary explicitly does **not** claim ownership of lifecycle semantics, progress/status calculation ownership, dashboard behaviour, or closed-case handling. +- Lifecycle display is currently driven by stage catalogues keyed by appeal type and mapped from CRM-derived inputs, rather than by a single explicit business model. +- Dashboard/worklist grouping uses additional state concepts beyond CRM `statuscode`, including `servicestage eq 1` for awaiting-submission cases and watched-case submission markers such as `pinswg_representationsubmitted`. + +### Known ownership boundaries + +- **CRM ownership:** operational case status/progression data (`statuscode`, `pinswg_casestage`, related entity fields, formatted labels). +- **Portal API ownership:** fetch and lightly reshape CRM data for consumers; examples include `getmycases_api`, `getawaitingsubmission_api`, and `getwatchedcases_api`. +- **Portal lifecycle seam ownership:** read-only interpretation and lookup behaviour, not source semantics (`lib/domain/case-lifecycle/README.md`). +- **Dashboard policy ownership:** limited watched/submitted classification for watched cases only; not overall dashboard lifecycle meaning (`lib/domain/dashboard-policy/README.md`). +- **Appeal-type policy ownership:** family classification only, not lifecycle/status behaviour (`lib/domain/appeal-type-policy/README.md`). + +### Known consumer groups + +- Public search results and case pages. +- Authenticated portal users in my portal panels and view-all screens. +- Watched-case and representation users. +- Admin/reporting views that aggregate counts by `statuscode` and appeal type/LPA. +- Case-summary users consuming the staged “status” journey view. + +### Known transformations + +- Raw CRM `statuscode` is transformed into: + - formatted public-facing status labels, + - stage-journey progress via `getLifecycleStagesForCase(...)`, + - aggregated reporting buckets/counts in admin dashboards, + - worklist segmentation such as awaiting submission, watched, and submitted representations. +- Specialist-process and appeal-type mappings influence which lifecycle stage catalogue is used. +- The portal reshapes watched-case and case query payloads by copying/renaming fields for UI convenience. +- Dashboard/worklist interpretations mix CRM data with portal-owned workflow markers such as blob-backed drafts and representation-submitted flags. + +Conclusion: the repository already shows that this area is not a single raw CRM status display. It is a multi-consumer interpretation layer spanning operational status, staged progress presentation, workflow segmentation, and reporting aggregation. + +--- + +## 2. What remains unknown? + +The most important genuine unknowns are: + +1. **`statuscode` vs `pinswg_casestage` relationship** + - It remains unclear whether these represent parallel CRM concepts, a primary/secondary lifecycle pair, or historical overlap. + +2. **Lifecycle journey ownership** + - It is not yet clear whether the staged journey shown in case status is an intentional business-facing lifecycle model or a portal-side presentation mapping layered on top of CRM statuses. + +3. **Specialist-process influence on lifecycle display** + - Specialist process is already used to choose stage catalogues in some flows, but the intended ownership and completeness of that influence is unclear. + +4. **Closed-state and non-intuitive stage handling intent** + - The lifecycle seam explicitly preserves ambiguity around status vs stage and closed-case behaviour, which implies unresolved semantics. + +5. **Progress display consistency across consumers** + - Public search, case summary, my portal panels, watched cases, and admin dashboards all consume status differently; it is unclear which differences are deliberate versus incidental. + +6. **Reporting interpretation boundaries** + - Admin dashboards aggregate directly by `statuscode`, but it is unclear whether those counts represent operational CRM reporting only or are intended to align with user-facing lifecycle stages. + +7. **Portal workflow vs CRM lifecycle boundary** + - Drafts, awaiting submission, submission processing, and submitted representations already use portal and blob/worklist concepts. The precise boundary between CRM lifecycle and portal workflow state remains unclear. + +8. **Whether current stage catalogues encode business meaning or UI narrative only** + - The repository contains large appeal-type-specific stage arrays, but current evidence does not prove whether they are authoritative business semantics or user-guidance presentation. + +--- + +## 3. Classification Assessment + +This area should currently be classified as a **mixture** of multiple model types. + +### B. Presentation Model + +**Selected: Yes** + +**Evidence** + +- `components/case/status.js` renders a staged progress UI from interpreted lifecycle stages. +- `components/case/summary/utils/caseStagesByAppealType.js` contains appeal-type-specific stage catalogues with title/description translation keys, which is strong evidence of a presentation-oriented journey model. +- The lifecycle boundary README explicitly says it is a read-only interpretation seam and does not define new lifecycle semantics. + +### C. CRM Compatibility Layer + +**Selected: Yes** + +**Evidence** + +- `docs/query-profile-compatibility.md` states CRM field names are the source of truth and that downstream status/lifecycle views depend on preserving CRM field variants. +- The system preserves raw CRM `statuscode` and variant field shapes rather than normalizing them into a single clean internal model. +- API routes and search/case components depend on CRM formatted values and raw fields directly. + +### D. Reporting Model + +**Selected: Yes** + +**Evidence** + +- Admin endpoints such as `getStatusCountsByAppeal_api.js`, `getStatusCountsByAppealAndLPA_api.js`, and `getAppealsByStatusCounts_api.js` aggregate counts by `statuscode` for dashboards and drill-down search links. +- This is a distinct consumer need from case-summary lifecycle presentation. + +### E. User Workflow Model + +**Selected: Yes** + +**Evidence** + +- `context/domain-flows.md` documents portal-visible states such as awaiting submission, pending, and submission processing. +- `getawaitingsubmission_api.js` segments cases using `servicestage eq 1`, and dashboard policy separately classifies watched/submitted records using representation submission markers. +- These workflow concepts are not reducible to the case-summary lifecycle display alone. + +### A. Business Decision Model + +**Selected: Maybe / partial only** + +**Evidence for limited inclusion** + +- The portal definitely makes repeatable interpretation decisions about which stage journey to show, which bucket a record belongs in, and which status label/count to expose. +- However, current repository evidence does **not** yet prove that this is a coherent, intentional business decision model in the same way representation participation was shown to be. +- Existing docs explicitly preserve ambiguity: the lifecycle seam says it does not own semantics and must preserve “status-vs-stage ambiguity”. + +Assessment: this is **not yet convincingly classifiable as a pure business decision model**. It looks more like a presentation/compatibility/workflow/reporting mixture with some embedded business meaning. + +--- + +## 4. Architectural Value Assessment + +If further characterization were performed, the likely outputs would be: + +1. **Ownership map** + - Clarify which lifecycle/status meanings are owned by CRM versus interpreted by portal presentation, dashboard logic, and reporting. + +2. **Transformation map** + - Trace how raw CRM fields (`statuscode`, `pinswg_casestage`, specialist process, service stage, representation submission flags) become user-facing lifecycle stages, worklists, and reporting summaries. + +3. **Presentation model documentation** + - Document what the case-status journey actually represents per appeal type and whether it is intended as user guidance, operational translation, or formal lifecycle narrative. + +4. **Compatibility documentation** + - Record which CRM field dependencies and ambiguities are compatibility-sensitive and must be preserved. + +5. **Consumer divergence map** + - Identify where public search, case summary, my portal, watched cases, and admin dashboards intentionally diverge or accidentally drift. + +6. **Workflow boundary clarification** + - Separate CRM operational lifecycle from portal draft/submission/worklist state. + +### Likely value + +The main value would be **architectural clarity**, not immediate extraction. It would reduce ambiguity for future refactor slices touching case summary, search, my portal, admin reporting, and CRM integration seams. + +--- + +## 5. Domain Candidate Assessment + +**Answer: Maybe** + +### Evidence + +- There is already a narrow `lib/domain/case-lifecycle` seam, which indicates the codebase has identified this as a potentially separable interpretation concern. +- The area spans multiple consumers and repeated translation logic, which is a common signal of a future domain-layer candidate. +- However, the current seam explicitly avoids owning semantics, progress/status calculation ownership, dashboard behaviour, and closed-case handling. +- The evidence currently points to a mixed concern area rather than a stable, well-bounded domain policy. + +Conclusion: this looks like a **future domain-layer candidate only if characterization first clarifies ownership and semantics**. Today it is too ambiguous and multi-purpose to treat as a clearly ready domain boundary. + +--- + +## 6. Cost vs Value Assessment + +### Investigation Cost + +**Medium** + +**Reasoning** + +- The evidence is already partially assembled through current docs and the extracted lifecycle seam. +- However, the concern spans many consumers: case summary, search, my portal, watched cases, admin dashboards, API queries, and stage catalogues. +- The ambiguity between status, stage, workflow, and reporting means a slice still requires careful cross-consumer characterization. + +### Architectural Value + +**High** + +**Reasoning** + +- This area sits at a boundary between CRM integration, portal presentation, and user workflow interpretation. +- Clarifying it would improve future decision-making in several existing streams and reduce the risk of accidental semantic changes during refactor. +- The repository already names this as the next likely discovery candidate, which aligns with the observed ambiguity. + +### Maintenance Value + +**Medium to High** + +**Reasoning** + +- Better understanding would help maintainers avoid conflating raw CRM status, lifecycle stage display, dashboard grouping, and workflow state. +- It would make future changes safer in high-touch files such as `components/case/status.js`, `components/case/summary.js`, `components/myportal/viewall.js`, and related API routes. +- Value is not yet “very high” because characterization alone would not immediately simplify the code unless followed later by carefully bounded extraction work. + +--- + +## 7. Recommendation + +**Recommendation: Option B — Perform one characterization slice.** + +### Supporting evidence + +- Current understanding is **not** sufficient to say this is only CRM compatibility or only presentation. +- Existing evidence already proves this area mixes at least presentation, workflow, reporting, and compatibility concerns. +- A full characterization stream is not yet justified because representation participation business validation is still an active dependency in project context, and the scope here is broad. +- One bounded slice focused on ownership and transformation clarity would likely answer whether the broader stream is worthwhile. + +Why not Option A: + +- There are still material unknowns around `statuscode` vs `pinswg_casestage`, stage ownership, consumer divergence, and workflow/reporting boundaries. + +Why not Option C: + +- The current evidence supports further investigation, but not yet a full multi-slice stream without first proving that the ambiguity resolves into a coherent characterization target. + +Why not Option D: + +- This remains a stronger next investigation candidate than many other areas because the ambiguity is architectural, cross-cutting, and already partially surfaced by existing seams and docs. + +--- + +## 8. Alternative Investigation Candidates + +If CRM Case Progress Display is not taken next, the strongest evidenced alternatives from the repository are: + +1. **Portal workflow state / my portal worklist segmentation** + - Evidence: `context/domain-flows.md`, `lib/domain/dashboard-policy/README.md`, `components/myportal/viewall.js`, `getawaitingsubmission_api.js`, watched/submitted classification. + - Why candidate: the portal already mixes draft, awaiting submission, watched, submitted, and representation states outside the lifecycle seam. + +2. **CRM integration boundary / status-query compatibility** + - Evidence: `docs/query-profile-compatibility.md`, `actions/selectQueryTypes.js`. + - Why candidate: lifecycle and status views depend on CRM field selection and compatibility-preserving query shapes. + +3. **Submission journey state boundaries** + - Evidence: awaiting-submission blob flows, service-stage filters, draft continuation routes, and my portal segmentation. + - Why candidate: this may produce a cleaner workflow-state understanding than starting with all lifecycle presentation concerns at once. + +4. **Notification / watched-case workflow interpretation** + - Evidence: `getwatchedcases_api.js`, dashboard-policy classification, watched vs submitted representation handling. + - Why candidate: it exposes a narrower but related interpretation boundary between CRM case records and user-facing participation state. + +These candidates are all evidenced in current repository state. None are invented. + +--- + +## 9. Final Conclusion + +**Answer: B. Probably** + +### Supporting evidence + +- The codebase already shows this area is broader than simple CRM status display. +- There is clear evidence of multiple overlapping models: CRM operational status, staged case progress presentation, dashboard/worklist workflow grouping, and reporting aggregation. +- The existing lifecycle seam explicitly preserves ambiguity instead of resolving it, which suggests meaningful architectural understanding is still missing. +- However, the area does **not yet** show the same clear coherence as representation participation; therefore the likely value is real but should first be tested with one bounded characterization slice rather than a full stream. + +Overall conclusion: + +> CRM Case Progress Display is likely to produce meaningful additional architectural understanding beyond what is already known, but only **probably**, not clearly enough yet to justify a full characterization stream immediately. + +--- + +## Assessment Outcome Summary + +- **Should this become a formal investigation stream now?** Not yet as a full stream. +- **Best next step:** one bounded characterization slice. +- **Current classification:** mixed presentation + CRM compatibility + reporting + user workflow area, with partial business meaning but no proven single policy model yet. +- **Domain-layer candidate assessment:** Maybe. +- **Cost/value:** Medium investigation cost; High architectural value; Medium-to-High maintenance value.