From 5399be1a41adb6fb50a8e0597ccd352433143571 Mon Sep 17 00:00:00 2001 From: sadmanrahman Date: Thu, 25 Jun 2026 10:43:49 +0100 Subject: [PATCH 01/70] HDPI-6835: Gen App Doc Sequencing --- .../reform/pcs/ccd/entity/PcsCaseEntity.java | 15 +-------------- .../V128__gen_app_case_level_rank.sql | 19 +++++++++++++++++++ .../pcs/ccd/entity/PcsCaseEntityTest.java | 17 ++--------------- 3 files changed, 22 insertions(+), 29 deletions(-) create mode 100644 src/main/resources/db/migration/V128__gen_app_case_level_rank.sql diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/entity/PcsCaseEntity.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/entity/PcsCaseEntity.java index 7ffbf572fa..b432823f7b 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/entity/PcsCaseEntity.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/entity/PcsCaseEntity.java @@ -26,7 +26,6 @@ import java.util.ArrayList; import java.util.HashSet; import java.util.List; -import java.util.Objects; import java.util.Set; import java.util.UUID; @@ -130,7 +129,7 @@ public void addClaim(ClaimEntity claim) { } public void addGenApp(GenAppEntity genApp) { - int rank = countNumberOfGenAppsForParty(genApp.getParty()) + 1; + int rank = genApps.size() + 1; genApp.setRank(rank); genApps.add(genApp); genApp.setPcsCase(this); @@ -163,16 +162,4 @@ public void addCaseNote(CaseNoteEntity caseNote) { caseNote.setPcsCase(this); } - private int countNumberOfGenAppsForParty(PartyEntity party) { - if (party == null || party.getId() == null) { - return 0; - } - - return (int) genApps.stream() - .map(GenAppEntity::getParty) - .filter(Objects::nonNull) - .filter(genAppParty -> party.getId().equals(genAppParty.getId())) - .count(); - } - } diff --git a/src/main/resources/db/migration/V128__gen_app_case_level_rank.sql b/src/main/resources/db/migration/V128__gen_app_case_level_rank.sql new file mode 100644 index 0000000000..16b1f9f8e7 --- /dev/null +++ b/src/main/resources/db/migration/V128__gen_app_case_level_rank.sql @@ -0,0 +1,19 @@ +-- Move GA rank uniqueness from party-level to case-level. +-- Drop the old constraint that included party_id. +ALTER TABLE general_application + DROP CONSTRAINT IF EXISTS uq_case_party_rank; + +-- Re-number any existing rows so that the first GA per case is rank 1, the second is rank 2, etc. +WITH renumbered AS ( + SELECT id, + ROW_NUMBER() OVER (PARTITION BY case_id ORDER BY application_submitted_date NULLS LAST, id) AS new_rank + FROM general_application +) +UPDATE general_application ga +SET rank = r.new_rank +FROM renumbered r +WHERE ga.id = r.id; + +-- Add the new case-level unique constraint. +ALTER TABLE general_application + ADD CONSTRAINT uq_general_application_case_rank UNIQUE (case_id, rank); diff --git a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/entity/PcsCaseEntityTest.java b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/entity/PcsCaseEntityTest.java index 96b1fd9728..50cb649560 100644 --- a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/entity/PcsCaseEntityTest.java +++ b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/entity/PcsCaseEntityTest.java @@ -2,14 +2,9 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.mockito.Mockito; -import uk.gov.hmcts.reform.pcs.ccd.entity.party.PartyEntity; - -import java.util.UUID; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; class PcsCaseEntityTest { @@ -36,19 +31,11 @@ void shouldUpdateCaseOnTenancyLicenceWhenSet() { } @Test - void shouldAddGenAppEntityAndSetRank() { + void shouldAddGenAppEntityAndSetCaseLevelRank() { // Given - PartyEntity party1 = mock(PartyEntity.class); - when(party1.getId()).thenReturn(UUID.randomUUID()); - PartyEntity party2 = mock(PartyEntity.class); - when(party2.getId()).thenReturn(UUID.randomUUID()); - GenAppEntity genAppEntity1 = mock(GenAppEntity.class); - when(genAppEntity1.getParty()).thenReturn(party1); GenAppEntity genAppEntity2 = mock(GenAppEntity.class); - Mockito.when(genAppEntity2.getParty()).thenReturn(party1); GenAppEntity genAppEntity3 = mock(GenAppEntity.class); - Mockito.when(genAppEntity3.getParty()).thenReturn(party2); // When underTest.addGenApp(genAppEntity1); @@ -62,7 +49,7 @@ void shouldAddGenAppEntityAndSetRank() { verify(genAppEntity2).setRank(2); verify(genAppEntity2).setPcsCase(underTest); - verify(genAppEntity3).setRank(1); + verify(genAppEntity3).setRank(3); verify(genAppEntity3).setPcsCase(underTest); } From b01ee406f1e10f37ddf59a16284f77b880f2937d Mon Sep 17 00:00:00 2001 From: sadmanrahman Date: Thu, 25 Jun 2026 16:30:53 +0100 Subject: [PATCH 02/70] HDPI-6835: Gen App Doc Sequencing Tests --- .../pcs/ccd/entity/PcsCaseEntityTest.java | 16 ++++++++++ .../document/DocumentNameServiceTest.java | 30 +++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/entity/PcsCaseEntityTest.java b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/entity/PcsCaseEntityTest.java index 50cb649560..09c77b5509 100644 --- a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/entity/PcsCaseEntityTest.java +++ b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/entity/PcsCaseEntityTest.java @@ -53,4 +53,20 @@ void shouldAddGenAppEntityAndSetCaseLevelRank() { verify(genAppEntity3).setPcsCase(underTest); } + @Test + void shouldContinueGenAppCaseLevelRankFromExistingApplications() { + // Given + for (int i = 0; i < 5; i++) { + underTest.getGenApps().add(mock(GenAppEntity.class)); + } + GenAppEntity genAppEntity = mock(GenAppEntity.class); + + // When + underTest.addGenApp(genAppEntity); + + // Then + verify(genAppEntity).setRank(6); + verify(genAppEntity).setPcsCase(underTest); + } + } diff --git a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentNameServiceTest.java b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentNameServiceTest.java index d8ce998884..f0e07cff97 100644 --- a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentNameServiceTest.java +++ b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentNameServiceTest.java @@ -82,6 +82,36 @@ private static Stream genAppNamingScenarios() { ); } + @Test + void shouldAddCaseLevelGenAppNumberAndClaimantLabelToGenAppDocument() { + // Given + UUID applicantPartyId = UUID.randomUUID(); + GenAppEntity genAppEntity = GenAppEntity.builder() + .rank(4) + .build(); + + PartyEntity claimantParty = PartyEntity.builder() + .id(applicantPartyId) + .build(); + + ClaimPartyEntity claimant = ClaimPartyEntity.builder() + .party(claimantParty) + .rank(1) + .role(PartyRole.CLAIMANT) + .build(); + + ClaimEntity mainClaim = ClaimEntity.builder() + .claimParties(List.of(claimant)) + .build(); + + // When + String updatedFilename + = underTest.appendGenAppPostfix("General Application.pdf", genAppEntity, mainClaim, applicantPartyId); + + // Then + assertThat(updatedFilename).isEqualTo("General Application GA4 - Claimant 1.pdf"); + } + @ParameterizedTest @MethodSource("partyNamingScenarios") void shouldAddPartyLabelWithoutGenAppNumber(PartyRole partyRole, From 6c1a1033bb3387f371a05e7de9f653e519d6fd63 Mon Sep 17 00:00:00 2001 From: sadmanrahman Date: Fri, 26 Jun 2026 09:44:28 +0100 Subject: [PATCH 03/70] HDPI-6835: remove cleanup --- .../db/migration/V128__gen_app_case_level_rank.sql | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/main/resources/db/migration/V128__gen_app_case_level_rank.sql b/src/main/resources/db/migration/V128__gen_app_case_level_rank.sql index 16b1f9f8e7..9492b0fec8 100644 --- a/src/main/resources/db/migration/V128__gen_app_case_level_rank.sql +++ b/src/main/resources/db/migration/V128__gen_app_case_level_rank.sql @@ -3,17 +3,6 @@ ALTER TABLE general_application DROP CONSTRAINT IF EXISTS uq_case_party_rank; --- Re-number any existing rows so that the first GA per case is rank 1, the second is rank 2, etc. -WITH renumbered AS ( - SELECT id, - ROW_NUMBER() OVER (PARTITION BY case_id ORDER BY application_submitted_date NULLS LAST, id) AS new_rank - FROM general_application -) -UPDATE general_application ga -SET rank = r.new_rank -FROM renumbered r -WHERE ga.id = r.id; - -- Add the new case-level unique constraint. ALTER TABLE general_application ADD CONSTRAINT uq_general_application_case_rank UNIQUE (case_id, rank); From 1d43736b5f716f539659194cd039826d2693d2b6 Mon Sep 17 00:00:00 2001 From: sadmanrahman Date: Fri, 26 Jun 2026 11:40:04 +0100 Subject: [PATCH 04/70] HDPI-6835: add cleanup --- .../db/migration/V128__gen_app_case_level_rank.sql | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/main/resources/db/migration/V128__gen_app_case_level_rank.sql b/src/main/resources/db/migration/V128__gen_app_case_level_rank.sql index 9492b0fec8..653295f347 100644 --- a/src/main/resources/db/migration/V128__gen_app_case_level_rank.sql +++ b/src/main/resources/db/migration/V128__gen_app_case_level_rank.sql @@ -3,6 +3,17 @@ ALTER TABLE general_application DROP CONSTRAINT IF EXISTS uq_case_party_rank; +-- Re-number any existing rows so that the first GA per case is rank 1, the second is rank 2, etc. +WITH renumbered AS ( + SELECT id, + ROW_NUMBER() OVER (PARTITION BY case_id ORDER BY application_submitted_date NULLS LAST, id) AS new_rank + FROM general_application +) +UPDATE general_application ga +SET rank = r.new_rank + FROM renumbered r +WHERE ga.id = r.id; + -- Add the new case-level unique constraint. ALTER TABLE general_application ADD CONSTRAINT uq_general_application_case_rank UNIQUE (case_id, rank); From 508d5008ccf0d16bfc379c9f9201d0235ca385ba Mon Sep 17 00:00:00 2001 From: sadmanrahman Date: Mon, 29 Jun 2026 14:04:46 +0100 Subject: [PATCH 05/70] HDPI-7308: select document screen --- .../pcs/ccd/domain/CaseFileCategory.java | 5 +- .../hmcts/reform/pcs/ccd/domain/PCSCase.java | 4 + .../documentamend/DocumentAmendDetails.java | 130 ++++++++++ .../reform/pcs/ccd/event/AmendDocuments.java | 55 ++++ .../hmcts/reform/pcs/ccd/event/EventId.java | 1 + .../AmendDocumentDetailsPlaceholderPage.java | 20 ++ .../documentamend/SelectDocumentPage.java | 156 ++++++++++++ .../DocumentAmendSelectionService.java | 240 ++++++++++++++++++ .../ccd/service/DraftCaseJsonMergerTest.java | 1 + .../DocumentAmendSelectionServiceTest.java | 202 +++++++++++++++ 10 files changed, 812 insertions(+), 2 deletions(-) create mode 100644 src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendDetails.java create mode 100644 src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/AmendDocuments.java create mode 100644 src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/AmendDocumentDetailsPlaceholderPage.java create mode 100644 src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java create mode 100644 src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionService.java create mode 100644 src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/CaseFileCategory.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/CaseFileCategory.java index 0d8a87716f..b60f2e0e88 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/CaseFileCategory.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/CaseFileCategory.java @@ -11,10 +11,11 @@ public enum CaseFileCategory { PROPERTY_DOCUMENTS("propertyDocuments", "Property documents", 2), EVIDENCE("evidence", "Evidence", 3), HEARING_DOCUMENTS("hearingDocuments", "Hearing documents", 4), - ORDERS_AND_NOTICE_OF_HEARINGS("ordersAndNoticeOfHearings", "Orders and notice of hearings", 5), + ORDERS_AND_NOTICE_OF_HEARINGS("ordersAndNoticeOfHearings", "Orders and Notice of Hearings", 5), APPLICATIONS("applications", "Applications", 6), APPEALS("appeals", "Appeals", 7), - CORRESPONDENCE("correspondence", "Correspondence", 8); + CORRESPONDENCE("correspondence", "Correspondence", 8), + UNCATEGORISED_DOCUMENTS("uncategorisedDocuments", "Uncategorised documents", 9); private final String id; private final String label; diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/PCSCase.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/PCSCase.java index 4aeaca8be7..a484c87842 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/PCSCase.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/PCSCase.java @@ -29,6 +29,7 @@ import uk.gov.hmcts.reform.pcs.ccd.accesscontrol.InternalCaseFlagAccess; import uk.gov.hmcts.reform.pcs.ccd.accesscontrol.RasValidationAccess; import uk.gov.hmcts.reform.pcs.ccd.domain.dashboard.DashboardData; +import uk.gov.hmcts.reform.pcs.ccd.domain.documentamend.DocumentAmendDetails; import uk.gov.hmcts.reform.pcs.ccd.domain.enforcetheorder.EnforcementOrder; import uk.gov.hmcts.reform.pcs.ccd.domain.genapp.CitizenGenAppRequest; import uk.gov.hmcts.reform.pcs.ccd.domain.genapp.GeneralApplication; @@ -473,6 +474,9 @@ public class PCSCase { @JsonUnwrapped private DocumentUploadDetails documentUploadDetails; + @JsonUnwrapped(prefix = "documentAmend_") + private DocumentAmendDetails documentAmendDetails; + @CCD( label = "Are you planning to make an application at the same time as your claim?", hint = "After you’ve submitted your claim, there will be instructions on how to make an application" diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendDetails.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendDetails.java new file mode 100644 index 0000000000..9207d9728b --- /dev/null +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendDetails.java @@ -0,0 +1,130 @@ +package uk.gov.hmcts.reform.pcs.ccd.domain.documentamend; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import uk.gov.hmcts.ccd.sdk.api.CCD; +import uk.gov.hmcts.ccd.sdk.type.DynamicList; +import uk.gov.hmcts.ccd.sdk.type.YesOrNo; +import uk.gov.hmcts.reform.pcs.ccd.type.DynamicStringList; + +import static uk.gov.hmcts.ccd.sdk.type.FieldType.DynamicRadioList; + +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@JsonInclude(Include.NON_NULL) +public class DocumentAmendDetails { + + @CCD( + label = "Which folder is the document in?", + searchable = false + ) + private DynamicList selectedFolder; + + @CCD( + label = "Which document do you want to amend?", + searchable = false, + typeOverride = DynamicRadioList + ) + private DynamicStringList statementsOfCaseDocuments; + + @CCD( + label = "Which document do you want to amend?", + searchable = false, + typeOverride = DynamicRadioList + ) + private DynamicStringList propertyDocuments; + + @CCD( + label = "Which document do you want to amend?", + searchable = false, + typeOverride = DynamicRadioList + ) + private DynamicStringList evidenceDocuments; + + @CCD( + label = "Which document do you want to amend?", + searchable = false, + typeOverride = DynamicRadioList + ) + private DynamicStringList hearingDocuments; + + @CCD( + label = "Which document do you want to amend?", + searchable = false, + typeOverride = DynamicRadioList + ) + private DynamicStringList ordersAndNoticeOfHearingsDocuments; + + @CCD( + label = "Which document do you want to amend?", + searchable = false, + typeOverride = DynamicRadioList + ) + private DynamicStringList applicationsDocuments; + + @CCD( + label = "Which document do you want to amend?", + searchable = false, + typeOverride = DynamicRadioList + ) + private DynamicStringList appealsDocuments; + + @CCD( + label = "Which document do you want to amend?", + searchable = false, + typeOverride = DynamicRadioList + ) + private DynamicStringList correspondenceDocuments; + + @CCD( + label = "Which document do you want to amend?", + searchable = false, + typeOverride = DynamicRadioList + ) + private DynamicStringList uncategorisedDocuments; + + @CCD(searchable = false) + private YesOrNo statementsOfCaseEmpty; + + @CCD(searchable = false) + private YesOrNo propertyDocumentsEmpty; + + @CCD(searchable = false) + private YesOrNo evidenceEmpty; + + @CCD(searchable = false) + private YesOrNo hearingDocumentsEmpty; + + @CCD(searchable = false) + private YesOrNo ordersAndNoticeOfHearingsEmpty; + + @CCD(searchable = false) + private YesOrNo applicationsEmpty; + + @CCD(searchable = false) + private YesOrNo appealsEmpty; + + @CCD(searchable = false) + private YesOrNo correspondenceEmpty; + + @CCD(searchable = false) + private YesOrNo uncategorisedDocumentsEmpty; + + @CCD(searchable = false) + private String selectedFolderId; + + @CCD(searchable = false) + private String selectedFolderLabel; + + @CCD(searchable = false) + private String selectedDocumentId; + + @CCD(searchable = false) + private String selectedDocumentFileName; +} diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/AmendDocuments.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/AmendDocuments.java new file mode 100644 index 0000000000..d7e4785ce1 --- /dev/null +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/AmendDocuments.java @@ -0,0 +1,55 @@ +package uk.gov.hmcts.reform.pcs.ccd.event; + +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Component; +import uk.gov.hmcts.ccd.sdk.api.CCDConfig; +import uk.gov.hmcts.ccd.sdk.api.DecentralisedConfigBuilder; +import uk.gov.hmcts.ccd.sdk.api.Event; +import uk.gov.hmcts.ccd.sdk.api.EventPayload; +import uk.gov.hmcts.ccd.sdk.api.Permission; +import uk.gov.hmcts.ccd.sdk.api.callback.SubmitResponse; +import uk.gov.hmcts.reform.pcs.ccd.accesscontrol.UserRole; +import uk.gov.hmcts.reform.pcs.ccd.common.PageBuilder; +import uk.gov.hmcts.reform.pcs.ccd.domain.PCSCase; +import uk.gov.hmcts.reform.pcs.ccd.domain.State; +import uk.gov.hmcts.reform.pcs.ccd.page.documentamend.AmendDocumentDetailsPlaceholderPage; +import uk.gov.hmcts.reform.pcs.ccd.page.documentamend.SelectDocumentPage; +import uk.gov.hmcts.reform.pcs.ccd.service.document.DocumentAmendSelectionService; + +import static uk.gov.hmcts.reform.pcs.ccd.event.EventId.amendDocuments; + +@Component +@AllArgsConstructor +public class AmendDocuments implements CCDConfig { + + private final DocumentAmendSelectionService documentAmendSelectionService; + private final SelectDocumentPage selectDocumentPage; + private final AmendDocumentDetailsPlaceholderPage amendDocumentDetailsPlaceholderPage; + + @Override + public void configureDecentralised(DecentralisedConfigBuilder configBuilder) { + Event.EventBuilder eventBuilder = + configBuilder + .decentralisedEvent(amendDocuments.name(), this::submit, this::start) + .forStates(State.CASE_ISSUED) + .name("Manage documents: Amend") + .grant(Permission.CRU, UserRole.CTSC_ADMIN) + .grant(Permission.CRU, UserRole.WLU_ADMIN) + .grant(Permission.CRU, UserRole.HEARING_CENTRE_ADMIN) + .endButtonLabel("Submit"); + + PageBuilder pageBuilder = new PageBuilder(eventBuilder); + selectDocumentPage.addTo(pageBuilder); + amendDocumentDetailsPlaceholderPage.addTo(pageBuilder); + } + + private PCSCase start(EventPayload eventPayload) { + PCSCase caseData = eventPayload.caseData(); + documentAmendSelectionService.initialise(eventPayload.caseReference(), caseData); + return caseData; + } + + private SubmitResponse submit(EventPayload eventPayload) { + return SubmitResponse.defaultResponse(); + } +} diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/EventId.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/EventId.java index a21043ef9f..eb00b7ce14 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/EventId.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/EventId.java @@ -15,6 +15,7 @@ public enum EventId { dashboardView, confirmEviction, uploadDocuments, + amendDocuments, addCaseNote, createFlags, amendFlags, diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/AmendDocumentDetailsPlaceholderPage.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/AmendDocumentDetailsPlaceholderPage.java new file mode 100644 index 0000000000..4414252a4d --- /dev/null +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/AmendDocumentDetailsPlaceholderPage.java @@ -0,0 +1,20 @@ +package uk.gov.hmcts.reform.pcs.ccd.page.documentamend; + +import org.springframework.stereotype.Component; +import uk.gov.hmcts.reform.pcs.ccd.common.CcdPageConfiguration; +import uk.gov.hmcts.reform.pcs.ccd.common.PageBuilder; + +@Component +public class AmendDocumentDetailsPlaceholderPage implements CcdPageConfiguration { + + @Override + public void addTo(PageBuilder pageBuilder) { + pageBuilder + .page("amendDocumentDetails") + .pageLabel("Amend document details") + .label("amendDocumentDetails-selectedDocument", """ + --- + Selected document: ${documentAmend_SelectedDocumentFileName} + """); + } +} diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java new file mode 100644 index 0000000000..064224ed20 --- /dev/null +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java @@ -0,0 +1,156 @@ +package uk.gov.hmcts.reform.pcs.ccd.page.documentamend; + +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Component; +import uk.gov.hmcts.ccd.sdk.api.CaseDetails; +import uk.gov.hmcts.ccd.sdk.api.callback.AboutToStartOrSubmitResponse; +import uk.gov.hmcts.reform.pcs.ccd.common.CcdPageConfiguration; +import uk.gov.hmcts.reform.pcs.ccd.common.PageBuilder; +import uk.gov.hmcts.reform.pcs.ccd.domain.CaseFileCategory; +import uk.gov.hmcts.reform.pcs.ccd.domain.PCSCase; +import uk.gov.hmcts.reform.pcs.ccd.domain.State; +import uk.gov.hmcts.reform.pcs.ccd.domain.documentamend.DocumentAmendDetails; +import uk.gov.hmcts.reform.pcs.ccd.service.document.DocumentAmendSelectionService; + +import java.util.List; + +import static uk.gov.hmcts.reform.pcs.ccd.ShowConditions.NEVER_SHOW; + +@AllArgsConstructor +@Component +public class SelectDocumentPage implements CcdPageConfiguration { + + private static final String PAGE_ID = "selectDocument"; + private static final String FIELD_PREFIX = "documentAmend_"; + private static final String YES = "=\"Yes\""; + private static final String NO = "=\"No\""; + + private final DocumentAmendSelectionService documentAmendSelectionService; + + @Override + public void addTo(PageBuilder pageBuilder) { + pageBuilder + .page(PAGE_ID, this::midEvent) + .pageLabel("Select document") + .label(PAGE_ID + "-caption", "### Manage documents: Amend") + .label(PAGE_ID + "-caseReference", "Case number: ${[CASE_REFERENCE]}") + .readonly(PCSCase::getPropertyAddress) + .readonly(PCSCase::getClaimantNames) + .readonly(PCSCase::getDefendantNames) + .complex(PCSCase::getDocumentAmendDetails) + .mandatory(DocumentAmendDetails::getSelectedFolder) + .mandatory(DocumentAmendDetails::getStatementsOfCaseDocuments, + documentsShowCondition(CaseFileCategory.STATEMENTS_OF_CASE)) + .label("statementsOfCaseNoDocumentsQuestion", "Which document do you want to amend?", + noDocumentsShowCondition(CaseFileCategory.STATEMENTS_OF_CASE)) + .label("statementsOfCaseNoDocuments", noDocumentsMessage(CaseFileCategory.STATEMENTS_OF_CASE), + noDocumentsShowCondition(CaseFileCategory.STATEMENTS_OF_CASE)) + .mandatory(DocumentAmendDetails::getPropertyDocuments, + documentsShowCondition(CaseFileCategory.PROPERTY_DOCUMENTS)) + .label("propertyDocumentsNoDocumentsQuestion", "Which document do you want to amend?", + noDocumentsShowCondition(CaseFileCategory.PROPERTY_DOCUMENTS)) + .label("propertyDocumentsNoDocuments", noDocumentsMessage(CaseFileCategory.PROPERTY_DOCUMENTS), + noDocumentsShowCondition(CaseFileCategory.PROPERTY_DOCUMENTS)) + .mandatory(DocumentAmendDetails::getEvidenceDocuments, + documentsShowCondition(CaseFileCategory.EVIDENCE)) + .label("evidenceNoDocumentsQuestion", "Which document do you want to amend?", + noDocumentsShowCondition(CaseFileCategory.EVIDENCE)) + .label("evidenceNoDocuments", noDocumentsMessage(CaseFileCategory.EVIDENCE), + noDocumentsShowCondition(CaseFileCategory.EVIDENCE)) + .mandatory(DocumentAmendDetails::getHearingDocuments, + documentsShowCondition(CaseFileCategory.HEARING_DOCUMENTS)) + .label("hearingDocumentsNoDocumentsQuestion", "Which document do you want to amend?", + noDocumentsShowCondition(CaseFileCategory.HEARING_DOCUMENTS)) + .label("hearingDocumentsNoDocuments", noDocumentsMessage(CaseFileCategory.HEARING_DOCUMENTS), + noDocumentsShowCondition(CaseFileCategory.HEARING_DOCUMENTS)) + .mandatory(DocumentAmendDetails::getOrdersAndNoticeOfHearingsDocuments, + documentsShowCondition(CaseFileCategory.ORDERS_AND_NOTICE_OF_HEARINGS)) + .label("ordersAndNoticeOfHearingsNoDocumentsQuestion", "Which document do you want to amend?", + noDocumentsShowCondition(CaseFileCategory.ORDERS_AND_NOTICE_OF_HEARINGS)) + .label("ordersAndNoticeOfHearingsNoDocuments", + noDocumentsMessage(CaseFileCategory.ORDERS_AND_NOTICE_OF_HEARINGS), + noDocumentsShowCondition(CaseFileCategory.ORDERS_AND_NOTICE_OF_HEARINGS)) + .mandatory(DocumentAmendDetails::getApplicationsDocuments, + documentsShowCondition(CaseFileCategory.APPLICATIONS)) + .label("applicationsNoDocumentsQuestion", "Which document do you want to amend?", + noDocumentsShowCondition(CaseFileCategory.APPLICATIONS)) + .label("applicationsNoDocuments", noDocumentsMessage(CaseFileCategory.APPLICATIONS), + noDocumentsShowCondition(CaseFileCategory.APPLICATIONS)) + .mandatory(DocumentAmendDetails::getAppealsDocuments, + documentsShowCondition(CaseFileCategory.APPEALS)) + .label("appealsNoDocumentsQuestion", "Which document do you want to amend?", + noDocumentsShowCondition(CaseFileCategory.APPEALS)) + .label("appealsNoDocuments", noDocumentsMessage(CaseFileCategory.APPEALS), + noDocumentsShowCondition(CaseFileCategory.APPEALS)) + .mandatory(DocumentAmendDetails::getCorrespondenceDocuments, + documentsShowCondition(CaseFileCategory.CORRESPONDENCE)) + .label("correspondenceNoDocumentsQuestion", "Which document do you want to amend?", + noDocumentsShowCondition(CaseFileCategory.CORRESPONDENCE)) + .label("correspondenceNoDocuments", noDocumentsMessage(CaseFileCategory.CORRESPONDENCE), + noDocumentsShowCondition(CaseFileCategory.CORRESPONDENCE)) + .mandatory(DocumentAmendDetails::getUncategorisedDocuments, + documentsShowCondition(CaseFileCategory.UNCATEGORISED_DOCUMENTS)) + .label("uncategorisedDocumentsNoDocumentsQuestion", "Which document do you want to amend?", + noDocumentsShowCondition(CaseFileCategory.UNCATEGORISED_DOCUMENTS)) + .label("uncategorisedDocumentsNoDocuments", + noDocumentsMessage(CaseFileCategory.UNCATEGORISED_DOCUMENTS), + noDocumentsShowCondition(CaseFileCategory.UNCATEGORISED_DOCUMENTS)) + .readonly(DocumentAmendDetails::getStatementsOfCaseEmpty, NEVER_SHOW, true) + .readonly(DocumentAmendDetails::getPropertyDocumentsEmpty, NEVER_SHOW, true) + .readonly(DocumentAmendDetails::getEvidenceEmpty, NEVER_SHOW, true) + .readonly(DocumentAmendDetails::getHearingDocumentsEmpty, NEVER_SHOW, true) + .readonly(DocumentAmendDetails::getOrdersAndNoticeOfHearingsEmpty, NEVER_SHOW, true) + .readonly(DocumentAmendDetails::getApplicationsEmpty, NEVER_SHOW, true) + .readonly(DocumentAmendDetails::getAppealsEmpty, NEVER_SHOW, true) + .readonly(DocumentAmendDetails::getCorrespondenceEmpty, NEVER_SHOW, true) + .readonly(DocumentAmendDetails::getUncategorisedDocumentsEmpty, NEVER_SHOW, true) + .readonly(DocumentAmendDetails::getSelectedFolderId, NEVER_SHOW, true) + .readonly(DocumentAmendDetails::getSelectedFolderLabel, NEVER_SHOW, true) + .readonly(DocumentAmendDetails::getSelectedDocumentId, NEVER_SHOW, true) + .readonly(DocumentAmendDetails::getSelectedDocumentFileName, NEVER_SHOW, true) + .done(); + } + + private AboutToStartOrSubmitResponse midEvent(CaseDetails details, + CaseDetails detailsBefore) { + PCSCase caseData = details.getData(); + + documentAmendSelectionService.initialise(details.getId(), caseData); + List errors = documentAmendSelectionService.validateAndStoreSelection(caseData); + + return AboutToStartOrSubmitResponse.builder() + .data(caseData) + .errors(errors.isEmpty() ? null : errors) + .build(); + } + + private String documentsShowCondition(CaseFileCategory category) { + return selectedFolderCondition(category) + " AND " + emptyFieldId(category) + NO; + } + + private String noDocumentsShowCondition(CaseFileCategory category) { + return selectedFolderCondition(category) + " AND " + emptyFieldId(category) + YES; + } + + private String selectedFolderCondition(CaseFileCategory category) { + return FIELD_PREFIX + "SelectedFolder=\"" + DocumentAmendSelectionService.folderCode(category) + "\""; + } + + private String emptyFieldId(CaseFileCategory category) { + return switch (category) { + case STATEMENTS_OF_CASE -> FIELD_PREFIX + "StatementsOfCaseEmpty"; + case PROPERTY_DOCUMENTS -> FIELD_PREFIX + "PropertyDocumentsEmpty"; + case EVIDENCE -> FIELD_PREFIX + "EvidenceEmpty"; + case HEARING_DOCUMENTS -> FIELD_PREFIX + "HearingDocumentsEmpty"; + case ORDERS_AND_NOTICE_OF_HEARINGS -> FIELD_PREFIX + "OrdersAndNoticeOfHearingsEmpty"; + case APPLICATIONS -> FIELD_PREFIX + "ApplicationsEmpty"; + case APPEALS -> FIELD_PREFIX + "AppealsEmpty"; + case CORRESPONDENCE -> FIELD_PREFIX + "CorrespondenceEmpty"; + case UNCATEGORISED_DOCUMENTS -> FIELD_PREFIX + "UncategorisedDocumentsEmpty"; + }; + } + + private String noDocumentsMessage(CaseFileCategory category) { + return "No documents in '" + category.getLabel() + "'"; + } +} diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionService.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionService.java new file mode 100644 index 0000000000..c279411be7 --- /dev/null +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionService.java @@ -0,0 +1,240 @@ +package uk.gov.hmcts.reform.pcs.ccd.service.document; + +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; +import uk.gov.hmcts.ccd.sdk.type.DynamicList; +import uk.gov.hmcts.ccd.sdk.type.DynamicListElement; +import uk.gov.hmcts.ccd.sdk.type.YesOrNo; +import uk.gov.hmcts.reform.pcs.ccd.domain.CaseFileCategory; +import uk.gov.hmcts.reform.pcs.ccd.domain.PCSCase; +import uk.gov.hmcts.reform.pcs.ccd.domain.VerticalYesNo; +import uk.gov.hmcts.reform.pcs.ccd.domain.documentamend.DocumentAmendDetails; +import uk.gov.hmcts.reform.pcs.ccd.entity.DocumentEntity; +import uk.gov.hmcts.reform.pcs.ccd.entity.PcsCaseEntity; +import uk.gov.hmcts.reform.pcs.ccd.service.PcsCaseService; +import uk.gov.hmcts.reform.pcs.ccd.type.DynamicStringList; +import uk.gov.hmcts.reform.pcs.ccd.type.DynamicStringListElement; + +import java.nio.charset.StandardCharsets; +import java.util.Comparator; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.UUID; + +@Service +public class DocumentAmendSelectionService { + + private static final String SELECT_DIFFERENT_FOLDER_ERROR = "Select a different folder to continue"; + private static final Comparator DOCUMENT_ORDER = Comparator + .comparing(DocumentEntity::getSubmittedDate, Comparator.nullsLast(Comparator.reverseOrder())) + .thenComparing(DocumentEntity::getFileName, Comparator.nullsLast(String::compareToIgnoreCase)); + + private final PcsCaseService pcsCaseService; + + public DocumentAmendSelectionService(PcsCaseService pcsCaseService) { + this.pcsCaseService = pcsCaseService; + } + + public static UUID folderCode(CaseFileCategory category) { + return UUID.nameUUIDFromBytes(category.getId().getBytes(StandardCharsets.UTF_8)); + } + + public void initialise(long caseReference, PCSCase caseData) { + DocumentAmendDetails details = getOrCreateDetails(caseData); + PcsCaseEntity pcsCase = pcsCaseService.loadCase(caseReference); + + details.setSelectedFolder(folderList(details.getSelectedFolder())); + setDocumentsForCategory(details, pcsCase, CaseFileCategory.STATEMENTS_OF_CASE); + setDocumentsForCategory(details, pcsCase, CaseFileCategory.PROPERTY_DOCUMENTS); + setDocumentsForCategory(details, pcsCase, CaseFileCategory.EVIDENCE); + setDocumentsForCategory(details, pcsCase, CaseFileCategory.HEARING_DOCUMENTS); + setDocumentsForCategory(details, pcsCase, CaseFileCategory.ORDERS_AND_NOTICE_OF_HEARINGS); + setDocumentsForCategory(details, pcsCase, CaseFileCategory.APPLICATIONS); + setDocumentsForCategory(details, pcsCase, CaseFileCategory.APPEALS); + setDocumentsForCategory(details, pcsCase, CaseFileCategory.CORRESPONDENCE); + setDocumentsForCategory(details, pcsCase, CaseFileCategory.UNCATEGORISED_DOCUMENTS); + } + + public List validateAndStoreSelection(PCSCase caseData) { + DocumentAmendDetails details = caseData.getDocumentAmendDetails(); + if (details == null || selectedFolderId(details) == null) { + return List.of(); + } + + CaseFileCategory selectedFolder = categoryForId(selectedFolderId(details)).orElse(null); + if (selectedFolder == null) { + return List.of(); + } + + DynamicStringList selectedDocuments = documentsForCategory(details, selectedFolder); + details.setSelectedFolderId(selectedFolder.getId()); + details.setSelectedFolderLabel(selectedFolder.getLabel()); + + if (isEmpty(selectedDocuments)) { + details.setSelectedDocumentId(null); + details.setSelectedDocumentFileName(null); + return List.of(SELECT_DIFFERENT_FOLDER_ERROR); + } + + DynamicStringListElement selectedDocument = selectedDocuments.getValue(); + if (selectedDocument == null || selectedDocument.getCode() == null) { + details.setSelectedDocumentId(null); + details.setSelectedDocumentFileName(null); + return List.of(); + } + + details.setSelectedDocumentId(selectedDocument.getCode()); + details.setSelectedDocumentFileName(selectedDocument.getLabel()); + return List.of(); + } + + private void setDocumentsForCategory(DocumentAmendDetails details, PcsCaseEntity pcsCase, + CaseFileCategory category) { + DynamicStringList documents = documentList(pcsCase, category, documentsForCategory(details, category)); + applyDocumentsForCategory(details, category, documents); + setEmptyForCategory(details, category, YesOrNo.from(isEmpty(documents))); + } + + private DynamicStringList documentList(PcsCaseEntity pcsCase, CaseFileCategory category, + DynamicStringList existingList) { + DynamicStringListElement selected = existingList == null ? null : existingList.getValue(); + + List documents = CollectionUtils.isEmpty(pcsCase.getDocuments()) + ? List.of() + : pcsCase.getDocuments().stream() + .filter(Objects::nonNull) + .filter(this::isVisibleToCaseworker) + .filter(document -> isInCategory(document, category)) + .sorted(DOCUMENT_ORDER) + .map(document -> DynamicStringListElement.builder() + .code(document.getId().toString()) + .label(document.getFileName()) + .build()) + .toList(); + + return DynamicStringList.builder() + .value(retainSelectedValue(selected, documents)) + .listItems(documents) + .build(); + } + + private boolean isVisibleToCaseworker(DocumentEntity document) { + return document.getGeneralApplication() == null + || document.getGeneralApplication().getWithoutNotice() != VerticalYesNo.YES; + } + + private boolean isInCategory(DocumentEntity document, CaseFileCategory category) { + if (category == CaseFileCategory.UNCATEGORISED_DOCUMENTS) { + return document.getCategoryId() == null; + } + + return category.getId().equals(document.getCategoryId()); + } + + private DynamicList folderList(DynamicList existingList) { + DynamicListElement selected = existingList == null ? null : existingList.getValue(); + List folders = List.of(CaseFileCategory.values()).stream() + .sorted(Comparator.comparing(CaseFileCategory::getDisplayOrder)) + .map(category -> new DynamicListElement(folderCode(category), category.getLabel())) + .toList(); + + return new DynamicList(retainSelectedFolder(selected, folders), folders); + } + + private DynamicStringListElement retainSelectedValue(DynamicStringListElement selected, + List options) { + if (selected == null || selected.getCode() == null) { + return null; + } + + return options.stream() + .filter(option -> selected.getCode().equals(option.getCode())) + .findFirst() + .orElse(null); + } + + private String selectedFolderId(DocumentAmendDetails details) { + if (details.getSelectedFolder() == null || details.getSelectedFolder().getValue() == null) { + return null; + } + + UUID selectedCode = details.getSelectedFolder().getValue().getCode(); + return List.of(CaseFileCategory.values()).stream() + .filter(category -> folderCode(category).equals(selectedCode)) + .map(CaseFileCategory::getId) + .findFirst() + .orElse(null); + } + + private DynamicListElement retainSelectedFolder(DynamicListElement selected, List options) { + if (selected == null || selected.getCode() == null) { + return null; + } + + return options.stream() + .filter(option -> selected.getCode().equals(option.getCode())) + .findFirst() + .orElse(null); + } + + private Optional categoryForId(String id) { + return List.of(CaseFileCategory.values()).stream() + .filter(category -> category.getId().equals(id)) + .findFirst(); + } + + private boolean isEmpty(DynamicStringList documents) { + return documents == null || CollectionUtils.isEmpty(documents.getListItems()); + } + + private DocumentAmendDetails getOrCreateDetails(PCSCase caseData) { + if (caseData.getDocumentAmendDetails() == null) { + caseData.setDocumentAmendDetails(new DocumentAmendDetails()); + } + return caseData.getDocumentAmendDetails(); + } + + private DynamicStringList documentsForCategory(DocumentAmendDetails details, CaseFileCategory category) { + return switch (category) { + case STATEMENTS_OF_CASE -> details.getStatementsOfCaseDocuments(); + case PROPERTY_DOCUMENTS -> details.getPropertyDocuments(); + case EVIDENCE -> details.getEvidenceDocuments(); + case HEARING_DOCUMENTS -> details.getHearingDocuments(); + case ORDERS_AND_NOTICE_OF_HEARINGS -> details.getOrdersAndNoticeOfHearingsDocuments(); + case APPLICATIONS -> details.getApplicationsDocuments(); + case APPEALS -> details.getAppealsDocuments(); + case CORRESPONDENCE -> details.getCorrespondenceDocuments(); + case UNCATEGORISED_DOCUMENTS -> details.getUncategorisedDocuments(); + }; + } + + private void applyDocumentsForCategory(DocumentAmendDetails details, CaseFileCategory category, + DynamicStringList documents) { + switch (category) { + case STATEMENTS_OF_CASE -> details.setStatementsOfCaseDocuments(documents); + case PROPERTY_DOCUMENTS -> details.setPropertyDocuments(documents); + case EVIDENCE -> details.setEvidenceDocuments(documents); + case HEARING_DOCUMENTS -> details.setHearingDocuments(documents); + case ORDERS_AND_NOTICE_OF_HEARINGS -> details.setOrdersAndNoticeOfHearingsDocuments(documents); + case APPLICATIONS -> details.setApplicationsDocuments(documents); + case APPEALS -> details.setAppealsDocuments(documents); + case CORRESPONDENCE -> details.setCorrespondenceDocuments(documents); + case UNCATEGORISED_DOCUMENTS -> details.setUncategorisedDocuments(documents); + } + } + + private void setEmptyForCategory(DocumentAmendDetails details, CaseFileCategory category, YesOrNo empty) { + switch (category) { + case STATEMENTS_OF_CASE -> details.setStatementsOfCaseEmpty(empty); + case PROPERTY_DOCUMENTS -> details.setPropertyDocumentsEmpty(empty); + case EVIDENCE -> details.setEvidenceEmpty(empty); + case HEARING_DOCUMENTS -> details.setHearingDocumentsEmpty(empty); + case ORDERS_AND_NOTICE_OF_HEARINGS -> details.setOrdersAndNoticeOfHearingsEmpty(empty); + case APPLICATIONS -> details.setApplicationsEmpty(empty); + case APPEALS -> details.setAppealsEmpty(empty); + case CORRESPONDENCE -> details.setCorrespondenceEmpty(empty); + case UNCATEGORISED_DOCUMENTS -> details.setUncategorisedDocumentsEmpty(empty); + } + } +} diff --git a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/DraftCaseJsonMergerTest.java b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/DraftCaseJsonMergerTest.java index c7e5d17730..5ac8c175b1 100644 --- a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/DraftCaseJsonMergerTest.java +++ b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/DraftCaseJsonMergerTest.java @@ -88,6 +88,7 @@ void shouldKeepExistingFieldsWhenMerging() throws JsonProcessingException { "possessionClaimResponse", "enforcementOrder.rawWarrantDetails.vulnerableAdultsChildren", "xuiGenAppRequest", + "documentAmendDetails", "casePartiesTab", "caseDetailsTab", "summaryTab") diff --git a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java new file mode 100644 index 0000000000..da0ca05a42 --- /dev/null +++ b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java @@ -0,0 +1,202 @@ +package uk.gov.hmcts.reform.pcs.ccd.service.document; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import uk.gov.hmcts.ccd.sdk.type.DynamicList; +import uk.gov.hmcts.ccd.sdk.type.DynamicListElement; +import uk.gov.hmcts.ccd.sdk.type.YesOrNo; +import uk.gov.hmcts.reform.pcs.ccd.domain.CaseFileCategory; +import uk.gov.hmcts.reform.pcs.ccd.domain.PCSCase; +import uk.gov.hmcts.reform.pcs.ccd.domain.VerticalYesNo; +import uk.gov.hmcts.reform.pcs.ccd.domain.documentamend.DocumentAmendDetails; +import uk.gov.hmcts.reform.pcs.ccd.entity.DocumentEntity; +import uk.gov.hmcts.reform.pcs.ccd.entity.GenAppEntity; +import uk.gov.hmcts.reform.pcs.ccd.entity.PcsCaseEntity; +import uk.gov.hmcts.reform.pcs.ccd.service.PcsCaseService; +import uk.gov.hmcts.reform.pcs.ccd.type.DynamicStringList; +import uk.gov.hmcts.reform.pcs.ccd.type.DynamicStringListElement; + +import java.time.Instant; +import java.util.List; +import java.util.UUID; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.when; +import static uk.gov.hmcts.reform.pcs.ccd.domain.CaseFileCategory.APPLICATIONS; +import static uk.gov.hmcts.reform.pcs.ccd.domain.CaseFileCategory.EVIDENCE; +import static uk.gov.hmcts.reform.pcs.ccd.domain.CaseFileCategory.UNCATEGORISED_DOCUMENTS; + +@ExtendWith(MockitoExtension.class) +class DocumentAmendSelectionServiceTest { + + private static final long CASE_REFERENCE = 1234567890123456L; + + @Mock + private PcsCaseService pcsCaseService; + + private DocumentAmendSelectionService underTest; + + @BeforeEach + void setUp() { + underTest = new DocumentAmendSelectionService(pcsCaseService); + } + + @Test + void shouldPopulateFolderDropdownWithCaseFileViewFolders() { + when(pcsCaseService.loadCase(CASE_REFERENCE)).thenReturn(PcsCaseEntity.builder().build()); + PCSCase caseData = PCSCase.builder().build(); + + underTest.initialise(CASE_REFERENCE, caseData); + + assertThat(caseData.getDocumentAmendDetails().getSelectedFolder().getListItems()) + .extracting(DynamicListElement::getLabel) + .containsExactly( + "Statements of case", + "Property documents", + "Evidence", + "Hearing documents", + "Orders and Notice of Hearings", + "Applications", + "Appeals", + "Correspondence", + "Uncategorised documents" + ); + } + + @Test + void shouldPopulateDocumentsForSelectedCategoryAndExcludeWithoutNoticeApplicationDocuments() { + DocumentEntity visibleEvidence = document("visible evidence.pdf", EVIDENCE.getId(), null); + DocumentEntity hiddenApplicationDocument = document( + "hidden application.pdf", + APPLICATIONS.getId(), + GenAppEntity.builder().withoutNotice(VerticalYesNo.YES).build() + ); + DocumentEntity visibleApplicationDocument = document( + "visible application.pdf", + APPLICATIONS.getId(), + GenAppEntity.builder().withoutNotice(VerticalYesNo.NO).build() + ); + PcsCaseEntity pcsCase = PcsCaseEntity.builder() + .documents(List.of(visibleEvidence, hiddenApplicationDocument, visibleApplicationDocument)) + .build(); + when(pcsCaseService.loadCase(CASE_REFERENCE)).thenReturn(pcsCase); + PCSCase caseData = PCSCase.builder().build(); + + underTest.initialise(CASE_REFERENCE, caseData); + + DocumentAmendDetails details = caseData.getDocumentAmendDetails(); + assertThat(details.getEvidenceDocuments().getListItems()) + .extracting(DynamicStringListElement::getLabel) + .containsExactly("visible evidence.pdf"); + assertThat(details.getApplicationsDocuments().getListItems()) + .extracting(DynamicStringListElement::getLabel) + .containsExactly("visible application.pdf"); + } + + @Test + void shouldShowDocumentsWithNullCategoryUnderUncategorisedDocuments() { + DocumentEntity uncategorisedDocument = document("loose document.pdf", null, null); + when(pcsCaseService.loadCase(CASE_REFERENCE)).thenReturn(PcsCaseEntity.builder() + .documents(List.of(uncategorisedDocument)) + .build()); + PCSCase caseData = PCSCase.builder().build(); + + underTest.initialise(CASE_REFERENCE, caseData); + + assertThat(caseData.getDocumentAmendDetails().getUncategorisedDocuments().getListItems()) + .extracting(DynamicStringListElement::getLabel) + .containsExactly("loose document.pdf"); + assertThat(caseData.getDocumentAmendDetails().getUncategorisedDocumentsEmpty()).isEqualTo(YesOrNo.NO); + } + + @Test + void shouldReturnDifferentFolderErrorWhenSelectedFolderHasNoDocuments() { + when(pcsCaseService.loadCase(CASE_REFERENCE)).thenReturn(PcsCaseEntity.builder().build()); + PCSCase caseData = PCSCase.builder() + .documentAmendDetails(DocumentAmendDetails.builder() + .selectedFolder(selectedFolder(UNCATEGORISED_DOCUMENTS)) + .build()) + .build(); + underTest.initialise(CASE_REFERENCE, caseData); + + List errors = underTest.validateAndStoreSelection(caseData); + + assertThat(errors).containsExactly("Select a different folder to continue"); + assertThat(caseData.getDocumentAmendDetails().getSelectedDocumentId()).isNull(); + } + + @Test + void shouldPersistSelectedFolderAndDocumentDetails() { + DocumentEntity document = document("photo.pdf", EVIDENCE.getId(), null); + when(pcsCaseService.loadCase(CASE_REFERENCE)).thenReturn(PcsCaseEntity.builder() + .documents(List.of(document)) + .build()); + PCSCase caseData = PCSCase.builder() + .documentAmendDetails(DocumentAmendDetails.builder() + .selectedFolder(selectedFolder(EVIDENCE)) + .evidenceDocuments(selectedDocument(document)) + .build()) + .build(); + underTest.initialise(CASE_REFERENCE, caseData); + + List errors = underTest.validateAndStoreSelection(caseData); + + assertThat(errors).isEmpty(); + assertThat(caseData.getDocumentAmendDetails().getSelectedFolderId()).isEqualTo(EVIDENCE.getId()); + assertThat(caseData.getDocumentAmendDetails().getSelectedFolderLabel()).isEqualTo(EVIDENCE.getLabel()); + assertThat(caseData.getDocumentAmendDetails().getSelectedDocumentId()).isEqualTo(document.getId().toString()); + assertThat(caseData.getDocumentAmendDetails().getSelectedDocumentFileName()).isEqualTo("photo.pdf"); + } + + @Test + void shouldLeaveMissingDocumentSelectionToExuiMandatoryValidation() { + DocumentEntity document = document("photo.pdf", EVIDENCE.getId(), null); + when(pcsCaseService.loadCase(CASE_REFERENCE)).thenReturn(PcsCaseEntity.builder() + .documents(List.of(document)) + .build()); + PCSCase caseData = PCSCase.builder() + .documentAmendDetails(DocumentAmendDetails.builder() + .selectedFolder(selectedFolder(EVIDENCE)) + .build()) + .build(); + underTest.initialise(CASE_REFERENCE, caseData); + + List errors = underTest.validateAndStoreSelection(caseData); + + assertThat(errors).isEmpty(); + assertThat(caseData.getDocumentAmendDetails().getSelectedDocumentId()).isNull(); + } + + private static DynamicList selectedFolder(CaseFileCategory category) { + DynamicListElement selectedFolder = new DynamicListElement( + DocumentAmendSelectionService.folderCode(category), + category.getLabel() + ); + return new DynamicList(selectedFolder, List.of(selectedFolder)); + } + + private static DynamicStringList selectedDocument(DocumentEntity document) { + DynamicStringListElement selectedDocument = DynamicStringListElement.builder() + .code(document.getId().toString()) + .label(document.getFileName()) + .build(); + + return DynamicStringList.builder() + .value(selectedDocument) + .listItems(List.of(selectedDocument)) + .build(); + } + + private static DocumentEntity document(String fileName, String categoryId, GenAppEntity generalApplication) { + return DocumentEntity.builder() + .id(UUID.randomUUID()) + .fileName(fileName) + .categoryId(categoryId) + .generalApplication(generalApplication) + .submittedDate(Instant.now()) + .build(); + } +} From 45938db645750c1edcaf1fc554a593ced8ae8454 Mon Sep 17 00:00:00 2001 From: sadmanrahman Date: Mon, 29 Jun 2026 14:18:15 +0100 Subject: [PATCH 06/70] HDPI-6835: update migration --- ..._app_case_level_rank.sql => V129__gen_app_case_level_rank.sql} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/main/resources/db/migration/{V128__gen_app_case_level_rank.sql => V129__gen_app_case_level_rank.sql} (100%) diff --git a/src/main/resources/db/migration/V128__gen_app_case_level_rank.sql b/src/main/resources/db/migration/V129__gen_app_case_level_rank.sql similarity index 100% rename from src/main/resources/db/migration/V128__gen_app_case_level_rank.sql rename to src/main/resources/db/migration/V129__gen_app_case_level_rank.sql From 47e4dd3e66d10db7abfcee2d8652cfffe0d5c465 Mon Sep 17 00:00:00 2001 From: sadmanrahman Date: Tue, 30 Jun 2026 10:26:23 +0100 Subject: [PATCH 07/70] HDPI-7308: update grants --- .../reform/pcs/ccd/event/AmendDocuments.java | 4 ++++ .../DocumentAmendSelectionService.java | 11 ---------- .../DocumentAmendSelectionServiceTest.java | 21 ++++++++++++------- 3 files changed, 17 insertions(+), 19 deletions(-) diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/AmendDocuments.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/AmendDocuments.java index d7e4785ce1..2893ae7a00 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/AmendDocuments.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/AmendDocuments.java @@ -36,6 +36,10 @@ public void configureDecentralised(DecentralisedConfigBuilder isInCategory(document, category)) .sorted(DOCUMENT_ORDER) .map(document -> DynamicStringListElement.builder() @@ -119,16 +117,7 @@ private DynamicStringList documentList(PcsCaseEntity pcsCase, CaseFileCategory c .build(); } - private boolean isVisibleToCaseworker(DocumentEntity document) { - return document.getGeneralApplication() == null - || document.getGeneralApplication().getWithoutNotice() != VerticalYesNo.YES; - } - private boolean isInCategory(DocumentEntity document, CaseFileCategory category) { - if (category == CaseFileCategory.UNCATEGORISED_DOCUMENTS) { - return document.getCategoryId() == null; - } - return category.getId().equals(document.getCategoryId()); } diff --git a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java index da0ca05a42..195022af82 100644 --- a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java +++ b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java @@ -67,10 +67,10 @@ void shouldPopulateFolderDropdownWithCaseFileViewFolders() { } @Test - void shouldPopulateDocumentsForSelectedCategoryAndExcludeWithoutNoticeApplicationDocuments() { + void shouldPopulateDocumentsForSelectedCategoryAndIncludeWithoutNoticeApplicationDocuments() { DocumentEntity visibleEvidence = document("visible evidence.pdf", EVIDENCE.getId(), null); - DocumentEntity hiddenApplicationDocument = document( - "hidden application.pdf", + DocumentEntity withoutNoticeApplicationDocument = document( + "without notice application.pdf", APPLICATIONS.getId(), GenAppEntity.builder().withoutNotice(VerticalYesNo.YES).build() ); @@ -80,7 +80,7 @@ void shouldPopulateDocumentsForSelectedCategoryAndExcludeWithoutNoticeApplicatio GenAppEntity.builder().withoutNotice(VerticalYesNo.NO).build() ); PcsCaseEntity pcsCase = PcsCaseEntity.builder() - .documents(List.of(visibleEvidence, hiddenApplicationDocument, visibleApplicationDocument)) + .documents(List.of(visibleEvidence, withoutNoticeApplicationDocument, visibleApplicationDocument)) .build(); when(pcsCaseService.loadCase(CASE_REFERENCE)).thenReturn(pcsCase); PCSCase caseData = PCSCase.builder().build(); @@ -93,14 +93,19 @@ void shouldPopulateDocumentsForSelectedCategoryAndExcludeWithoutNoticeApplicatio .containsExactly("visible evidence.pdf"); assertThat(details.getApplicationsDocuments().getListItems()) .extracting(DynamicStringListElement::getLabel) - .containsExactly("visible application.pdf"); + .containsExactly("visible application.pdf", "without notice application.pdf"); } @Test - void shouldShowDocumentsWithNullCategoryUnderUncategorisedDocuments() { + void shouldOnlyShowDocumentsWithUncategorisedCategoryUnderUncategorisedDocuments() { DocumentEntity uncategorisedDocument = document("loose document.pdf", null, null); + DocumentEntity categorisedDocument = document( + "uncategorised document.pdf", + UNCATEGORISED_DOCUMENTS.getId(), + null + ); when(pcsCaseService.loadCase(CASE_REFERENCE)).thenReturn(PcsCaseEntity.builder() - .documents(List.of(uncategorisedDocument)) + .documents(List.of(uncategorisedDocument, categorisedDocument)) .build()); PCSCase caseData = PCSCase.builder().build(); @@ -108,7 +113,7 @@ void shouldShowDocumentsWithNullCategoryUnderUncategorisedDocuments() { assertThat(caseData.getDocumentAmendDetails().getUncategorisedDocuments().getListItems()) .extracting(DynamicStringListElement::getLabel) - .containsExactly("loose document.pdf"); + .containsExactly("uncategorised document.pdf"); assertThat(caseData.getDocumentAmendDetails().getUncategorisedDocumentsEmpty()).isEqualTo(YesOrNo.NO); } From ef947105102123ceda897c422815a414cff592cd Mon Sep 17 00:00:00 2001 From: sadmanrahman Date: Tue, 30 Jun 2026 14:24:34 +0100 Subject: [PATCH 08/70] HDPI-7308: fix select doc screen --- .../documentamend/DocumentAmendDetails.java | 14 +++- .../documentamend/DocumentAmendFolder.java | 27 +++++++ .../documentamend/SelectDocumentPage.java | 28 ++++++-- .../DocumentAmendSelectionService.java | 71 +++++-------------- .../DocumentAmendSelectionServiceTest.java | 56 ++++++++++----- 5 files changed, 116 insertions(+), 80 deletions(-) create mode 100644 src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendFolder.java diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendDetails.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendDetails.java index 9207d9728b..c14b3e21a0 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendDetails.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendDetails.java @@ -7,11 +7,11 @@ import lombok.Data; import lombok.NoArgsConstructor; import uk.gov.hmcts.ccd.sdk.api.CCD; -import uk.gov.hmcts.ccd.sdk.type.DynamicList; import uk.gov.hmcts.ccd.sdk.type.YesOrNo; import uk.gov.hmcts.reform.pcs.ccd.type.DynamicStringList; import static uk.gov.hmcts.ccd.sdk.type.FieldType.DynamicRadioList; +import static uk.gov.hmcts.ccd.sdk.type.FieldType.FixedList; @Builder @Data @@ -22,9 +22,17 @@ public class DocumentAmendDetails { @CCD( label = "Which folder is the document in?", - searchable = false + searchable = false, + typeOverride = FixedList, + typeParameterOverride = "DocumentAmendFolder" ) - private DynamicList selectedFolder; + private DocumentAmendFolder selectedFolder; + + @CCD(searchable = false) + private String propertyAddressSummary; + + @CCD(searchable = false) + private String partyNamesSummary; @CCD( label = "Which document do you want to amend?", diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendFolder.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendFolder.java new file mode 100644 index 0000000000..073c023397 --- /dev/null +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendFolder.java @@ -0,0 +1,27 @@ +package uk.gov.hmcts.reform.pcs.ccd.domain.documentamend; + +import lombok.Getter; +import uk.gov.hmcts.ccd.sdk.api.HasLabel; +import uk.gov.hmcts.reform.pcs.ccd.domain.CaseFileCategory; + +@Getter +public enum DocumentAmendFolder implements HasLabel { + + STATEMENTS_OF_CASE(CaseFileCategory.STATEMENTS_OF_CASE), + PROPERTY_DOCUMENTS(CaseFileCategory.PROPERTY_DOCUMENTS), + EVIDENCE(CaseFileCategory.EVIDENCE), + HEARING_DOCUMENTS(CaseFileCategory.HEARING_DOCUMENTS), + ORDERS_AND_NOTICE_OF_HEARINGS(CaseFileCategory.ORDERS_AND_NOTICE_OF_HEARINGS), + APPLICATIONS(CaseFileCategory.APPLICATIONS), + APPEALS(CaseFileCategory.APPEALS), + CORRESPONDENCE(CaseFileCategory.CORRESPONDENCE), + UNCATEGORISED_DOCUMENTS(CaseFileCategory.UNCATEGORISED_DOCUMENTS); + + private final CaseFileCategory category; + private final String label; + + DocumentAmendFolder(CaseFileCategory category) { + this.category = category; + this.label = category.getLabel(); + } +} diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java index 064224ed20..865de3656d 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java @@ -10,6 +10,7 @@ import uk.gov.hmcts.reform.pcs.ccd.domain.PCSCase; import uk.gov.hmcts.reform.pcs.ccd.domain.State; import uk.gov.hmcts.reform.pcs.ccd.domain.documentamend.DocumentAmendDetails; +import uk.gov.hmcts.reform.pcs.ccd.domain.documentamend.DocumentAmendFolder; import uk.gov.hmcts.reform.pcs.ccd.service.document.DocumentAmendSelectionService; import java.util.List; @@ -32,12 +33,15 @@ public void addTo(PageBuilder pageBuilder) { pageBuilder .page(PAGE_ID, this::midEvent) .pageLabel("Select document") - .label(PAGE_ID + "-caption", "### Manage documents: Amend") .label(PAGE_ID + "-caseReference", "Case number: ${[CASE_REFERENCE]}") - .readonly(PCSCase::getPropertyAddress) - .readonly(PCSCase::getClaimantNames) - .readonly(PCSCase::getDefendantNames) + .label(PAGE_ID + "-propertyAddress", "${documentAmend_PropertyAddressSummary}", + "documentAmend_PropertyAddressSummary!=\"\"") + .label(PAGE_ID + "-partyNames", "${documentAmend_PartyNamesSummary}", + "documentAmend_PartyNamesSummary!=\"\"") + .label(PAGE_ID + "-separator", "---") .complex(PCSCase::getDocumentAmendDetails) + .readonly(DocumentAmendDetails::getPropertyAddressSummary, NEVER_SHOW, true) + .readonly(DocumentAmendDetails::getPartyNamesSummary, NEVER_SHOW, true) .mandatory(DocumentAmendDetails::getSelectedFolder) .mandatory(DocumentAmendDetails::getStatementsOfCaseDocuments, documentsShowCondition(CaseFileCategory.STATEMENTS_OF_CASE)) @@ -133,7 +137,21 @@ private String noDocumentsShowCondition(CaseFileCategory category) { } private String selectedFolderCondition(CaseFileCategory category) { - return FIELD_PREFIX + "SelectedFolder=\"" + DocumentAmendSelectionService.folderCode(category) + "\""; + return FIELD_PREFIX + "SelectedFolder=\"" + folderForCategory(category).name() + "\""; + } + + private DocumentAmendFolder folderForCategory(CaseFileCategory category) { + return switch (category) { + case STATEMENTS_OF_CASE -> DocumentAmendFolder.STATEMENTS_OF_CASE; + case PROPERTY_DOCUMENTS -> DocumentAmendFolder.PROPERTY_DOCUMENTS; + case EVIDENCE -> DocumentAmendFolder.EVIDENCE; + case HEARING_DOCUMENTS -> DocumentAmendFolder.HEARING_DOCUMENTS; + case ORDERS_AND_NOTICE_OF_HEARINGS -> DocumentAmendFolder.ORDERS_AND_NOTICE_OF_HEARINGS; + case APPLICATIONS -> DocumentAmendFolder.APPLICATIONS; + case APPEALS -> DocumentAmendFolder.APPEALS; + case CORRESPONDENCE -> DocumentAmendFolder.CORRESPONDENCE; + case UNCATEGORISED_DOCUMENTS -> DocumentAmendFolder.UNCATEGORISED_DOCUMENTS; + }; } private String emptyFieldId(CaseFileCategory category) { diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionService.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionService.java index 6b0a126af7..2ecd234162 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionService.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionService.java @@ -2,8 +2,6 @@ import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; -import uk.gov.hmcts.ccd.sdk.type.DynamicList; -import uk.gov.hmcts.ccd.sdk.type.DynamicListElement; import uk.gov.hmcts.ccd.sdk.type.YesOrNo; import uk.gov.hmcts.reform.pcs.ccd.domain.CaseFileCategory; import uk.gov.hmcts.reform.pcs.ccd.domain.PCSCase; @@ -13,13 +11,13 @@ import uk.gov.hmcts.reform.pcs.ccd.service.PcsCaseService; import uk.gov.hmcts.reform.pcs.ccd.type.DynamicStringList; import uk.gov.hmcts.reform.pcs.ccd.type.DynamicStringListElement; +import uk.gov.hmcts.reform.pcs.ccd.util.AddressFormatter; -import java.nio.charset.StandardCharsets; import java.util.Comparator; import java.util.List; import java.util.Objects; -import java.util.Optional; -import java.util.UUID; + +import static uk.gov.hmcts.reform.pcs.ccd.util.AddressFormatter.COMMA_DELIMITER; @Service public class DocumentAmendSelectionService { @@ -30,20 +28,20 @@ public class DocumentAmendSelectionService { .thenComparing(DocumentEntity::getFileName, Comparator.nullsLast(String::compareToIgnoreCase)); private final PcsCaseService pcsCaseService; + private final AddressFormatter addressFormatter; - public DocumentAmendSelectionService(PcsCaseService pcsCaseService) { + public DocumentAmendSelectionService(PcsCaseService pcsCaseService, AddressFormatter addressFormatter) { this.pcsCaseService = pcsCaseService; - } - - public static UUID folderCode(CaseFileCategory category) { - return UUID.nameUUIDFromBytes(category.getId().getBytes(StandardCharsets.UTF_8)); + this.addressFormatter = addressFormatter; } public void initialise(long caseReference, PCSCase caseData) { DocumentAmendDetails details = getOrCreateDetails(caseData); PcsCaseEntity pcsCase = pcsCaseService.loadCase(caseReference); - details.setSelectedFolder(folderList(details.getSelectedFolder())); + details.setPropertyAddressSummary(addressFormatter.formatShortAddress(caseData.getPropertyAddress(), + COMMA_DELIMITER)); + details.setPartyNamesSummary(buildPartyNamesSummary(caseData)); setDocumentsForCategory(details, pcsCase, CaseFileCategory.STATEMENTS_OF_CASE); setDocumentsForCategory(details, pcsCase, CaseFileCategory.PROPERTY_DOCUMENTS); setDocumentsForCategory(details, pcsCase, CaseFileCategory.EVIDENCE); @@ -57,15 +55,11 @@ public void initialise(long caseReference, PCSCase caseData) { public List validateAndStoreSelection(PCSCase caseData) { DocumentAmendDetails details = caseData.getDocumentAmendDetails(); - if (details == null || selectedFolderId(details) == null) { - return List.of(); - } - - CaseFileCategory selectedFolder = categoryForId(selectedFolderId(details)).orElse(null); - if (selectedFolder == null) { + if (details == null || details.getSelectedFolder() == null) { return List.of(); } + CaseFileCategory selectedFolder = details.getSelectedFolder().getCategory(); DynamicStringList selectedDocuments = documentsForCategory(details, selectedFolder); details.setSelectedFolderId(selectedFolder.getId()); details.setSelectedFolderLabel(selectedFolder.getLabel()); @@ -121,16 +115,6 @@ private boolean isInCategory(DocumentEntity document, CaseFileCategory category) return category.getId().equals(document.getCategoryId()); } - private DynamicList folderList(DynamicList existingList) { - DynamicListElement selected = existingList == null ? null : existingList.getValue(); - List folders = List.of(CaseFileCategory.values()).stream() - .sorted(Comparator.comparing(CaseFileCategory::getDisplayOrder)) - .map(category -> new DynamicListElement(folderCode(category), category.getLabel())) - .toList(); - - return new DynamicList(retainSelectedFolder(selected, folders), folders); - } - private DynamicStringListElement retainSelectedValue(DynamicStringListElement selected, List options) { if (selected == null || selected.getCode() == null) { @@ -143,38 +127,15 @@ private DynamicStringListElement retainSelectedValue(DynamicStringListElement se .orElse(null); } - private String selectedFolderId(DocumentAmendDetails details) { - if (details.getSelectedFolder() == null || details.getSelectedFolder().getValue() == null) { - return null; - } - - UUID selectedCode = details.getSelectedFolder().getValue().getCode(); - return List.of(CaseFileCategory.values()).stream() - .filter(category -> folderCode(category).equals(selectedCode)) - .map(CaseFileCategory::getId) - .findFirst() - .orElse(null); + private boolean isEmpty(DynamicStringList documents) { + return documents == null || CollectionUtils.isEmpty(documents.getListItems()); } - private DynamicListElement retainSelectedFolder(DynamicListElement selected, List options) { - if (selected == null || selected.getCode() == null) { + private String buildPartyNamesSummary(PCSCase caseData) { + if (caseData.getClaimantNames() == null || caseData.getDefendantNames() == null) { return null; } - - return options.stream() - .filter(option -> selected.getCode().equals(option.getCode())) - .findFirst() - .orElse(null); - } - - private Optional categoryForId(String id) { - return List.of(CaseFileCategory.values()).stream() - .filter(category -> category.getId().equals(id)) - .findFirst(); - } - - private boolean isEmpty(DynamicStringList documents) { - return documents == null || CollectionUtils.isEmpty(documents.getListItems()); + return caseData.getClaimantNames() + " vs " + caseData.getDefendantNames(); } private DocumentAmendDetails getOrCreateDetails(PCSCase caseData) { diff --git a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java index 195022af82..a01caf7ab8 100644 --- a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java +++ b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java @@ -5,19 +5,19 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import uk.gov.hmcts.ccd.sdk.type.DynamicList; -import uk.gov.hmcts.ccd.sdk.type.DynamicListElement; import uk.gov.hmcts.ccd.sdk.type.YesOrNo; import uk.gov.hmcts.reform.pcs.ccd.domain.CaseFileCategory; import uk.gov.hmcts.reform.pcs.ccd.domain.PCSCase; import uk.gov.hmcts.reform.pcs.ccd.domain.VerticalYesNo; import uk.gov.hmcts.reform.pcs.ccd.domain.documentamend.DocumentAmendDetails; +import uk.gov.hmcts.reform.pcs.ccd.domain.documentamend.DocumentAmendFolder; import uk.gov.hmcts.reform.pcs.ccd.entity.DocumentEntity; import uk.gov.hmcts.reform.pcs.ccd.entity.GenAppEntity; import uk.gov.hmcts.reform.pcs.ccd.entity.PcsCaseEntity; import uk.gov.hmcts.reform.pcs.ccd.service.PcsCaseService; import uk.gov.hmcts.reform.pcs.ccd.type.DynamicStringList; import uk.gov.hmcts.reform.pcs.ccd.type.DynamicStringListElement; +import uk.gov.hmcts.reform.pcs.ccd.util.AddressFormatter; import java.time.Instant; import java.util.List; @@ -41,18 +41,13 @@ class DocumentAmendSelectionServiceTest { @BeforeEach void setUp() { - underTest = new DocumentAmendSelectionService(pcsCaseService); + underTest = new DocumentAmendSelectionService(pcsCaseService, new AddressFormatter()); } @Test - void shouldPopulateFolderDropdownWithCaseFileViewFolders() { - when(pcsCaseService.loadCase(CASE_REFERENCE)).thenReturn(PcsCaseEntity.builder().build()); - PCSCase caseData = PCSCase.builder().build(); - - underTest.initialise(CASE_REFERENCE, caseData); - - assertThat(caseData.getDocumentAmendDetails().getSelectedFolder().getListItems()) - .extracting(DynamicListElement::getLabel) + void shouldDefineFolderDropdownWithCaseFileViewFolders() { + assertThat(DocumentAmendFolder.values()) + .extracting(DocumentAmendFolder::getLabel) .containsExactly( "Statements of case", "Property documents", @@ -66,6 +61,27 @@ void shouldPopulateFolderDropdownWithCaseFileViewFolders() { ); } + @Test + void shouldPopulateCompactCaseSummaryFields() { + when(pcsCaseService.loadCase(CASE_REFERENCE)).thenReturn(PcsCaseEntity.builder().build()); + PCSCase caseData = PCSCase.builder() + .propertyAddress(uk.gov.hmcts.ccd.sdk.type.AddressUK.builder() + .addressLine1("15 Garden Drive") + .postTown("Luton") + .postCode("LU1 1AB") + .build()) + .claimantNames("Treetops Housing") + .defendantNames("Billy Wright") + .build(); + + underTest.initialise(CASE_REFERENCE, caseData); + + assertThat(caseData.getDocumentAmendDetails().getPropertyAddressSummary()) + .isEqualTo("15 Garden Drive, Luton, LU1 1AB"); + assertThat(caseData.getDocumentAmendDetails().getPartyNamesSummary()) + .isEqualTo("Treetops Housing vs Billy Wright"); + } + @Test void shouldPopulateDocumentsForSelectedCategoryAndIncludeWithoutNoticeApplicationDocuments() { DocumentEntity visibleEvidence = document("visible evidence.pdf", EVIDENCE.getId(), null); @@ -175,12 +191,18 @@ void shouldLeaveMissingDocumentSelectionToExuiMandatoryValidation() { assertThat(caseData.getDocumentAmendDetails().getSelectedDocumentId()).isNull(); } - private static DynamicList selectedFolder(CaseFileCategory category) { - DynamicListElement selectedFolder = new DynamicListElement( - DocumentAmendSelectionService.folderCode(category), - category.getLabel() - ); - return new DynamicList(selectedFolder, List.of(selectedFolder)); + private static DocumentAmendFolder selectedFolder(CaseFileCategory category) { + return switch (category) { + case STATEMENTS_OF_CASE -> DocumentAmendFolder.STATEMENTS_OF_CASE; + case PROPERTY_DOCUMENTS -> DocumentAmendFolder.PROPERTY_DOCUMENTS; + case EVIDENCE -> DocumentAmendFolder.EVIDENCE; + case HEARING_DOCUMENTS -> DocumentAmendFolder.HEARING_DOCUMENTS; + case ORDERS_AND_NOTICE_OF_HEARINGS -> DocumentAmendFolder.ORDERS_AND_NOTICE_OF_HEARINGS; + case APPLICATIONS -> DocumentAmendFolder.APPLICATIONS; + case APPEALS -> DocumentAmendFolder.APPEALS; + case CORRESPONDENCE -> DocumentAmendFolder.CORRESPONDENCE; + case UNCATEGORISED_DOCUMENTS -> DocumentAmendFolder.UNCATEGORISED_DOCUMENTS; + }; } private static DynamicStringList selectedDocument(DocumentEntity document) { From 727b6777460cd06f0236a684622e2ae92f5bc0fa Mon Sep 17 00:00:00 2001 From: sadmanrahman Date: Tue, 30 Jun 2026 16:02:51 +0100 Subject: [PATCH 09/70] HDPI-7308: add radiobuttons --- .../documentamend/SelectDocumentPage.java | 17 +---------- .../DocumentAmendSelectionService.java | 16 +++++++--- .../DocumentAmendSelectionServiceTest.java | 29 +++++++++++++++++-- 3 files changed, 39 insertions(+), 23 deletions(-) diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java index 865de3656d..f04e1fb87d 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java @@ -10,7 +10,6 @@ import uk.gov.hmcts.reform.pcs.ccd.domain.PCSCase; import uk.gov.hmcts.reform.pcs.ccd.domain.State; import uk.gov.hmcts.reform.pcs.ccd.domain.documentamend.DocumentAmendDetails; -import uk.gov.hmcts.reform.pcs.ccd.domain.documentamend.DocumentAmendFolder; import uk.gov.hmcts.reform.pcs.ccd.service.document.DocumentAmendSelectionService; import java.util.List; @@ -137,21 +136,7 @@ private String noDocumentsShowCondition(CaseFileCategory category) { } private String selectedFolderCondition(CaseFileCategory category) { - return FIELD_PREFIX + "SelectedFolder=\"" + folderForCategory(category).name() + "\""; - } - - private DocumentAmendFolder folderForCategory(CaseFileCategory category) { - return switch (category) { - case STATEMENTS_OF_CASE -> DocumentAmendFolder.STATEMENTS_OF_CASE; - case PROPERTY_DOCUMENTS -> DocumentAmendFolder.PROPERTY_DOCUMENTS; - case EVIDENCE -> DocumentAmendFolder.EVIDENCE; - case HEARING_DOCUMENTS -> DocumentAmendFolder.HEARING_DOCUMENTS; - case ORDERS_AND_NOTICE_OF_HEARINGS -> DocumentAmendFolder.ORDERS_AND_NOTICE_OF_HEARINGS; - case APPLICATIONS -> DocumentAmendFolder.APPLICATIONS; - case APPEALS -> DocumentAmendFolder.APPEALS; - case CORRESPONDENCE -> DocumentAmendFolder.CORRESPONDENCE; - case UNCATEGORISED_DOCUMENTS -> DocumentAmendFolder.UNCATEGORISED_DOCUMENTS; - }; + return FIELD_PREFIX + "SelectedFolder=\"" + category.getLabel() + "\""; } private String emptyFieldId(CaseFileCategory category) { diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionService.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionService.java index 2ecd234162..1f3835cebe 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionService.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionService.java @@ -8,6 +8,7 @@ import uk.gov.hmcts.reform.pcs.ccd.domain.documentamend.DocumentAmendDetails; import uk.gov.hmcts.reform.pcs.ccd.entity.DocumentEntity; import uk.gov.hmcts.reform.pcs.ccd.entity.PcsCaseEntity; +import uk.gov.hmcts.reform.pcs.ccd.service.CaseNameFormatter; import uk.gov.hmcts.reform.pcs.ccd.service.PcsCaseService; import uk.gov.hmcts.reform.pcs.ccd.type.DynamicStringList; import uk.gov.hmcts.reform.pcs.ccd.type.DynamicStringListElement; @@ -23,16 +24,20 @@ public class DocumentAmendSelectionService { private static final String SELECT_DIFFERENT_FOLDER_ERROR = "Select a different folder to continue"; + private static final String SELECT_DOCUMENT_ERROR = "Select which document you want to amend"; private static final Comparator DOCUMENT_ORDER = Comparator .comparing(DocumentEntity::getSubmittedDate, Comparator.nullsLast(Comparator.reverseOrder())) .thenComparing(DocumentEntity::getFileName, Comparator.nullsLast(String::compareToIgnoreCase)); private final PcsCaseService pcsCaseService; private final AddressFormatter addressFormatter; + private final CaseNameFormatter caseNameFormatter; - public DocumentAmendSelectionService(PcsCaseService pcsCaseService, AddressFormatter addressFormatter) { + public DocumentAmendSelectionService(PcsCaseService pcsCaseService, AddressFormatter addressFormatter, + CaseNameFormatter caseNameFormatter) { this.pcsCaseService = pcsCaseService; this.addressFormatter = addressFormatter; + this.caseNameFormatter = caseNameFormatter; } public void initialise(long caseReference, PCSCase caseData) { @@ -74,7 +79,7 @@ public List validateAndStoreSelection(PCSCase caseData) { if (selectedDocument == null || selectedDocument.getCode() == null) { details.setSelectedDocumentId(null); details.setSelectedDocumentFileName(null); - return List.of(); + return List.of(SELECT_DOCUMENT_ERROR); } details.setSelectedDocumentId(selectedDocument.getCode()); @@ -132,10 +137,13 @@ private boolean isEmpty(DynamicStringList documents) { } private String buildPartyNamesSummary(PCSCase caseData) { - if (caseData.getClaimantNames() == null || caseData.getDefendantNames() == null) { + if (caseData.getClaimantNames() != null && caseData.getDefendantNames() != null) { + return caseData.getClaimantNames() + " vs " + caseData.getDefendantNames(); + } + if (CollectionUtils.isEmpty(caseData.getAllClaimants()) && CollectionUtils.isEmpty(caseData.getAllDefendants())) { return null; } - return caseData.getClaimantNames() + " vs " + caseData.getDefendantNames(); + return caseNameFormatter.formatCaseName(caseData); } private DocumentAmendDetails getOrCreateDetails(PCSCase caseData) { diff --git a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java index a01caf7ab8..9238c7e534 100644 --- a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java +++ b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java @@ -8,12 +8,14 @@ import uk.gov.hmcts.ccd.sdk.type.YesOrNo; import uk.gov.hmcts.reform.pcs.ccd.domain.CaseFileCategory; import uk.gov.hmcts.reform.pcs.ccd.domain.PCSCase; +import uk.gov.hmcts.reform.pcs.ccd.domain.Party; import uk.gov.hmcts.reform.pcs.ccd.domain.VerticalYesNo; import uk.gov.hmcts.reform.pcs.ccd.domain.documentamend.DocumentAmendDetails; import uk.gov.hmcts.reform.pcs.ccd.domain.documentamend.DocumentAmendFolder; import uk.gov.hmcts.reform.pcs.ccd.entity.DocumentEntity; import uk.gov.hmcts.reform.pcs.ccd.entity.GenAppEntity; import uk.gov.hmcts.reform.pcs.ccd.entity.PcsCaseEntity; +import uk.gov.hmcts.reform.pcs.ccd.service.CaseNameFormatter; import uk.gov.hmcts.reform.pcs.ccd.service.PcsCaseService; import uk.gov.hmcts.reform.pcs.ccd.type.DynamicStringList; import uk.gov.hmcts.reform.pcs.ccd.type.DynamicStringListElement; @@ -28,6 +30,7 @@ import static uk.gov.hmcts.reform.pcs.ccd.domain.CaseFileCategory.APPLICATIONS; import static uk.gov.hmcts.reform.pcs.ccd.domain.CaseFileCategory.EVIDENCE; import static uk.gov.hmcts.reform.pcs.ccd.domain.CaseFileCategory.UNCATEGORISED_DOCUMENTS; +import static uk.gov.hmcts.reform.pcs.ccd.util.ListValueUtils.wrapListItems; @ExtendWith(MockitoExtension.class) class DocumentAmendSelectionServiceTest { @@ -41,7 +44,7 @@ class DocumentAmendSelectionServiceTest { @BeforeEach void setUp() { - underTest = new DocumentAmendSelectionService(pcsCaseService, new AddressFormatter()); + underTest = new DocumentAmendSelectionService(pcsCaseService, new AddressFormatter(), new CaseNameFormatter()); } @Test @@ -82,6 +85,26 @@ void shouldPopulateCompactCaseSummaryFields() { .isEqualTo("Treetops Housing vs Billy Wright"); } + @Test + void shouldPopulatePartyNamesSummaryFromPartyCollectionsWhenSummaryFieldsAreMissing() { + when(pcsCaseService.loadCase(CASE_REFERENCE)).thenReturn(PcsCaseEntity.builder().build()); + PCSCase caseData = PCSCase.builder() + .allClaimants(wrapListItems(List.of(Party.builder() + .orgName("Treetops Housing") + .build()))) + .allDefendants(wrapListItems(List.of(Party.builder() + .firstName("Billy") + .lastName("Wright") + .nameKnown(VerticalYesNo.YES) + .build()))) + .build(); + + underTest.initialise(CASE_REFERENCE, caseData); + + assertThat(caseData.getDocumentAmendDetails().getPartyNamesSummary()) + .isEqualTo("Treetops Housing vs Billy Wright"); + } + @Test void shouldPopulateDocumentsForSelectedCategoryAndIncludeWithoutNoticeApplicationDocuments() { DocumentEntity visibleEvidence = document("visible evidence.pdf", EVIDENCE.getId(), null); @@ -173,7 +196,7 @@ void shouldPersistSelectedFolderAndDocumentDetails() { } @Test - void shouldLeaveMissingDocumentSelectionToExuiMandatoryValidation() { + void shouldReturnErrorWhenSelectedFolderHasDocumentsButNoDocumentSelected() { DocumentEntity document = document("photo.pdf", EVIDENCE.getId(), null); when(pcsCaseService.loadCase(CASE_REFERENCE)).thenReturn(PcsCaseEntity.builder() .documents(List.of(document)) @@ -187,7 +210,7 @@ void shouldLeaveMissingDocumentSelectionToExuiMandatoryValidation() { List errors = underTest.validateAndStoreSelection(caseData); - assertThat(errors).isEmpty(); + assertThat(errors).containsExactly("Select which document you want to amend"); assertThat(caseData.getDocumentAmendDetails().getSelectedDocumentId()).isNull(); } From f49a099eaaf5ce08c8f14ff47535bad4a4ac589a Mon Sep 17 00:00:00 2001 From: sadmanrahman Date: Tue, 30 Jun 2026 16:12:10 +0100 Subject: [PATCH 10/70] HDPI-7308: checkstyle fix --- .../ccd/service/document/DocumentAmendSelectionService.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionService.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionService.java index 1f3835cebe..962c656f0a 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionService.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionService.java @@ -140,7 +140,8 @@ private String buildPartyNamesSummary(PCSCase caseData) { if (caseData.getClaimantNames() != null && caseData.getDefendantNames() != null) { return caseData.getClaimantNames() + " vs " + caseData.getDefendantNames(); } - if (CollectionUtils.isEmpty(caseData.getAllClaimants()) && CollectionUtils.isEmpty(caseData.getAllDefendants())) { + if (CollectionUtils.isEmpty(caseData.getAllClaimants()) + && CollectionUtils.isEmpty(caseData.getAllDefendants())) { return null; } return caseNameFormatter.formatCaseName(caseData); From 01dd3b619e34560fc535f0812dc82471a343eb61 Mon Sep 17 00:00:00 2001 From: sadmanrahman Date: Tue, 30 Jun 2026 16:52:26 +0100 Subject: [PATCH 11/70] HDPI-7308: radiobutton fix --- .../pcs/ccd/page/documentamend/SelectDocumentPage.java | 6 +++--- .../ccd/service/document/DocumentAmendSelectionService.java | 3 +-- .../service/document/DocumentAmendSelectionServiceTest.java | 4 ++-- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java index f04e1fb87d..1b794fad96 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java @@ -23,7 +23,6 @@ public class SelectDocumentPage implements CcdPageConfiguration { private static final String PAGE_ID = "selectDocument"; private static final String FIELD_PREFIX = "documentAmend_"; private static final String YES = "=\"Yes\""; - private static final String NO = "=\"No\""; private final DocumentAmendSelectionService documentAmendSelectionService; @@ -128,7 +127,7 @@ private AboutToStartOrSubmitResponse midEvent(CaseDetails DOCUMENT_ORDER = Comparator .comparing(DocumentEntity::getSubmittedDate, Comparator.nullsLast(Comparator.reverseOrder())) .thenComparing(DocumentEntity::getFileName, Comparator.nullsLast(String::compareToIgnoreCase)); @@ -79,7 +78,7 @@ public List validateAndStoreSelection(PCSCase caseData) { if (selectedDocument == null || selectedDocument.getCode() == null) { details.setSelectedDocumentId(null); details.setSelectedDocumentFileName(null); - return List.of(SELECT_DOCUMENT_ERROR); + return List.of(); } details.setSelectedDocumentId(selectedDocument.getCode()); diff --git a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java index 9238c7e534..4634d135ee 100644 --- a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java +++ b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java @@ -196,7 +196,7 @@ void shouldPersistSelectedFolderAndDocumentDetails() { } @Test - void shouldReturnErrorWhenSelectedFolderHasDocumentsButNoDocumentSelected() { + void shouldLeaveMissingDocumentSelectionToExuiMandatoryValidation() { DocumentEntity document = document("photo.pdf", EVIDENCE.getId(), null); when(pcsCaseService.loadCase(CASE_REFERENCE)).thenReturn(PcsCaseEntity.builder() .documents(List.of(document)) @@ -210,7 +210,7 @@ void shouldReturnErrorWhenSelectedFolderHasDocumentsButNoDocumentSelected() { List errors = underTest.validateAndStoreSelection(caseData); - assertThat(errors).containsExactly("Select which document you want to amend"); + assertThat(errors).isEmpty(); assertThat(caseData.getDocumentAmendDetails().getSelectedDocumentId()).isNull(); } From 040d6428fda22d98a2426b588bb416b14f30d116 Mon Sep 17 00:00:00 2001 From: sadmanrahman Date: Tue, 30 Jun 2026 17:23:14 +0100 Subject: [PATCH 12/70] HDPI-7308: radiobutton fix --- .../reform/pcs/ccd/page/documentamend/SelectDocumentPage.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java index 1b794fad96..9a78373b73 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java @@ -135,8 +135,7 @@ private String noDocumentsShowCondition(CaseFileCategory category) { } private String selectedFolderCondition(CaseFileCategory category) { - return "(" + FIELD_PREFIX + "SelectedFolder=\"" + category.getLabel() + "\"" - + " OR " + FIELD_PREFIX + "SelectedFolder=\"" + category.name() + "\")"; + return FIELD_PREFIX + "SelectedFolder=\"" + category.name() + "\""; } private String emptyFieldId(CaseFileCategory category) { From 6047d0fd5c2f8a5bd67dcca66378704c4db3183e Mon Sep 17 00:00:00 2001 From: sadmanrahman Date: Wed, 1 Jul 2026 09:44:50 +0100 Subject: [PATCH 13/70] HDPI-7308: radiobutton fix --- .../documentamend/DocumentAmendDetails.java | 27 ++++++++++++ .../documentamend/SelectDocumentPage.java | 28 ++++++++++++- .../DocumentAmendSelectionService.java | 27 ++++++++++++ .../DocumentAmendSelectionServiceTest.java | 42 +++++++++++++++++++ 4 files changed, 122 insertions(+), 2 deletions(-) diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendDetails.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendDetails.java index c14b3e21a0..948dd57f19 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendDetails.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendDetails.java @@ -124,6 +124,33 @@ public class DocumentAmendDetails { @CCD(searchable = false) private YesOrNo uncategorisedDocumentsEmpty; + @CCD(searchable = false) + private YesOrNo showStatementsOfCase; + + @CCD(searchable = false) + private YesOrNo showPropertyDocuments; + + @CCD(searchable = false) + private YesOrNo showEvidence; + + @CCD(searchable = false) + private YesOrNo showHearingDocuments; + + @CCD(searchable = false) + private YesOrNo showOrdersAndNoticeOfHearings; + + @CCD(searchable = false) + private YesOrNo showApplications; + + @CCD(searchable = false) + private YesOrNo showAppeals; + + @CCD(searchable = false) + private YesOrNo showCorrespondence; + + @CCD(searchable = false) + private YesOrNo showUncategorisedDocuments; + @CCD(searchable = false) private String selectedFolderId; diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java index 9a78373b73..ce799814f6 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java @@ -23,6 +23,7 @@ public class SelectDocumentPage implements CcdPageConfiguration { private static final String PAGE_ID = "selectDocument"; private static final String FIELD_PREFIX = "documentAmend_"; private static final String YES = "=\"Yes\""; + private static final String NO = "=\"No\""; private final DocumentAmendSelectionService documentAmendSelectionService; @@ -106,6 +107,15 @@ public void addTo(PageBuilder pageBuilder) { .readonly(DocumentAmendDetails::getAppealsEmpty, NEVER_SHOW, true) .readonly(DocumentAmendDetails::getCorrespondenceEmpty, NEVER_SHOW, true) .readonly(DocumentAmendDetails::getUncategorisedDocumentsEmpty, NEVER_SHOW, true) + .readonly(DocumentAmendDetails::getShowStatementsOfCase, NEVER_SHOW, true) + .readonly(DocumentAmendDetails::getShowPropertyDocuments, NEVER_SHOW, true) + .readonly(DocumentAmendDetails::getShowEvidence, NEVER_SHOW, true) + .readonly(DocumentAmendDetails::getShowHearingDocuments, NEVER_SHOW, true) + .readonly(DocumentAmendDetails::getShowOrdersAndNoticeOfHearings, NEVER_SHOW, true) + .readonly(DocumentAmendDetails::getShowApplications, NEVER_SHOW, true) + .readonly(DocumentAmendDetails::getShowAppeals, NEVER_SHOW, true) + .readonly(DocumentAmendDetails::getShowCorrespondence, NEVER_SHOW, true) + .readonly(DocumentAmendDetails::getShowUncategorisedDocuments, NEVER_SHOW, true) .readonly(DocumentAmendDetails::getSelectedFolderId, NEVER_SHOW, true) .readonly(DocumentAmendDetails::getSelectedFolderLabel, NEVER_SHOW, true) .readonly(DocumentAmendDetails::getSelectedDocumentId, NEVER_SHOW, true) @@ -127,7 +137,7 @@ private AboutToStartOrSubmitResponse midEvent(CaseDetails FIELD_PREFIX + "ShowStatementsOfCase"; + case PROPERTY_DOCUMENTS -> FIELD_PREFIX + "ShowPropertyDocuments"; + case EVIDENCE -> FIELD_PREFIX + "ShowEvidence"; + case HEARING_DOCUMENTS -> FIELD_PREFIX + "ShowHearingDocuments"; + case ORDERS_AND_NOTICE_OF_HEARINGS -> FIELD_PREFIX + "ShowOrdersAndNoticeOfHearings"; + case APPLICATIONS -> FIELD_PREFIX + "ShowApplications"; + case APPEALS -> FIELD_PREFIX + "ShowAppeals"; + case CORRESPONDENCE -> FIELD_PREFIX + "ShowCorrespondence"; + case UNCATEGORISED_DOCUMENTS -> FIELD_PREFIX + "ShowUncategorisedDocuments"; + }; + } + private String noDocumentsMessage(CaseFileCategory category) { return "No documents in '" + category.getLabel() + "'"; } diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionService.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionService.java index f0d3e6d7ff..106c3b4981 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionService.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionService.java @@ -55,6 +55,7 @@ public void initialise(long caseReference, PCSCase caseData) { setDocumentsForCategory(details, pcsCase, CaseFileCategory.APPEALS); setDocumentsForCategory(details, pcsCase, CaseFileCategory.CORRESPONDENCE); setDocumentsForCategory(details, pcsCase, CaseFileCategory.UNCATEGORISED_DOCUMENTS); + setSelectedFolderDisplayFlags(details); } public List validateAndStoreSelection(PCSCase caseData) { @@ -195,4 +196,30 @@ private void setEmptyForCategory(DocumentAmendDetails details, CaseFileCategory case UNCATEGORISED_DOCUMENTS -> details.setUncategorisedDocumentsEmpty(empty); } } + + private void setSelectedFolderDisplayFlags(DocumentAmendDetails details) { + CaseFileCategory selectedCategory = details.getSelectedFolder() == null + ? null + : details.getSelectedFolder().getCategory(); + + details.setShowStatementsOfCase(showSelectedFolder(selectedCategory, CaseFileCategory.STATEMENTS_OF_CASE)); + details.setShowPropertyDocuments(showSelectedFolder(selectedCategory, CaseFileCategory.PROPERTY_DOCUMENTS)); + details.setShowEvidence(showSelectedFolder(selectedCategory, CaseFileCategory.EVIDENCE)); + details.setShowHearingDocuments(showSelectedFolder(selectedCategory, CaseFileCategory.HEARING_DOCUMENTS)); + details.setShowOrdersAndNoticeOfHearings(showSelectedFolder( + selectedCategory, + CaseFileCategory.ORDERS_AND_NOTICE_OF_HEARINGS + )); + details.setShowApplications(showSelectedFolder(selectedCategory, CaseFileCategory.APPLICATIONS)); + details.setShowAppeals(showSelectedFolder(selectedCategory, CaseFileCategory.APPEALS)); + details.setShowCorrespondence(showSelectedFolder(selectedCategory, CaseFileCategory.CORRESPONDENCE)); + details.setShowUncategorisedDocuments(showSelectedFolder( + selectedCategory, + CaseFileCategory.UNCATEGORISED_DOCUMENTS + )); + } + + private YesOrNo showSelectedFolder(CaseFileCategory selectedCategory, CaseFileCategory category) { + return YesOrNo.from(category == selectedCategory); + } } diff --git a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java index 4634d135ee..df6d362956 100644 --- a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java +++ b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java @@ -135,6 +135,48 @@ void shouldPopulateDocumentsForSelectedCategoryAndIncludeWithoutNoticeApplicatio .containsExactly("visible application.pdf", "without notice application.pdf"); } + @Test + void shouldSetOnlySelectedFolderDisplayFlag() { + when(pcsCaseService.loadCase(CASE_REFERENCE)).thenReturn(PcsCaseEntity.builder().build()); + PCSCase caseData = PCSCase.builder() + .documentAmendDetails(DocumentAmendDetails.builder() + .selectedFolder(selectedFolder(APPLICATIONS)) + .build()) + .build(); + + underTest.initialise(CASE_REFERENCE, caseData); + + DocumentAmendDetails details = caseData.getDocumentAmendDetails(); + assertThat(details.getShowApplications()).isEqualTo(YesOrNo.YES); + assertThat(details.getShowStatementsOfCase()).isEqualTo(YesOrNo.NO); + assertThat(details.getShowPropertyDocuments()).isEqualTo(YesOrNo.NO); + assertThat(details.getShowEvidence()).isEqualTo(YesOrNo.NO); + assertThat(details.getShowHearingDocuments()).isEqualTo(YesOrNo.NO); + assertThat(details.getShowOrdersAndNoticeOfHearings()).isEqualTo(YesOrNo.NO); + assertThat(details.getShowAppeals()).isEqualTo(YesOrNo.NO); + assertThat(details.getShowCorrespondence()).isEqualTo(YesOrNo.NO); + assertThat(details.getShowUncategorisedDocuments()).isEqualTo(YesOrNo.NO); + } + + @Test + void shouldClearFolderDisplayFlagsWhenNoFolderSelected() { + when(pcsCaseService.loadCase(CASE_REFERENCE)).thenReturn(PcsCaseEntity.builder().build()); + PCSCase caseData = PCSCase.builder().build(); + + underTest.initialise(CASE_REFERENCE, caseData); + + DocumentAmendDetails details = caseData.getDocumentAmendDetails(); + assertThat(details.getShowStatementsOfCase()).isEqualTo(YesOrNo.NO); + assertThat(details.getShowPropertyDocuments()).isEqualTo(YesOrNo.NO); + assertThat(details.getShowEvidence()).isEqualTo(YesOrNo.NO); + assertThat(details.getShowHearingDocuments()).isEqualTo(YesOrNo.NO); + assertThat(details.getShowOrdersAndNoticeOfHearings()).isEqualTo(YesOrNo.NO); + assertThat(details.getShowApplications()).isEqualTo(YesOrNo.NO); + assertThat(details.getShowAppeals()).isEqualTo(YesOrNo.NO); + assertThat(details.getShowCorrespondence()).isEqualTo(YesOrNo.NO); + assertThat(details.getShowUncategorisedDocuments()).isEqualTo(YesOrNo.NO); + } + @Test void shouldOnlyShowDocumentsWithUncategorisedCategoryUnderUncategorisedDocuments() { DocumentEntity uncategorisedDocument = document("loose document.pdf", null, null); From af434162da1a63c3c80497f1df66d33b7f5efc14 Mon Sep 17 00:00:00 2001 From: sadmanrahman Date: Wed, 1 Jul 2026 10:32:26 +0100 Subject: [PATCH 14/70] HDPI-7308: radiobutton fix 2 --- .../documentamend/DocumentAmendDetails.java | 2 + .../documentamend/DocumentAmendFolder.java | 16 ++++++++ .../DocumentAmendFolderDeserializer.java | 39 ++++++++++++++++++ .../DocumentAmendFolderTest.java | 41 +++++++++++++++++++ 4 files changed, 98 insertions(+) create mode 100644 src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendFolderDeserializer.java create mode 100644 src/test/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendFolderTest.java diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendDetails.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendDetails.java index 948dd57f19..86672fe36a 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendDetails.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendDetails.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -26,6 +27,7 @@ public class DocumentAmendDetails { typeOverride = FixedList, typeParameterOverride = "DocumentAmendFolder" ) + @JsonDeserialize(using = DocumentAmendFolderDeserializer.class) private DocumentAmendFolder selectedFolder; @CCD(searchable = false) diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendFolder.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendFolder.java index 073c023397..452358921b 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendFolder.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendFolder.java @@ -24,4 +24,20 @@ public enum DocumentAmendFolder implements HasLabel { this.category = category; this.label = category.getLabel(); } + + public static DocumentAmendFolder from(String value) { + if (value == null) { + return null; + } + + for (DocumentAmendFolder folder : values()) { + if (folder.name().equals(value) + || folder.getLabel().equals(value) + || folder.getCategory().getId().equals(value)) { + return folder; + } + } + + return null; + } } diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendFolderDeserializer.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendFolderDeserializer.java new file mode 100644 index 0000000000..b548c2ebf5 --- /dev/null +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendFolderDeserializer.java @@ -0,0 +1,39 @@ +package uk.gov.hmcts.reform.pcs.ccd.domain.documentamend; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; + +import java.io.IOException; + +public class DocumentAmendFolderDeserializer extends JsonDeserializer { + + @Override + public DocumentAmendFolder deserialize(JsonParser parser, DeserializationContext context) throws IOException { + JsonNode node = parser.getCodec().readTree(parser); + return DocumentAmendFolder.from(folderValue(node)); + } + + private String folderValue(JsonNode node) { + if (node == null || node.isNull()) { + return null; + } + if (node.isTextual()) { + return node.asText(); + } + + JsonNode value = node.get("value"); + if (value != null) { + return folderValue(value); + } + + JsonNode code = node.get("code"); + if (code != null) { + return code.asText(); + } + + JsonNode label = node.get("label"); + return label == null ? null : label.asText(); + } +} diff --git a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendFolderTest.java b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendFolderTest.java new file mode 100644 index 0000000000..bf94a77c57 --- /dev/null +++ b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendFolderTest.java @@ -0,0 +1,41 @@ +package uk.gov.hmcts.reform.pcs.ccd.domain.documentamend; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class DocumentAmendFolderTest { + + private final ObjectMapper objectMapper = new ObjectMapper(); + + @Test + void shouldResolveFolderFromCodeLabelOrCategoryId() { + assertThat(DocumentAmendFolder.from("PROPERTY_DOCUMENTS")) + .isEqualTo(DocumentAmendFolder.PROPERTY_DOCUMENTS); + assertThat(DocumentAmendFolder.from("Property documents")) + .isEqualTo(DocumentAmendFolder.PROPERTY_DOCUMENTS); + assertThat(DocumentAmendFolder.from("propertyDocuments")) + .isEqualTo(DocumentAmendFolder.PROPERTY_DOCUMENTS); + } + + @Test + void shouldDeserializeFolderFromFixedListCode() throws Exception { + DocumentAmendDetails details = objectMapper.readValue( + "{\"selectedFolder\":\"PROPERTY_DOCUMENTS\"}", + DocumentAmendDetails.class + ); + + assertThat(details.getSelectedFolder()).isEqualTo(DocumentAmendFolder.PROPERTY_DOCUMENTS); + } + + @Test + void shouldDeserializeFolderFromFixedListObject() throws Exception { + DocumentAmendDetails details = objectMapper.readValue( + "{\"selectedFolder\":{\"value\":{\"code\":\"PROPERTY_DOCUMENTS\",\"label\":\"Property documents\"}}}", + DocumentAmendDetails.class + ); + + assertThat(details.getSelectedFolder()).isEqualTo(DocumentAmendFolder.PROPERTY_DOCUMENTS); + } +} From e6f054b221cd3618949772edc4050a20afad3faf Mon Sep 17 00:00:00 2001 From: sadmanrahman Date: Wed, 1 Jul 2026 11:03:14 +0100 Subject: [PATCH 15/70] HDPI-7308: radiobutton fix 3 --- .../documentamend/DocumentAmendDetails.java | 27 ------------ .../documentamend/SelectDocumentPage.java | 43 +++++-------------- .../DocumentAmendSelectionService.java | 26 ----------- .../DocumentAmendSelectionServiceTest.java | 42 ------------------ 4 files changed, 10 insertions(+), 128 deletions(-) diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendDetails.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendDetails.java index 86672fe36a..71c0a4c05c 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendDetails.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendDetails.java @@ -126,33 +126,6 @@ public class DocumentAmendDetails { @CCD(searchable = false) private YesOrNo uncategorisedDocumentsEmpty; - @CCD(searchable = false) - private YesOrNo showStatementsOfCase; - - @CCD(searchable = false) - private YesOrNo showPropertyDocuments; - - @CCD(searchable = false) - private YesOrNo showEvidence; - - @CCD(searchable = false) - private YesOrNo showHearingDocuments; - - @CCD(searchable = false) - private YesOrNo showOrdersAndNoticeOfHearings; - - @CCD(searchable = false) - private YesOrNo showApplications; - - @CCD(searchable = false) - private YesOrNo showAppeals; - - @CCD(searchable = false) - private YesOrNo showCorrespondence; - - @CCD(searchable = false) - private YesOrNo showUncategorisedDocuments; - @CCD(searchable = false) private String selectedFolderId; diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java index ce799814f6..adf4858325 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java @@ -43,56 +43,56 @@ public void addTo(PageBuilder pageBuilder) { .readonly(DocumentAmendDetails::getPartyNamesSummary, NEVER_SHOW, true) .mandatory(DocumentAmendDetails::getSelectedFolder) .mandatory(DocumentAmendDetails::getStatementsOfCaseDocuments, - documentsShowCondition(CaseFileCategory.STATEMENTS_OF_CASE)) + documentsShowCondition(CaseFileCategory.STATEMENTS_OF_CASE), true) .label("statementsOfCaseNoDocumentsQuestion", "Which document do you want to amend?", noDocumentsShowCondition(CaseFileCategory.STATEMENTS_OF_CASE)) .label("statementsOfCaseNoDocuments", noDocumentsMessage(CaseFileCategory.STATEMENTS_OF_CASE), noDocumentsShowCondition(CaseFileCategory.STATEMENTS_OF_CASE)) .mandatory(DocumentAmendDetails::getPropertyDocuments, - documentsShowCondition(CaseFileCategory.PROPERTY_DOCUMENTS)) + documentsShowCondition(CaseFileCategory.PROPERTY_DOCUMENTS), true) .label("propertyDocumentsNoDocumentsQuestion", "Which document do you want to amend?", noDocumentsShowCondition(CaseFileCategory.PROPERTY_DOCUMENTS)) .label("propertyDocumentsNoDocuments", noDocumentsMessage(CaseFileCategory.PROPERTY_DOCUMENTS), noDocumentsShowCondition(CaseFileCategory.PROPERTY_DOCUMENTS)) .mandatory(DocumentAmendDetails::getEvidenceDocuments, - documentsShowCondition(CaseFileCategory.EVIDENCE)) + documentsShowCondition(CaseFileCategory.EVIDENCE), true) .label("evidenceNoDocumentsQuestion", "Which document do you want to amend?", noDocumentsShowCondition(CaseFileCategory.EVIDENCE)) .label("evidenceNoDocuments", noDocumentsMessage(CaseFileCategory.EVIDENCE), noDocumentsShowCondition(CaseFileCategory.EVIDENCE)) .mandatory(DocumentAmendDetails::getHearingDocuments, - documentsShowCondition(CaseFileCategory.HEARING_DOCUMENTS)) + documentsShowCondition(CaseFileCategory.HEARING_DOCUMENTS), true) .label("hearingDocumentsNoDocumentsQuestion", "Which document do you want to amend?", noDocumentsShowCondition(CaseFileCategory.HEARING_DOCUMENTS)) .label("hearingDocumentsNoDocuments", noDocumentsMessage(CaseFileCategory.HEARING_DOCUMENTS), noDocumentsShowCondition(CaseFileCategory.HEARING_DOCUMENTS)) .mandatory(DocumentAmendDetails::getOrdersAndNoticeOfHearingsDocuments, - documentsShowCondition(CaseFileCategory.ORDERS_AND_NOTICE_OF_HEARINGS)) + documentsShowCondition(CaseFileCategory.ORDERS_AND_NOTICE_OF_HEARINGS), true) .label("ordersAndNoticeOfHearingsNoDocumentsQuestion", "Which document do you want to amend?", noDocumentsShowCondition(CaseFileCategory.ORDERS_AND_NOTICE_OF_HEARINGS)) .label("ordersAndNoticeOfHearingsNoDocuments", noDocumentsMessage(CaseFileCategory.ORDERS_AND_NOTICE_OF_HEARINGS), noDocumentsShowCondition(CaseFileCategory.ORDERS_AND_NOTICE_OF_HEARINGS)) .mandatory(DocumentAmendDetails::getApplicationsDocuments, - documentsShowCondition(CaseFileCategory.APPLICATIONS)) + documentsShowCondition(CaseFileCategory.APPLICATIONS), true) .label("applicationsNoDocumentsQuestion", "Which document do you want to amend?", noDocumentsShowCondition(CaseFileCategory.APPLICATIONS)) .label("applicationsNoDocuments", noDocumentsMessage(CaseFileCategory.APPLICATIONS), noDocumentsShowCondition(CaseFileCategory.APPLICATIONS)) .mandatory(DocumentAmendDetails::getAppealsDocuments, - documentsShowCondition(CaseFileCategory.APPEALS)) + documentsShowCondition(CaseFileCategory.APPEALS), true) .label("appealsNoDocumentsQuestion", "Which document do you want to amend?", noDocumentsShowCondition(CaseFileCategory.APPEALS)) .label("appealsNoDocuments", noDocumentsMessage(CaseFileCategory.APPEALS), noDocumentsShowCondition(CaseFileCategory.APPEALS)) .mandatory(DocumentAmendDetails::getCorrespondenceDocuments, - documentsShowCondition(CaseFileCategory.CORRESPONDENCE)) + documentsShowCondition(CaseFileCategory.CORRESPONDENCE), true) .label("correspondenceNoDocumentsQuestion", "Which document do you want to amend?", noDocumentsShowCondition(CaseFileCategory.CORRESPONDENCE)) .label("correspondenceNoDocuments", noDocumentsMessage(CaseFileCategory.CORRESPONDENCE), noDocumentsShowCondition(CaseFileCategory.CORRESPONDENCE)) .mandatory(DocumentAmendDetails::getUncategorisedDocuments, - documentsShowCondition(CaseFileCategory.UNCATEGORISED_DOCUMENTS)) + documentsShowCondition(CaseFileCategory.UNCATEGORISED_DOCUMENTS), true) .label("uncategorisedDocumentsNoDocumentsQuestion", "Which document do you want to amend?", noDocumentsShowCondition(CaseFileCategory.UNCATEGORISED_DOCUMENTS)) .label("uncategorisedDocumentsNoDocuments", @@ -107,15 +107,6 @@ public void addTo(PageBuilder pageBuilder) { .readonly(DocumentAmendDetails::getAppealsEmpty, NEVER_SHOW, true) .readonly(DocumentAmendDetails::getCorrespondenceEmpty, NEVER_SHOW, true) .readonly(DocumentAmendDetails::getUncategorisedDocumentsEmpty, NEVER_SHOW, true) - .readonly(DocumentAmendDetails::getShowStatementsOfCase, NEVER_SHOW, true) - .readonly(DocumentAmendDetails::getShowPropertyDocuments, NEVER_SHOW, true) - .readonly(DocumentAmendDetails::getShowEvidence, NEVER_SHOW, true) - .readonly(DocumentAmendDetails::getShowHearingDocuments, NEVER_SHOW, true) - .readonly(DocumentAmendDetails::getShowOrdersAndNoticeOfHearings, NEVER_SHOW, true) - .readonly(DocumentAmendDetails::getShowApplications, NEVER_SHOW, true) - .readonly(DocumentAmendDetails::getShowAppeals, NEVER_SHOW, true) - .readonly(DocumentAmendDetails::getShowCorrespondence, NEVER_SHOW, true) - .readonly(DocumentAmendDetails::getShowUncategorisedDocuments, NEVER_SHOW, true) .readonly(DocumentAmendDetails::getSelectedFolderId, NEVER_SHOW, true) .readonly(DocumentAmendDetails::getSelectedFolderLabel, NEVER_SHOW, true) .readonly(DocumentAmendDetails::getSelectedDocumentId, NEVER_SHOW, true) @@ -145,7 +136,7 @@ private String noDocumentsShowCondition(CaseFileCategory category) { } private String selectedFolderCondition(CaseFileCategory category) { - return showFieldId(category) + YES; + return FIELD_PREFIX + "SelectedFolder=\"" + category.name() + "\""; } private String emptyFieldId(CaseFileCategory category) { @@ -162,20 +153,6 @@ private String emptyFieldId(CaseFileCategory category) { }; } - private String showFieldId(CaseFileCategory category) { - return switch (category) { - case STATEMENTS_OF_CASE -> FIELD_PREFIX + "ShowStatementsOfCase"; - case PROPERTY_DOCUMENTS -> FIELD_PREFIX + "ShowPropertyDocuments"; - case EVIDENCE -> FIELD_PREFIX + "ShowEvidence"; - case HEARING_DOCUMENTS -> FIELD_PREFIX + "ShowHearingDocuments"; - case ORDERS_AND_NOTICE_OF_HEARINGS -> FIELD_PREFIX + "ShowOrdersAndNoticeOfHearings"; - case APPLICATIONS -> FIELD_PREFIX + "ShowApplications"; - case APPEALS -> FIELD_PREFIX + "ShowAppeals"; - case CORRESPONDENCE -> FIELD_PREFIX + "ShowCorrespondence"; - case UNCATEGORISED_DOCUMENTS -> FIELD_PREFIX + "ShowUncategorisedDocuments"; - }; - } - private String noDocumentsMessage(CaseFileCategory category) { return "No documents in '" + category.getLabel() + "'"; } diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionService.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionService.java index 106c3b4981..74c3cf0851 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionService.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionService.java @@ -55,7 +55,6 @@ public void initialise(long caseReference, PCSCase caseData) { setDocumentsForCategory(details, pcsCase, CaseFileCategory.APPEALS); setDocumentsForCategory(details, pcsCase, CaseFileCategory.CORRESPONDENCE); setDocumentsForCategory(details, pcsCase, CaseFileCategory.UNCATEGORISED_DOCUMENTS); - setSelectedFolderDisplayFlags(details); } public List validateAndStoreSelection(PCSCase caseData) { @@ -197,29 +196,4 @@ private void setEmptyForCategory(DocumentAmendDetails details, CaseFileCategory } } - private void setSelectedFolderDisplayFlags(DocumentAmendDetails details) { - CaseFileCategory selectedCategory = details.getSelectedFolder() == null - ? null - : details.getSelectedFolder().getCategory(); - - details.setShowStatementsOfCase(showSelectedFolder(selectedCategory, CaseFileCategory.STATEMENTS_OF_CASE)); - details.setShowPropertyDocuments(showSelectedFolder(selectedCategory, CaseFileCategory.PROPERTY_DOCUMENTS)); - details.setShowEvidence(showSelectedFolder(selectedCategory, CaseFileCategory.EVIDENCE)); - details.setShowHearingDocuments(showSelectedFolder(selectedCategory, CaseFileCategory.HEARING_DOCUMENTS)); - details.setShowOrdersAndNoticeOfHearings(showSelectedFolder( - selectedCategory, - CaseFileCategory.ORDERS_AND_NOTICE_OF_HEARINGS - )); - details.setShowApplications(showSelectedFolder(selectedCategory, CaseFileCategory.APPLICATIONS)); - details.setShowAppeals(showSelectedFolder(selectedCategory, CaseFileCategory.APPEALS)); - details.setShowCorrespondence(showSelectedFolder(selectedCategory, CaseFileCategory.CORRESPONDENCE)); - details.setShowUncategorisedDocuments(showSelectedFolder( - selectedCategory, - CaseFileCategory.UNCATEGORISED_DOCUMENTS - )); - } - - private YesOrNo showSelectedFolder(CaseFileCategory selectedCategory, CaseFileCategory category) { - return YesOrNo.from(category == selectedCategory); - } } diff --git a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java index df6d362956..4634d135ee 100644 --- a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java +++ b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java @@ -135,48 +135,6 @@ void shouldPopulateDocumentsForSelectedCategoryAndIncludeWithoutNoticeApplicatio .containsExactly("visible application.pdf", "without notice application.pdf"); } - @Test - void shouldSetOnlySelectedFolderDisplayFlag() { - when(pcsCaseService.loadCase(CASE_REFERENCE)).thenReturn(PcsCaseEntity.builder().build()); - PCSCase caseData = PCSCase.builder() - .documentAmendDetails(DocumentAmendDetails.builder() - .selectedFolder(selectedFolder(APPLICATIONS)) - .build()) - .build(); - - underTest.initialise(CASE_REFERENCE, caseData); - - DocumentAmendDetails details = caseData.getDocumentAmendDetails(); - assertThat(details.getShowApplications()).isEqualTo(YesOrNo.YES); - assertThat(details.getShowStatementsOfCase()).isEqualTo(YesOrNo.NO); - assertThat(details.getShowPropertyDocuments()).isEqualTo(YesOrNo.NO); - assertThat(details.getShowEvidence()).isEqualTo(YesOrNo.NO); - assertThat(details.getShowHearingDocuments()).isEqualTo(YesOrNo.NO); - assertThat(details.getShowOrdersAndNoticeOfHearings()).isEqualTo(YesOrNo.NO); - assertThat(details.getShowAppeals()).isEqualTo(YesOrNo.NO); - assertThat(details.getShowCorrespondence()).isEqualTo(YesOrNo.NO); - assertThat(details.getShowUncategorisedDocuments()).isEqualTo(YesOrNo.NO); - } - - @Test - void shouldClearFolderDisplayFlagsWhenNoFolderSelected() { - when(pcsCaseService.loadCase(CASE_REFERENCE)).thenReturn(PcsCaseEntity.builder().build()); - PCSCase caseData = PCSCase.builder().build(); - - underTest.initialise(CASE_REFERENCE, caseData); - - DocumentAmendDetails details = caseData.getDocumentAmendDetails(); - assertThat(details.getShowStatementsOfCase()).isEqualTo(YesOrNo.NO); - assertThat(details.getShowPropertyDocuments()).isEqualTo(YesOrNo.NO); - assertThat(details.getShowEvidence()).isEqualTo(YesOrNo.NO); - assertThat(details.getShowHearingDocuments()).isEqualTo(YesOrNo.NO); - assertThat(details.getShowOrdersAndNoticeOfHearings()).isEqualTo(YesOrNo.NO); - assertThat(details.getShowApplications()).isEqualTo(YesOrNo.NO); - assertThat(details.getShowAppeals()).isEqualTo(YesOrNo.NO); - assertThat(details.getShowCorrespondence()).isEqualTo(YesOrNo.NO); - assertThat(details.getShowUncategorisedDocuments()).isEqualTo(YesOrNo.NO); - } - @Test void shouldOnlyShowDocumentsWithUncategorisedCategoryUnderUncategorisedDocuments() { DocumentEntity uncategorisedDocument = document("loose document.pdf", null, null); From a593af7d2a32cf150fe64f0281808a6c8a00e99e Mon Sep 17 00:00:00 2001 From: Liban Abdirahman Date: Wed, 1 Jul 2026 11:07:18 +0100 Subject: [PATCH 16/70] HDPI-6502: Adding case state change event/page --- .../uk/gov/hmcts/reform/pcs/ccd/CaseType.java | 1 + .../pcs/ccd/accesscontrol/AccessGrants.java | 2 + .../pcs/ccd/accesscontrol/AccessProfile.java | 2 +- .../pcs/ccd/domain/CaseStateOption.java | 32 ++++++++ .../hmcts/reform/pcs/ccd/domain/PCSCase.java | 13 +++- .../hmcts/reform/pcs/ccd/domain/State.java | 64 ++++++++++++++- .../hmcts/reform/pcs/ccd/event/EventId.java | 3 +- .../changecasestate/ChangeCaseState.java | 77 +++++++++++++++++++ .../changecasestate/ChangeCaseStatePage.java | 23 ++++++ 9 files changed, 208 insertions(+), 9 deletions(-) create mode 100644 src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/CaseStateOption.java create mode 100644 src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/changecasestate/ChangeCaseState.java create mode 100644 src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/changecasestate/ChangeCaseStatePage.java diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/CaseType.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/CaseType.java index d929d53583..077dd4c12b 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/CaseType.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/CaseType.java @@ -33,6 +33,7 @@ public class CaseType implements CCDConfig { AccessProfile.CITIZEN, AccessProfile.DEFENDANT, AccessProfile.PCS_SOLICITOR, + AccessProfile.PCS_CASE_WORKER, AccessProfile.JUDGE, AccessProfile.FEE_PAID_JUDGE, AccessProfile.CIRCUIT_JUDGE, diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/AccessGrants.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/AccessGrants.java index 2040c1352c..33882d4cfb 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/AccessGrants.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/AccessGrants.java @@ -15,6 +15,7 @@ import static uk.gov.hmcts.reform.pcs.ccd.accesscontrol.UserRole.HEARING_CENTRE_ADMIN; import static uk.gov.hmcts.reform.pcs.ccd.accesscontrol.UserRole.JUDGE; import static uk.gov.hmcts.reform.pcs.ccd.accesscontrol.UserRole.LEADERSHIP_JUDGE; +import static uk.gov.hmcts.reform.pcs.ccd.accesscontrol.UserRole.PCS_CASE_WORKER; import static uk.gov.hmcts.reform.pcs.ccd.accesscontrol.UserRole.PCS_SOLICITOR; import static uk.gov.hmcts.reform.pcs.ccd.accesscontrol.UserRole.WLU_ADMIN; @@ -24,6 +25,7 @@ final class AccessGrants { CITIZEN, DEFENDANT, PCS_SOLICITOR, + PCS_CASE_WORKER, JUDGE, FEE_PAID_JUDGE, CIRCUIT_JUDGE, diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/AccessProfile.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/AccessProfile.java index 3938f5b9fc..e0bfb043d1 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/AccessProfile.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/AccessProfile.java @@ -19,7 +19,7 @@ public enum AccessProfile implements HasRole { DEFENDANT("[DEFENDANT]", CRU), CLAIMANT_SOLICITOR("[CLAIMANTSOLICITOR]", CRU), DEFENDANT_SOLICITOR("[DEFENDANTSOLICITOR]", CRU), - PCS_CASE_WORKER("caseworker-pcs", Set.of(R)), + PCS_CASE_WORKER("caseworker-pcs", CRU), PCS_SOLICITOR("caseworker-pcs-solicitor", CRU), JUDGE("judge", Set.of(R)), diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/CaseStateOption.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/CaseStateOption.java new file mode 100644 index 0000000000..349bf889ee --- /dev/null +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/CaseStateOption.java @@ -0,0 +1,32 @@ +package uk.gov.hmcts.reform.pcs.ccd.domain; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import uk.gov.hmcts.ccd.sdk.api.HasLabel; + + +/** + * Representation of selectable case states for the Change Case State event. + * Each constant here MUST have a matching constant of the same name in {@link State}. + */ +@Getter +@AllArgsConstructor +public enum CaseStateOption implements HasLabel { + + JUDICIAL_REFERRAL("Judicial Referral"), + HEARING_READINESS("Hearing Readiness"), + PREPARE_FOR_HEARING_CONDUCT_HEARING ("Prepare For Hearing Conduct Hearing"), + DECISION_OUTCOME("Decision Outcome"), + CASE_PROGRESSION("Case Progression"), + ALL_FINAL_ORDERS_ISSUED ("All Final Orders"), + CASE_STAYED ("Case Stayed"), + BREATHING_SPACE("Breathing space"); + + private final String label; + + // Converts to the matching State constant — constant names must stay in sync with State enum + public State toState() { + return State.valueOf(this.name()); + } + +} diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/PCSCase.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/PCSCase.java index fd1bc24471..4facf7ccfa 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/PCSCase.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/PCSCase.java @@ -32,11 +32,11 @@ import uk.gov.hmcts.reform.pcs.ccd.accesscontrol.PartyVisibleTabAccess; import uk.gov.hmcts.reform.pcs.ccd.accesscontrol.RasValidationAccess; import uk.gov.hmcts.reform.pcs.ccd.domain.dashboard.DashboardData; +import uk.gov.hmcts.reform.pcs.ccd.domain.documentupload.DocumentUploadDetails; import uk.gov.hmcts.reform.pcs.ccd.domain.enforcetheorder.EnforcementOrder; import uk.gov.hmcts.reform.pcs.ccd.domain.genapp.CitizenGenAppRequest; import uk.gov.hmcts.reform.pcs.ccd.domain.genapp.GeneralApplication; import uk.gov.hmcts.reform.pcs.ccd.domain.genapp.XuiGenAppRequest; -import uk.gov.hmcts.reform.pcs.ccd.domain.documentupload.DocumentUploadDetails; import uk.gov.hmcts.reform.pcs.ccd.domain.grounds.AssuredNoArrearsPossessionGrounds; import uk.gov.hmcts.reform.pcs.ccd.domain.grounds.AssuredRentArrearsPossessionGrounds; import uk.gov.hmcts.reform.pcs.ccd.domain.grounds.ClaimGroundSummary; @@ -48,8 +48,8 @@ import uk.gov.hmcts.reform.pcs.ccd.domain.grounds.SecureOrFlexiblePossessionGrounds; import uk.gov.hmcts.reform.pcs.ccd.domain.respondpossessionclaim.PossessionClaimResponse; import uk.gov.hmcts.reform.pcs.ccd.domain.statementoftruth.StatementOfTruthDetails; -import uk.gov.hmcts.reform.pcs.ccd.domain.tabs.parties.CasePartiesTab; import uk.gov.hmcts.reform.pcs.ccd.domain.tabs.details.CaseDetailsTab; +import uk.gov.hmcts.reform.pcs.ccd.domain.tabs.parties.CasePartiesTab; import uk.gov.hmcts.reform.pcs.ccd.domain.tabs.summary.SummaryTab; import uk.gov.hmcts.reform.pcs.ccd.domain.wales.ASBQuestionsDetailsWales; import uk.gov.hmcts.reform.pcs.ccd.domain.wales.EstateManagementGroundsWales; @@ -57,8 +57,8 @@ import uk.gov.hmcts.reform.pcs.ccd.domain.wales.GroundsReasonsWales; import uk.gov.hmcts.reform.pcs.ccd.domain.wales.OccupationLicenceDetailsWales; import uk.gov.hmcts.reform.pcs.ccd.domain.wales.PeriodicContractTermsWales; -import uk.gov.hmcts.reform.pcs.ccd.domain.wales.WalesDocuments; import uk.gov.hmcts.reform.pcs.ccd.domain.wales.SecureContractGroundsForPossessionWales; +import uk.gov.hmcts.reform.pcs.ccd.domain.wales.WalesDocuments; import uk.gov.hmcts.reform.pcs.ccd.type.DynamicStringList; import uk.gov.hmcts.reform.pcs.postcodecourt.model.LegislativeCountry; @@ -69,6 +69,7 @@ import static uk.gov.hmcts.ccd.sdk.type.FieldType.Collection; import static uk.gov.hmcts.ccd.sdk.type.FieldType.DynamicRadioList; +import static uk.gov.hmcts.ccd.sdk.type.FieldType.FixedList; import static uk.gov.hmcts.ccd.sdk.type.FieldType.MultiSelectList; import static uk.gov.hmcts.ccd.sdk.type.FieldType.TextArea; @@ -715,4 +716,10 @@ public class PCSCase { @CCD private String dateIssuedString; + + @CCD(label = "Which state are you moving the case to?", + typeOverride = FixedList, + typeParameterOverride = "CaseStateOption" + ) + private CaseStateOption targetState; } diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/State.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/State.java index 32aeec350c..5289fff263 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/State.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/State.java @@ -7,8 +7,8 @@ import uk.gov.hmcts.reform.pcs.ccd.accesscontrol.CitizenAccess; import uk.gov.hmcts.reform.pcs.ccd.accesscontrol.ClaimantAccess; import uk.gov.hmcts.reform.pcs.ccd.accesscontrol.DefendantAccess; -import uk.gov.hmcts.reform.pcs.ccd.accesscontrol.InternalCaseFlagAccess; import uk.gov.hmcts.reform.pcs.ccd.accesscontrol.GlobalSearchAccess; +import uk.gov.hmcts.reform.pcs.ccd.accesscontrol.InternalCaseFlagAccess; import uk.gov.hmcts.reform.pcs.ccd.accesscontrol.RasValidationAccess; /** @@ -21,7 +21,7 @@ public enum State { @CCD( label = "Awaiting Submission to HMCTS", - access = {ClaimantAccess.class, CitizenAccess.class, RasValidationAccess.class}, + access = {ClaimantAccess.class, CitizenAccess.class, RasValidationAccess.class,CaseworkerReadAccess.class}, hint = "${caseTitleMarkdown}" ) AWAITING_SUBMISSION_TO_HMCTS, @@ -29,7 +29,7 @@ public enum State { @CCD( label = "Pending Case Issued", access = {ClaimantAccess.class, CitizenAccess.class, RasValidationAccess.class, - InternalCaseFlagAccess.class, GlobalSearchAccess.class}, + InternalCaseFlagAccess.class, GlobalSearchAccess.class,CaseworkerReadAccess.class}, hint = "${caseTitleMarkdown}" ) PENDING_CASE_ISSUED, @@ -40,6 +40,62 @@ public enum State { GlobalSearchAccess.class}, hint = "${caseTitleMarkdown}" ) - CASE_ISSUED + CASE_ISSUED, + + @CCD( + label = "Judicial Referral", + access = {CaseworkerReadAccess.class, ClaimantAccess.class}, + hint = "${caseTitleMarkdown}" + ) + JUDICIAL_REFERRAL, + + @CCD( + label = "Hearing Readiness", + access = {CaseworkerReadAccess.class, ClaimantAccess.class}, + hint = "${caseTitleMarkdown}" + ) + HEARING_READINESS, + + @CCD( + label = "Prepare For Hearing Conduct Hearing", + access = {CaseworkerReadAccess.class, ClaimantAccess.class}, + hint = "${caseTitleMarkdown}" + ) + PREPARE_FOR_HEARING_CONDUCT_HEARING, + + @CCD( + label = "Decision Outcome", + access = {CaseworkerReadAccess.class, ClaimantAccess.class}, + hint = "${caseTitleMarkdown}" + ) + DECISION_OUTCOME, + + @CCD( + label = "Case Progression", + access = {CaseworkerReadAccess.class, ClaimantAccess.class}, + hint = "${caseTitleMarkdown}" + ) + CASE_PROGRESSION, + + @CCD( + label = "All Final Orders", + access = {CaseworkerReadAccess.class, ClaimantAccess.class}, + hint = "${caseTitleMarkdown}" + ) + ALL_FINAL_ORDERS_ISSUED, + + @CCD( + label = "Case Stayed", + access = {CaseworkerReadAccess.class, ClaimantAccess.class}, + hint = "${caseTitleMarkdown}" + ) + CASE_STAYED, + + @CCD( + label = "Breathing Space", + access = {CaseworkerReadAccess.class, ClaimantAccess.class}, + hint = "${caseTitleMarkdown}" + ) + BREATHING_SPACE } diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/EventId.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/EventId.java index a21043ef9f..109456c49b 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/EventId.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/EventId.java @@ -18,5 +18,6 @@ public enum EventId { addCaseNote, createFlags, amendFlags, - claimIssuePayment + claimIssuePayment, + changeCaseState } diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/changecasestate/ChangeCaseState.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/changecasestate/ChangeCaseState.java new file mode 100644 index 0000000000..19ee402cf0 --- /dev/null +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/changecasestate/ChangeCaseState.java @@ -0,0 +1,77 @@ +package uk.gov.hmcts.reform.pcs.ccd.event.changecasestate; + +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Component; +import uk.gov.hmcts.ccd.sdk.api.CCDConfig; +import uk.gov.hmcts.ccd.sdk.api.DecentralisedConfigBuilder; +import uk.gov.hmcts.ccd.sdk.api.Event; +import uk.gov.hmcts.ccd.sdk.api.EventPayload; +import uk.gov.hmcts.ccd.sdk.api.Permission; +import uk.gov.hmcts.ccd.sdk.api.callback.SubmitResponse; +import uk.gov.hmcts.reform.pcs.ccd.accesscontrol.UserRole; +import uk.gov.hmcts.reform.pcs.ccd.common.PageBuilder; +import uk.gov.hmcts.reform.pcs.ccd.domain.PCSCase; +import uk.gov.hmcts.reform.pcs.ccd.domain.State; +import uk.gov.hmcts.reform.pcs.ccd.page.changecasestate.ChangeCaseStatePage; +import uk.gov.hmcts.reform.pcs.ccd.util.AddressFormatter; + +import static uk.gov.hmcts.reform.pcs.ccd.accesscontrol.JudicialHistoryRoles.JUDICIAL_HISTORY_ROLES; +import static uk.gov.hmcts.reform.pcs.ccd.event.EventId.changeCaseState; +import static uk.gov.hmcts.reform.pcs.ccd.util.AddressFormatter.COMMA_DELIMITER; + +@Component +@AllArgsConstructor +public class ChangeCaseState implements CCDConfig { + + private final AddressFormatter addressFormatter; + + @Override + public void configureDecentralised(DecentralisedConfigBuilder configBuilder) { + Event.EventBuilder eventBuilder = configBuilder + .decentralisedEvent(changeCaseState.name(), this::submit) + .forStates( + State.JUDICIAL_REFERRAL, + State.HEARING_READINESS, + State.PREPARE_FOR_HEARING_CONDUCT_HEARING, + State.DECISION_OUTCOME, + State.CASE_PROGRESSION, + State.ALL_FINAL_ORDERS_ISSUED, + State.CASE_STAYED, + State.BREATHING_SPACE + ) + .name("Change case state") + .grant(Permission.CRUD, UserRole.PCS_CASE_WORKER) + .grantHistoryOnly(JUDICIAL_HISTORY_ROLES) + .showSummary() + .endButtonLabel("Submit"); + + new PageBuilder(eventBuilder) + .add(new ChangeCaseStatePage()); + } + + private SubmitResponse submit(EventPayload eventPayload) { + PCSCase pcsCase = eventPayload.caseData(); + State targetState = pcsCase.getTargetState().toState(); + return SubmitResponse.builder() + .state(targetState) + .confirmationBody(buildConfirmationMarkdown(pcsCase, eventPayload.caseReference())) + .build(); + } + + private String buildConfirmationMarkdown(PCSCase pcsCase, long caseReference) { + String address = addressFormatter.formatShortAddress(pcsCase.getPropertyAddress(), COMMA_DELIMITER); + return """ + --- +
+ Case state changed +
+ Case number: %s
+ Property address: %s +
+
+ +

What happens next

+

The case will progress according to the state it has been changed to.

+ """.formatted(caseReference, address); + } +} diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/changecasestate/ChangeCaseStatePage.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/changecasestate/ChangeCaseStatePage.java new file mode 100644 index 0000000000..f0bfbc66ed --- /dev/null +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/changecasestate/ChangeCaseStatePage.java @@ -0,0 +1,23 @@ +package uk.gov.hmcts.reform.pcs.ccd.page.changecasestate; + +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Component; +import uk.gov.hmcts.reform.pcs.ccd.common.CcdPageConfiguration; +import uk.gov.hmcts.reform.pcs.ccd.common.PageBuilder; +import uk.gov.hmcts.reform.pcs.ccd.domain.PCSCase; + + +@AllArgsConstructor +@Component +public class ChangeCaseStatePage implements CcdPageConfiguration { + + @Override + public void addTo(PageBuilder pageBuilder) { + pageBuilder.page("changeCaseStatePage") + .pageLabel("Case state to change to") + .label("changeCaseStatePage-lineSeparator", "---") + .label("changeCaseState-currentState", "Current state: ${[STATE]}") + .mandatory(PCSCase::getTargetState); + } + +} From 183d5b90ebf6195ca9094c278af8af072df01b2c Mon Sep 17 00:00:00 2001 From: sadmanrahman Date: Wed, 1 Jul 2026 11:29:14 +0100 Subject: [PATCH 17/70] HDPI-7308: radiobutton with question working --- .../documentamend/DocumentAmendDetails.java | 2 - .../documentamend/DocumentAmendFolder.java | 16 -------- .../DocumentAmendFolderDeserializer.java | 39 ------------------- .../documentamend/SelectDocumentPage.java | 21 +++++----- .../DocumentAmendSelectionService.java | 1 - 5 files changed, 10 insertions(+), 69 deletions(-) delete mode 100644 src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendFolderDeserializer.java diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendDetails.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendDetails.java index 71c0a4c05c..c14b3e21a0 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendDetails.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendDetails.java @@ -2,7 +2,6 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; -import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -27,7 +26,6 @@ public class DocumentAmendDetails { typeOverride = FixedList, typeParameterOverride = "DocumentAmendFolder" ) - @JsonDeserialize(using = DocumentAmendFolderDeserializer.class) private DocumentAmendFolder selectedFolder; @CCD(searchable = false) diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendFolder.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendFolder.java index 452358921b..073c023397 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendFolder.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendFolder.java @@ -24,20 +24,4 @@ public enum DocumentAmendFolder implements HasLabel { this.category = category; this.label = category.getLabel(); } - - public static DocumentAmendFolder from(String value) { - if (value == null) { - return null; - } - - for (DocumentAmendFolder folder : values()) { - if (folder.name().equals(value) - || folder.getLabel().equals(value) - || folder.getCategory().getId().equals(value)) { - return folder; - } - } - - return null; - } } diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendFolderDeserializer.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendFolderDeserializer.java deleted file mode 100644 index b548c2ebf5..0000000000 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendFolderDeserializer.java +++ /dev/null @@ -1,39 +0,0 @@ -package uk.gov.hmcts.reform.pcs.ccd.domain.documentamend; - -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.JsonDeserializer; -import com.fasterxml.jackson.databind.JsonNode; - -import java.io.IOException; - -public class DocumentAmendFolderDeserializer extends JsonDeserializer { - - @Override - public DocumentAmendFolder deserialize(JsonParser parser, DeserializationContext context) throws IOException { - JsonNode node = parser.getCodec().readTree(parser); - return DocumentAmendFolder.from(folderValue(node)); - } - - private String folderValue(JsonNode node) { - if (node == null || node.isNull()) { - return null; - } - if (node.isTextual()) { - return node.asText(); - } - - JsonNode value = node.get("value"); - if (value != null) { - return folderValue(value); - } - - JsonNode code = node.get("code"); - if (code != null) { - return code.asText(); - } - - JsonNode label = node.get("label"); - return label == null ? null : label.asText(); - } -} diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java index adf4858325..9a78373b73 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java @@ -23,7 +23,6 @@ public class SelectDocumentPage implements CcdPageConfiguration { private static final String PAGE_ID = "selectDocument"; private static final String FIELD_PREFIX = "documentAmend_"; private static final String YES = "=\"Yes\""; - private static final String NO = "=\"No\""; private final DocumentAmendSelectionService documentAmendSelectionService; @@ -43,56 +42,56 @@ public void addTo(PageBuilder pageBuilder) { .readonly(DocumentAmendDetails::getPartyNamesSummary, NEVER_SHOW, true) .mandatory(DocumentAmendDetails::getSelectedFolder) .mandatory(DocumentAmendDetails::getStatementsOfCaseDocuments, - documentsShowCondition(CaseFileCategory.STATEMENTS_OF_CASE), true) + documentsShowCondition(CaseFileCategory.STATEMENTS_OF_CASE)) .label("statementsOfCaseNoDocumentsQuestion", "Which document do you want to amend?", noDocumentsShowCondition(CaseFileCategory.STATEMENTS_OF_CASE)) .label("statementsOfCaseNoDocuments", noDocumentsMessage(CaseFileCategory.STATEMENTS_OF_CASE), noDocumentsShowCondition(CaseFileCategory.STATEMENTS_OF_CASE)) .mandatory(DocumentAmendDetails::getPropertyDocuments, - documentsShowCondition(CaseFileCategory.PROPERTY_DOCUMENTS), true) + documentsShowCondition(CaseFileCategory.PROPERTY_DOCUMENTS)) .label("propertyDocumentsNoDocumentsQuestion", "Which document do you want to amend?", noDocumentsShowCondition(CaseFileCategory.PROPERTY_DOCUMENTS)) .label("propertyDocumentsNoDocuments", noDocumentsMessage(CaseFileCategory.PROPERTY_DOCUMENTS), noDocumentsShowCondition(CaseFileCategory.PROPERTY_DOCUMENTS)) .mandatory(DocumentAmendDetails::getEvidenceDocuments, - documentsShowCondition(CaseFileCategory.EVIDENCE), true) + documentsShowCondition(CaseFileCategory.EVIDENCE)) .label("evidenceNoDocumentsQuestion", "Which document do you want to amend?", noDocumentsShowCondition(CaseFileCategory.EVIDENCE)) .label("evidenceNoDocuments", noDocumentsMessage(CaseFileCategory.EVIDENCE), noDocumentsShowCondition(CaseFileCategory.EVIDENCE)) .mandatory(DocumentAmendDetails::getHearingDocuments, - documentsShowCondition(CaseFileCategory.HEARING_DOCUMENTS), true) + documentsShowCondition(CaseFileCategory.HEARING_DOCUMENTS)) .label("hearingDocumentsNoDocumentsQuestion", "Which document do you want to amend?", noDocumentsShowCondition(CaseFileCategory.HEARING_DOCUMENTS)) .label("hearingDocumentsNoDocuments", noDocumentsMessage(CaseFileCategory.HEARING_DOCUMENTS), noDocumentsShowCondition(CaseFileCategory.HEARING_DOCUMENTS)) .mandatory(DocumentAmendDetails::getOrdersAndNoticeOfHearingsDocuments, - documentsShowCondition(CaseFileCategory.ORDERS_AND_NOTICE_OF_HEARINGS), true) + documentsShowCondition(CaseFileCategory.ORDERS_AND_NOTICE_OF_HEARINGS)) .label("ordersAndNoticeOfHearingsNoDocumentsQuestion", "Which document do you want to amend?", noDocumentsShowCondition(CaseFileCategory.ORDERS_AND_NOTICE_OF_HEARINGS)) .label("ordersAndNoticeOfHearingsNoDocuments", noDocumentsMessage(CaseFileCategory.ORDERS_AND_NOTICE_OF_HEARINGS), noDocumentsShowCondition(CaseFileCategory.ORDERS_AND_NOTICE_OF_HEARINGS)) .mandatory(DocumentAmendDetails::getApplicationsDocuments, - documentsShowCondition(CaseFileCategory.APPLICATIONS), true) + documentsShowCondition(CaseFileCategory.APPLICATIONS)) .label("applicationsNoDocumentsQuestion", "Which document do you want to amend?", noDocumentsShowCondition(CaseFileCategory.APPLICATIONS)) .label("applicationsNoDocuments", noDocumentsMessage(CaseFileCategory.APPLICATIONS), noDocumentsShowCondition(CaseFileCategory.APPLICATIONS)) .mandatory(DocumentAmendDetails::getAppealsDocuments, - documentsShowCondition(CaseFileCategory.APPEALS), true) + documentsShowCondition(CaseFileCategory.APPEALS)) .label("appealsNoDocumentsQuestion", "Which document do you want to amend?", noDocumentsShowCondition(CaseFileCategory.APPEALS)) .label("appealsNoDocuments", noDocumentsMessage(CaseFileCategory.APPEALS), noDocumentsShowCondition(CaseFileCategory.APPEALS)) .mandatory(DocumentAmendDetails::getCorrespondenceDocuments, - documentsShowCondition(CaseFileCategory.CORRESPONDENCE), true) + documentsShowCondition(CaseFileCategory.CORRESPONDENCE)) .label("correspondenceNoDocumentsQuestion", "Which document do you want to amend?", noDocumentsShowCondition(CaseFileCategory.CORRESPONDENCE)) .label("correspondenceNoDocuments", noDocumentsMessage(CaseFileCategory.CORRESPONDENCE), noDocumentsShowCondition(CaseFileCategory.CORRESPONDENCE)) .mandatory(DocumentAmendDetails::getUncategorisedDocuments, - documentsShowCondition(CaseFileCategory.UNCATEGORISED_DOCUMENTS), true) + documentsShowCondition(CaseFileCategory.UNCATEGORISED_DOCUMENTS)) .label("uncategorisedDocumentsNoDocumentsQuestion", "Which document do you want to amend?", noDocumentsShowCondition(CaseFileCategory.UNCATEGORISED_DOCUMENTS)) .label("uncategorisedDocumentsNoDocuments", @@ -128,7 +127,7 @@ private AboutToStartOrSubmitResponse midEvent(CaseDetails details.setUncategorisedDocumentsEmpty(empty); } } - } From 145df1fe08794e7642b003a070df8ba7ff51a30e Mon Sep 17 00:00:00 2001 From: sadmanrahman Date: Wed, 1 Jul 2026 11:30:06 +0100 Subject: [PATCH 18/70] HDPI-7308: radiobutton --- .../documentamend/DocumentAmendDetails.java | 2 + .../documentamend/DocumentAmendFolder.java | 16 ++++++++ .../DocumentAmendFolderDeserializer.java | 39 +++++++++++++++++++ .../documentamend/SelectDocumentPage.java | 21 +++++----- .../DocumentAmendSelectionService.java | 1 + 5 files changed, 69 insertions(+), 10 deletions(-) create mode 100644 src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendFolderDeserializer.java diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendDetails.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendDetails.java index c14b3e21a0..71c0a4c05c 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendDetails.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendDetails.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -26,6 +27,7 @@ public class DocumentAmendDetails { typeOverride = FixedList, typeParameterOverride = "DocumentAmendFolder" ) + @JsonDeserialize(using = DocumentAmendFolderDeserializer.class) private DocumentAmendFolder selectedFolder; @CCD(searchable = false) diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendFolder.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendFolder.java index 073c023397..452358921b 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendFolder.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendFolder.java @@ -24,4 +24,20 @@ public enum DocumentAmendFolder implements HasLabel { this.category = category; this.label = category.getLabel(); } + + public static DocumentAmendFolder from(String value) { + if (value == null) { + return null; + } + + for (DocumentAmendFolder folder : values()) { + if (folder.name().equals(value) + || folder.getLabel().equals(value) + || folder.getCategory().getId().equals(value)) { + return folder; + } + } + + return null; + } } diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendFolderDeserializer.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendFolderDeserializer.java new file mode 100644 index 0000000000..b548c2ebf5 --- /dev/null +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendFolderDeserializer.java @@ -0,0 +1,39 @@ +package uk.gov.hmcts.reform.pcs.ccd.domain.documentamend; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; + +import java.io.IOException; + +public class DocumentAmendFolderDeserializer extends JsonDeserializer { + + @Override + public DocumentAmendFolder deserialize(JsonParser parser, DeserializationContext context) throws IOException { + JsonNode node = parser.getCodec().readTree(parser); + return DocumentAmendFolder.from(folderValue(node)); + } + + private String folderValue(JsonNode node) { + if (node == null || node.isNull()) { + return null; + } + if (node.isTextual()) { + return node.asText(); + } + + JsonNode value = node.get("value"); + if (value != null) { + return folderValue(value); + } + + JsonNode code = node.get("code"); + if (code != null) { + return code.asText(); + } + + JsonNode label = node.get("label"); + return label == null ? null : label.asText(); + } +} diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java index 9a78373b73..adf4858325 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java @@ -23,6 +23,7 @@ public class SelectDocumentPage implements CcdPageConfiguration { private static final String PAGE_ID = "selectDocument"; private static final String FIELD_PREFIX = "documentAmend_"; private static final String YES = "=\"Yes\""; + private static final String NO = "=\"No\""; private final DocumentAmendSelectionService documentAmendSelectionService; @@ -42,56 +43,56 @@ public void addTo(PageBuilder pageBuilder) { .readonly(DocumentAmendDetails::getPartyNamesSummary, NEVER_SHOW, true) .mandatory(DocumentAmendDetails::getSelectedFolder) .mandatory(DocumentAmendDetails::getStatementsOfCaseDocuments, - documentsShowCondition(CaseFileCategory.STATEMENTS_OF_CASE)) + documentsShowCondition(CaseFileCategory.STATEMENTS_OF_CASE), true) .label("statementsOfCaseNoDocumentsQuestion", "Which document do you want to amend?", noDocumentsShowCondition(CaseFileCategory.STATEMENTS_OF_CASE)) .label("statementsOfCaseNoDocuments", noDocumentsMessage(CaseFileCategory.STATEMENTS_OF_CASE), noDocumentsShowCondition(CaseFileCategory.STATEMENTS_OF_CASE)) .mandatory(DocumentAmendDetails::getPropertyDocuments, - documentsShowCondition(CaseFileCategory.PROPERTY_DOCUMENTS)) + documentsShowCondition(CaseFileCategory.PROPERTY_DOCUMENTS), true) .label("propertyDocumentsNoDocumentsQuestion", "Which document do you want to amend?", noDocumentsShowCondition(CaseFileCategory.PROPERTY_DOCUMENTS)) .label("propertyDocumentsNoDocuments", noDocumentsMessage(CaseFileCategory.PROPERTY_DOCUMENTS), noDocumentsShowCondition(CaseFileCategory.PROPERTY_DOCUMENTS)) .mandatory(DocumentAmendDetails::getEvidenceDocuments, - documentsShowCondition(CaseFileCategory.EVIDENCE)) + documentsShowCondition(CaseFileCategory.EVIDENCE), true) .label("evidenceNoDocumentsQuestion", "Which document do you want to amend?", noDocumentsShowCondition(CaseFileCategory.EVIDENCE)) .label("evidenceNoDocuments", noDocumentsMessage(CaseFileCategory.EVIDENCE), noDocumentsShowCondition(CaseFileCategory.EVIDENCE)) .mandatory(DocumentAmendDetails::getHearingDocuments, - documentsShowCondition(CaseFileCategory.HEARING_DOCUMENTS)) + documentsShowCondition(CaseFileCategory.HEARING_DOCUMENTS), true) .label("hearingDocumentsNoDocumentsQuestion", "Which document do you want to amend?", noDocumentsShowCondition(CaseFileCategory.HEARING_DOCUMENTS)) .label("hearingDocumentsNoDocuments", noDocumentsMessage(CaseFileCategory.HEARING_DOCUMENTS), noDocumentsShowCondition(CaseFileCategory.HEARING_DOCUMENTS)) .mandatory(DocumentAmendDetails::getOrdersAndNoticeOfHearingsDocuments, - documentsShowCondition(CaseFileCategory.ORDERS_AND_NOTICE_OF_HEARINGS)) + documentsShowCondition(CaseFileCategory.ORDERS_AND_NOTICE_OF_HEARINGS), true) .label("ordersAndNoticeOfHearingsNoDocumentsQuestion", "Which document do you want to amend?", noDocumentsShowCondition(CaseFileCategory.ORDERS_AND_NOTICE_OF_HEARINGS)) .label("ordersAndNoticeOfHearingsNoDocuments", noDocumentsMessage(CaseFileCategory.ORDERS_AND_NOTICE_OF_HEARINGS), noDocumentsShowCondition(CaseFileCategory.ORDERS_AND_NOTICE_OF_HEARINGS)) .mandatory(DocumentAmendDetails::getApplicationsDocuments, - documentsShowCondition(CaseFileCategory.APPLICATIONS)) + documentsShowCondition(CaseFileCategory.APPLICATIONS), true) .label("applicationsNoDocumentsQuestion", "Which document do you want to amend?", noDocumentsShowCondition(CaseFileCategory.APPLICATIONS)) .label("applicationsNoDocuments", noDocumentsMessage(CaseFileCategory.APPLICATIONS), noDocumentsShowCondition(CaseFileCategory.APPLICATIONS)) .mandatory(DocumentAmendDetails::getAppealsDocuments, - documentsShowCondition(CaseFileCategory.APPEALS)) + documentsShowCondition(CaseFileCategory.APPEALS), true) .label("appealsNoDocumentsQuestion", "Which document do you want to amend?", noDocumentsShowCondition(CaseFileCategory.APPEALS)) .label("appealsNoDocuments", noDocumentsMessage(CaseFileCategory.APPEALS), noDocumentsShowCondition(CaseFileCategory.APPEALS)) .mandatory(DocumentAmendDetails::getCorrespondenceDocuments, - documentsShowCondition(CaseFileCategory.CORRESPONDENCE)) + documentsShowCondition(CaseFileCategory.CORRESPONDENCE), true) .label("correspondenceNoDocumentsQuestion", "Which document do you want to amend?", noDocumentsShowCondition(CaseFileCategory.CORRESPONDENCE)) .label("correspondenceNoDocuments", noDocumentsMessage(CaseFileCategory.CORRESPONDENCE), noDocumentsShowCondition(CaseFileCategory.CORRESPONDENCE)) .mandatory(DocumentAmendDetails::getUncategorisedDocuments, - documentsShowCondition(CaseFileCategory.UNCATEGORISED_DOCUMENTS)) + documentsShowCondition(CaseFileCategory.UNCATEGORISED_DOCUMENTS), true) .label("uncategorisedDocumentsNoDocumentsQuestion", "Which document do you want to amend?", noDocumentsShowCondition(CaseFileCategory.UNCATEGORISED_DOCUMENTS)) .label("uncategorisedDocumentsNoDocuments", @@ -127,7 +128,7 @@ private AboutToStartOrSubmitResponse midEvent(CaseDetails details.setUncategorisedDocumentsEmpty(empty); } } + } From 1e5623b2b716e49e152f5c5b68f75d4878d286fc Mon Sep 17 00:00:00 2001 From: sadmanrahman Date: Wed, 1 Jul 2026 11:37:56 +0100 Subject: [PATCH 19/70] HDPI-7308: second question working --- .../documentamend/DocumentAmendDetails.java | 29 ++++++++++++- .../documentamend/DocumentAmendFolder.java | 16 ------- .../DocumentAmendFolderDeserializer.java | 39 ----------------- .../documentamend/SelectDocumentPage.java | 43 ++++++++++++++----- .../DocumentAmendSelectionService.java | 26 +++++++++++ .../DocumentAmendFolderTest.java | 41 ------------------ .../DocumentAmendSelectionServiceTest.java | 42 ++++++++++++++++++ 7 files changed, 128 insertions(+), 108 deletions(-) delete mode 100644 src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendFolderDeserializer.java delete mode 100644 src/test/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendFolderTest.java diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendDetails.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendDetails.java index 71c0a4c05c..948dd57f19 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendDetails.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendDetails.java @@ -2,7 +2,6 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; -import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -27,7 +26,6 @@ public class DocumentAmendDetails { typeOverride = FixedList, typeParameterOverride = "DocumentAmendFolder" ) - @JsonDeserialize(using = DocumentAmendFolderDeserializer.class) private DocumentAmendFolder selectedFolder; @CCD(searchable = false) @@ -126,6 +124,33 @@ public class DocumentAmendDetails { @CCD(searchable = false) private YesOrNo uncategorisedDocumentsEmpty; + @CCD(searchable = false) + private YesOrNo showStatementsOfCase; + + @CCD(searchable = false) + private YesOrNo showPropertyDocuments; + + @CCD(searchable = false) + private YesOrNo showEvidence; + + @CCD(searchable = false) + private YesOrNo showHearingDocuments; + + @CCD(searchable = false) + private YesOrNo showOrdersAndNoticeOfHearings; + + @CCD(searchable = false) + private YesOrNo showApplications; + + @CCD(searchable = false) + private YesOrNo showAppeals; + + @CCD(searchable = false) + private YesOrNo showCorrespondence; + + @CCD(searchable = false) + private YesOrNo showUncategorisedDocuments; + @CCD(searchable = false) private String selectedFolderId; diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendFolder.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendFolder.java index 452358921b..073c023397 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendFolder.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendFolder.java @@ -24,20 +24,4 @@ public enum DocumentAmendFolder implements HasLabel { this.category = category; this.label = category.getLabel(); } - - public static DocumentAmendFolder from(String value) { - if (value == null) { - return null; - } - - for (DocumentAmendFolder folder : values()) { - if (folder.name().equals(value) - || folder.getLabel().equals(value) - || folder.getCategory().getId().equals(value)) { - return folder; - } - } - - return null; - } } diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendFolderDeserializer.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendFolderDeserializer.java deleted file mode 100644 index b548c2ebf5..0000000000 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendFolderDeserializer.java +++ /dev/null @@ -1,39 +0,0 @@ -package uk.gov.hmcts.reform.pcs.ccd.domain.documentamend; - -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.JsonDeserializer; -import com.fasterxml.jackson.databind.JsonNode; - -import java.io.IOException; - -public class DocumentAmendFolderDeserializer extends JsonDeserializer { - - @Override - public DocumentAmendFolder deserialize(JsonParser parser, DeserializationContext context) throws IOException { - JsonNode node = parser.getCodec().readTree(parser); - return DocumentAmendFolder.from(folderValue(node)); - } - - private String folderValue(JsonNode node) { - if (node == null || node.isNull()) { - return null; - } - if (node.isTextual()) { - return node.asText(); - } - - JsonNode value = node.get("value"); - if (value != null) { - return folderValue(value); - } - - JsonNode code = node.get("code"); - if (code != null) { - return code.asText(); - } - - JsonNode label = node.get("label"); - return label == null ? null : label.asText(); - } -} diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java index adf4858325..ce799814f6 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java @@ -43,56 +43,56 @@ public void addTo(PageBuilder pageBuilder) { .readonly(DocumentAmendDetails::getPartyNamesSummary, NEVER_SHOW, true) .mandatory(DocumentAmendDetails::getSelectedFolder) .mandatory(DocumentAmendDetails::getStatementsOfCaseDocuments, - documentsShowCondition(CaseFileCategory.STATEMENTS_OF_CASE), true) + documentsShowCondition(CaseFileCategory.STATEMENTS_OF_CASE)) .label("statementsOfCaseNoDocumentsQuestion", "Which document do you want to amend?", noDocumentsShowCondition(CaseFileCategory.STATEMENTS_OF_CASE)) .label("statementsOfCaseNoDocuments", noDocumentsMessage(CaseFileCategory.STATEMENTS_OF_CASE), noDocumentsShowCondition(CaseFileCategory.STATEMENTS_OF_CASE)) .mandatory(DocumentAmendDetails::getPropertyDocuments, - documentsShowCondition(CaseFileCategory.PROPERTY_DOCUMENTS), true) + documentsShowCondition(CaseFileCategory.PROPERTY_DOCUMENTS)) .label("propertyDocumentsNoDocumentsQuestion", "Which document do you want to amend?", noDocumentsShowCondition(CaseFileCategory.PROPERTY_DOCUMENTS)) .label("propertyDocumentsNoDocuments", noDocumentsMessage(CaseFileCategory.PROPERTY_DOCUMENTS), noDocumentsShowCondition(CaseFileCategory.PROPERTY_DOCUMENTS)) .mandatory(DocumentAmendDetails::getEvidenceDocuments, - documentsShowCondition(CaseFileCategory.EVIDENCE), true) + documentsShowCondition(CaseFileCategory.EVIDENCE)) .label("evidenceNoDocumentsQuestion", "Which document do you want to amend?", noDocumentsShowCondition(CaseFileCategory.EVIDENCE)) .label("evidenceNoDocuments", noDocumentsMessage(CaseFileCategory.EVIDENCE), noDocumentsShowCondition(CaseFileCategory.EVIDENCE)) .mandatory(DocumentAmendDetails::getHearingDocuments, - documentsShowCondition(CaseFileCategory.HEARING_DOCUMENTS), true) + documentsShowCondition(CaseFileCategory.HEARING_DOCUMENTS)) .label("hearingDocumentsNoDocumentsQuestion", "Which document do you want to amend?", noDocumentsShowCondition(CaseFileCategory.HEARING_DOCUMENTS)) .label("hearingDocumentsNoDocuments", noDocumentsMessage(CaseFileCategory.HEARING_DOCUMENTS), noDocumentsShowCondition(CaseFileCategory.HEARING_DOCUMENTS)) .mandatory(DocumentAmendDetails::getOrdersAndNoticeOfHearingsDocuments, - documentsShowCondition(CaseFileCategory.ORDERS_AND_NOTICE_OF_HEARINGS), true) + documentsShowCondition(CaseFileCategory.ORDERS_AND_NOTICE_OF_HEARINGS)) .label("ordersAndNoticeOfHearingsNoDocumentsQuestion", "Which document do you want to amend?", noDocumentsShowCondition(CaseFileCategory.ORDERS_AND_NOTICE_OF_HEARINGS)) .label("ordersAndNoticeOfHearingsNoDocuments", noDocumentsMessage(CaseFileCategory.ORDERS_AND_NOTICE_OF_HEARINGS), noDocumentsShowCondition(CaseFileCategory.ORDERS_AND_NOTICE_OF_HEARINGS)) .mandatory(DocumentAmendDetails::getApplicationsDocuments, - documentsShowCondition(CaseFileCategory.APPLICATIONS), true) + documentsShowCondition(CaseFileCategory.APPLICATIONS)) .label("applicationsNoDocumentsQuestion", "Which document do you want to amend?", noDocumentsShowCondition(CaseFileCategory.APPLICATIONS)) .label("applicationsNoDocuments", noDocumentsMessage(CaseFileCategory.APPLICATIONS), noDocumentsShowCondition(CaseFileCategory.APPLICATIONS)) .mandatory(DocumentAmendDetails::getAppealsDocuments, - documentsShowCondition(CaseFileCategory.APPEALS), true) + documentsShowCondition(CaseFileCategory.APPEALS)) .label("appealsNoDocumentsQuestion", "Which document do you want to amend?", noDocumentsShowCondition(CaseFileCategory.APPEALS)) .label("appealsNoDocuments", noDocumentsMessage(CaseFileCategory.APPEALS), noDocumentsShowCondition(CaseFileCategory.APPEALS)) .mandatory(DocumentAmendDetails::getCorrespondenceDocuments, - documentsShowCondition(CaseFileCategory.CORRESPONDENCE), true) + documentsShowCondition(CaseFileCategory.CORRESPONDENCE)) .label("correspondenceNoDocumentsQuestion", "Which document do you want to amend?", noDocumentsShowCondition(CaseFileCategory.CORRESPONDENCE)) .label("correspondenceNoDocuments", noDocumentsMessage(CaseFileCategory.CORRESPONDENCE), noDocumentsShowCondition(CaseFileCategory.CORRESPONDENCE)) .mandatory(DocumentAmendDetails::getUncategorisedDocuments, - documentsShowCondition(CaseFileCategory.UNCATEGORISED_DOCUMENTS), true) + documentsShowCondition(CaseFileCategory.UNCATEGORISED_DOCUMENTS)) .label("uncategorisedDocumentsNoDocumentsQuestion", "Which document do you want to amend?", noDocumentsShowCondition(CaseFileCategory.UNCATEGORISED_DOCUMENTS)) .label("uncategorisedDocumentsNoDocuments", @@ -107,6 +107,15 @@ public void addTo(PageBuilder pageBuilder) { .readonly(DocumentAmendDetails::getAppealsEmpty, NEVER_SHOW, true) .readonly(DocumentAmendDetails::getCorrespondenceEmpty, NEVER_SHOW, true) .readonly(DocumentAmendDetails::getUncategorisedDocumentsEmpty, NEVER_SHOW, true) + .readonly(DocumentAmendDetails::getShowStatementsOfCase, NEVER_SHOW, true) + .readonly(DocumentAmendDetails::getShowPropertyDocuments, NEVER_SHOW, true) + .readonly(DocumentAmendDetails::getShowEvidence, NEVER_SHOW, true) + .readonly(DocumentAmendDetails::getShowHearingDocuments, NEVER_SHOW, true) + .readonly(DocumentAmendDetails::getShowOrdersAndNoticeOfHearings, NEVER_SHOW, true) + .readonly(DocumentAmendDetails::getShowApplications, NEVER_SHOW, true) + .readonly(DocumentAmendDetails::getShowAppeals, NEVER_SHOW, true) + .readonly(DocumentAmendDetails::getShowCorrespondence, NEVER_SHOW, true) + .readonly(DocumentAmendDetails::getShowUncategorisedDocuments, NEVER_SHOW, true) .readonly(DocumentAmendDetails::getSelectedFolderId, NEVER_SHOW, true) .readonly(DocumentAmendDetails::getSelectedFolderLabel, NEVER_SHOW, true) .readonly(DocumentAmendDetails::getSelectedDocumentId, NEVER_SHOW, true) @@ -136,7 +145,7 @@ private String noDocumentsShowCondition(CaseFileCategory category) { } private String selectedFolderCondition(CaseFileCategory category) { - return FIELD_PREFIX + "SelectedFolder=\"" + category.name() + "\""; + return showFieldId(category) + YES; } private String emptyFieldId(CaseFileCategory category) { @@ -153,6 +162,20 @@ private String emptyFieldId(CaseFileCategory category) { }; } + private String showFieldId(CaseFileCategory category) { + return switch (category) { + case STATEMENTS_OF_CASE -> FIELD_PREFIX + "ShowStatementsOfCase"; + case PROPERTY_DOCUMENTS -> FIELD_PREFIX + "ShowPropertyDocuments"; + case EVIDENCE -> FIELD_PREFIX + "ShowEvidence"; + case HEARING_DOCUMENTS -> FIELD_PREFIX + "ShowHearingDocuments"; + case ORDERS_AND_NOTICE_OF_HEARINGS -> FIELD_PREFIX + "ShowOrdersAndNoticeOfHearings"; + case APPLICATIONS -> FIELD_PREFIX + "ShowApplications"; + case APPEALS -> FIELD_PREFIX + "ShowAppeals"; + case CORRESPONDENCE -> FIELD_PREFIX + "ShowCorrespondence"; + case UNCATEGORISED_DOCUMENTS -> FIELD_PREFIX + "ShowUncategorisedDocuments"; + }; + } + private String noDocumentsMessage(CaseFileCategory category) { return "No documents in '" + category.getLabel() + "'"; } diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionService.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionService.java index 74c3cf0851..106c3b4981 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionService.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionService.java @@ -55,6 +55,7 @@ public void initialise(long caseReference, PCSCase caseData) { setDocumentsForCategory(details, pcsCase, CaseFileCategory.APPEALS); setDocumentsForCategory(details, pcsCase, CaseFileCategory.CORRESPONDENCE); setDocumentsForCategory(details, pcsCase, CaseFileCategory.UNCATEGORISED_DOCUMENTS); + setSelectedFolderDisplayFlags(details); } public List validateAndStoreSelection(PCSCase caseData) { @@ -196,4 +197,29 @@ private void setEmptyForCategory(DocumentAmendDetails details, CaseFileCategory } } + private void setSelectedFolderDisplayFlags(DocumentAmendDetails details) { + CaseFileCategory selectedCategory = details.getSelectedFolder() == null + ? null + : details.getSelectedFolder().getCategory(); + + details.setShowStatementsOfCase(showSelectedFolder(selectedCategory, CaseFileCategory.STATEMENTS_OF_CASE)); + details.setShowPropertyDocuments(showSelectedFolder(selectedCategory, CaseFileCategory.PROPERTY_DOCUMENTS)); + details.setShowEvidence(showSelectedFolder(selectedCategory, CaseFileCategory.EVIDENCE)); + details.setShowHearingDocuments(showSelectedFolder(selectedCategory, CaseFileCategory.HEARING_DOCUMENTS)); + details.setShowOrdersAndNoticeOfHearings(showSelectedFolder( + selectedCategory, + CaseFileCategory.ORDERS_AND_NOTICE_OF_HEARINGS + )); + details.setShowApplications(showSelectedFolder(selectedCategory, CaseFileCategory.APPLICATIONS)); + details.setShowAppeals(showSelectedFolder(selectedCategory, CaseFileCategory.APPEALS)); + details.setShowCorrespondence(showSelectedFolder(selectedCategory, CaseFileCategory.CORRESPONDENCE)); + details.setShowUncategorisedDocuments(showSelectedFolder( + selectedCategory, + CaseFileCategory.UNCATEGORISED_DOCUMENTS + )); + } + + private YesOrNo showSelectedFolder(CaseFileCategory selectedCategory, CaseFileCategory category) { + return YesOrNo.from(category == selectedCategory); + } } diff --git a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendFolderTest.java b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendFolderTest.java deleted file mode 100644 index bf94a77c57..0000000000 --- a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendFolderTest.java +++ /dev/null @@ -1,41 +0,0 @@ -package uk.gov.hmcts.reform.pcs.ccd.domain.documentamend; - -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; - -class DocumentAmendFolderTest { - - private final ObjectMapper objectMapper = new ObjectMapper(); - - @Test - void shouldResolveFolderFromCodeLabelOrCategoryId() { - assertThat(DocumentAmendFolder.from("PROPERTY_DOCUMENTS")) - .isEqualTo(DocumentAmendFolder.PROPERTY_DOCUMENTS); - assertThat(DocumentAmendFolder.from("Property documents")) - .isEqualTo(DocumentAmendFolder.PROPERTY_DOCUMENTS); - assertThat(DocumentAmendFolder.from("propertyDocuments")) - .isEqualTo(DocumentAmendFolder.PROPERTY_DOCUMENTS); - } - - @Test - void shouldDeserializeFolderFromFixedListCode() throws Exception { - DocumentAmendDetails details = objectMapper.readValue( - "{\"selectedFolder\":\"PROPERTY_DOCUMENTS\"}", - DocumentAmendDetails.class - ); - - assertThat(details.getSelectedFolder()).isEqualTo(DocumentAmendFolder.PROPERTY_DOCUMENTS); - } - - @Test - void shouldDeserializeFolderFromFixedListObject() throws Exception { - DocumentAmendDetails details = objectMapper.readValue( - "{\"selectedFolder\":{\"value\":{\"code\":\"PROPERTY_DOCUMENTS\",\"label\":\"Property documents\"}}}", - DocumentAmendDetails.class - ); - - assertThat(details.getSelectedFolder()).isEqualTo(DocumentAmendFolder.PROPERTY_DOCUMENTS); - } -} diff --git a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java index 4634d135ee..df6d362956 100644 --- a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java +++ b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java @@ -135,6 +135,48 @@ void shouldPopulateDocumentsForSelectedCategoryAndIncludeWithoutNoticeApplicatio .containsExactly("visible application.pdf", "without notice application.pdf"); } + @Test + void shouldSetOnlySelectedFolderDisplayFlag() { + when(pcsCaseService.loadCase(CASE_REFERENCE)).thenReturn(PcsCaseEntity.builder().build()); + PCSCase caseData = PCSCase.builder() + .documentAmendDetails(DocumentAmendDetails.builder() + .selectedFolder(selectedFolder(APPLICATIONS)) + .build()) + .build(); + + underTest.initialise(CASE_REFERENCE, caseData); + + DocumentAmendDetails details = caseData.getDocumentAmendDetails(); + assertThat(details.getShowApplications()).isEqualTo(YesOrNo.YES); + assertThat(details.getShowStatementsOfCase()).isEqualTo(YesOrNo.NO); + assertThat(details.getShowPropertyDocuments()).isEqualTo(YesOrNo.NO); + assertThat(details.getShowEvidence()).isEqualTo(YesOrNo.NO); + assertThat(details.getShowHearingDocuments()).isEqualTo(YesOrNo.NO); + assertThat(details.getShowOrdersAndNoticeOfHearings()).isEqualTo(YesOrNo.NO); + assertThat(details.getShowAppeals()).isEqualTo(YesOrNo.NO); + assertThat(details.getShowCorrespondence()).isEqualTo(YesOrNo.NO); + assertThat(details.getShowUncategorisedDocuments()).isEqualTo(YesOrNo.NO); + } + + @Test + void shouldClearFolderDisplayFlagsWhenNoFolderSelected() { + when(pcsCaseService.loadCase(CASE_REFERENCE)).thenReturn(PcsCaseEntity.builder().build()); + PCSCase caseData = PCSCase.builder().build(); + + underTest.initialise(CASE_REFERENCE, caseData); + + DocumentAmendDetails details = caseData.getDocumentAmendDetails(); + assertThat(details.getShowStatementsOfCase()).isEqualTo(YesOrNo.NO); + assertThat(details.getShowPropertyDocuments()).isEqualTo(YesOrNo.NO); + assertThat(details.getShowEvidence()).isEqualTo(YesOrNo.NO); + assertThat(details.getShowHearingDocuments()).isEqualTo(YesOrNo.NO); + assertThat(details.getShowOrdersAndNoticeOfHearings()).isEqualTo(YesOrNo.NO); + assertThat(details.getShowApplications()).isEqualTo(YesOrNo.NO); + assertThat(details.getShowAppeals()).isEqualTo(YesOrNo.NO); + assertThat(details.getShowCorrespondence()).isEqualTo(YesOrNo.NO); + assertThat(details.getShowUncategorisedDocuments()).isEqualTo(YesOrNo.NO); + } + @Test void shouldOnlyShowDocumentsWithUncategorisedCategoryUnderUncategorisedDocuments() { DocumentEntity uncategorisedDocument = document("loose document.pdf", null, null); From 265e23bc2349825710ba431d622f158cab80ae24 Mon Sep 17 00:00:00 2001 From: sadmanrahman Date: Wed, 1 Jul 2026 11:55:48 +0100 Subject: [PATCH 20/70] HDPI-7308: select second question working --- .../documentamend/DocumentAmendDetails.java | 27 ------------ .../documentamend/SelectDocumentPage.java | 28 +------------ .../DocumentAmendSelectionService.java | 27 ------------ .../DocumentAmendSelectionServiceTest.java | 42 ------------------- 4 files changed, 2 insertions(+), 122 deletions(-) diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendDetails.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendDetails.java index 948dd57f19..c14b3e21a0 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendDetails.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendDetails.java @@ -124,33 +124,6 @@ public class DocumentAmendDetails { @CCD(searchable = false) private YesOrNo uncategorisedDocumentsEmpty; - @CCD(searchable = false) - private YesOrNo showStatementsOfCase; - - @CCD(searchable = false) - private YesOrNo showPropertyDocuments; - - @CCD(searchable = false) - private YesOrNo showEvidence; - - @CCD(searchable = false) - private YesOrNo showHearingDocuments; - - @CCD(searchable = false) - private YesOrNo showOrdersAndNoticeOfHearings; - - @CCD(searchable = false) - private YesOrNo showApplications; - - @CCD(searchable = false) - private YesOrNo showAppeals; - - @CCD(searchable = false) - private YesOrNo showCorrespondence; - - @CCD(searchable = false) - private YesOrNo showUncategorisedDocuments; - @CCD(searchable = false) private String selectedFolderId; diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java index ce799814f6..9a78373b73 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java @@ -23,7 +23,6 @@ public class SelectDocumentPage implements CcdPageConfiguration { private static final String PAGE_ID = "selectDocument"; private static final String FIELD_PREFIX = "documentAmend_"; private static final String YES = "=\"Yes\""; - private static final String NO = "=\"No\""; private final DocumentAmendSelectionService documentAmendSelectionService; @@ -107,15 +106,6 @@ public void addTo(PageBuilder pageBuilder) { .readonly(DocumentAmendDetails::getAppealsEmpty, NEVER_SHOW, true) .readonly(DocumentAmendDetails::getCorrespondenceEmpty, NEVER_SHOW, true) .readonly(DocumentAmendDetails::getUncategorisedDocumentsEmpty, NEVER_SHOW, true) - .readonly(DocumentAmendDetails::getShowStatementsOfCase, NEVER_SHOW, true) - .readonly(DocumentAmendDetails::getShowPropertyDocuments, NEVER_SHOW, true) - .readonly(DocumentAmendDetails::getShowEvidence, NEVER_SHOW, true) - .readonly(DocumentAmendDetails::getShowHearingDocuments, NEVER_SHOW, true) - .readonly(DocumentAmendDetails::getShowOrdersAndNoticeOfHearings, NEVER_SHOW, true) - .readonly(DocumentAmendDetails::getShowApplications, NEVER_SHOW, true) - .readonly(DocumentAmendDetails::getShowAppeals, NEVER_SHOW, true) - .readonly(DocumentAmendDetails::getShowCorrespondence, NEVER_SHOW, true) - .readonly(DocumentAmendDetails::getShowUncategorisedDocuments, NEVER_SHOW, true) .readonly(DocumentAmendDetails::getSelectedFolderId, NEVER_SHOW, true) .readonly(DocumentAmendDetails::getSelectedFolderLabel, NEVER_SHOW, true) .readonly(DocumentAmendDetails::getSelectedDocumentId, NEVER_SHOW, true) @@ -137,7 +127,7 @@ private AboutToStartOrSubmitResponse midEvent(CaseDetails FIELD_PREFIX + "ShowStatementsOfCase"; - case PROPERTY_DOCUMENTS -> FIELD_PREFIX + "ShowPropertyDocuments"; - case EVIDENCE -> FIELD_PREFIX + "ShowEvidence"; - case HEARING_DOCUMENTS -> FIELD_PREFIX + "ShowHearingDocuments"; - case ORDERS_AND_NOTICE_OF_HEARINGS -> FIELD_PREFIX + "ShowOrdersAndNoticeOfHearings"; - case APPLICATIONS -> FIELD_PREFIX + "ShowApplications"; - case APPEALS -> FIELD_PREFIX + "ShowAppeals"; - case CORRESPONDENCE -> FIELD_PREFIX + "ShowCorrespondence"; - case UNCATEGORISED_DOCUMENTS -> FIELD_PREFIX + "ShowUncategorisedDocuments"; - }; - } - private String noDocumentsMessage(CaseFileCategory category) { return "No documents in '" + category.getLabel() + "'"; } diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionService.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionService.java index 106c3b4981..f0d3e6d7ff 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionService.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionService.java @@ -55,7 +55,6 @@ public void initialise(long caseReference, PCSCase caseData) { setDocumentsForCategory(details, pcsCase, CaseFileCategory.APPEALS); setDocumentsForCategory(details, pcsCase, CaseFileCategory.CORRESPONDENCE); setDocumentsForCategory(details, pcsCase, CaseFileCategory.UNCATEGORISED_DOCUMENTS); - setSelectedFolderDisplayFlags(details); } public List validateAndStoreSelection(PCSCase caseData) { @@ -196,30 +195,4 @@ private void setEmptyForCategory(DocumentAmendDetails details, CaseFileCategory case UNCATEGORISED_DOCUMENTS -> details.setUncategorisedDocumentsEmpty(empty); } } - - private void setSelectedFolderDisplayFlags(DocumentAmendDetails details) { - CaseFileCategory selectedCategory = details.getSelectedFolder() == null - ? null - : details.getSelectedFolder().getCategory(); - - details.setShowStatementsOfCase(showSelectedFolder(selectedCategory, CaseFileCategory.STATEMENTS_OF_CASE)); - details.setShowPropertyDocuments(showSelectedFolder(selectedCategory, CaseFileCategory.PROPERTY_DOCUMENTS)); - details.setShowEvidence(showSelectedFolder(selectedCategory, CaseFileCategory.EVIDENCE)); - details.setShowHearingDocuments(showSelectedFolder(selectedCategory, CaseFileCategory.HEARING_DOCUMENTS)); - details.setShowOrdersAndNoticeOfHearings(showSelectedFolder( - selectedCategory, - CaseFileCategory.ORDERS_AND_NOTICE_OF_HEARINGS - )); - details.setShowApplications(showSelectedFolder(selectedCategory, CaseFileCategory.APPLICATIONS)); - details.setShowAppeals(showSelectedFolder(selectedCategory, CaseFileCategory.APPEALS)); - details.setShowCorrespondence(showSelectedFolder(selectedCategory, CaseFileCategory.CORRESPONDENCE)); - details.setShowUncategorisedDocuments(showSelectedFolder( - selectedCategory, - CaseFileCategory.UNCATEGORISED_DOCUMENTS - )); - } - - private YesOrNo showSelectedFolder(CaseFileCategory selectedCategory, CaseFileCategory category) { - return YesOrNo.from(category == selectedCategory); - } } diff --git a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java index df6d362956..4634d135ee 100644 --- a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java +++ b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java @@ -135,48 +135,6 @@ void shouldPopulateDocumentsForSelectedCategoryAndIncludeWithoutNoticeApplicatio .containsExactly("visible application.pdf", "without notice application.pdf"); } - @Test - void shouldSetOnlySelectedFolderDisplayFlag() { - when(pcsCaseService.loadCase(CASE_REFERENCE)).thenReturn(PcsCaseEntity.builder().build()); - PCSCase caseData = PCSCase.builder() - .documentAmendDetails(DocumentAmendDetails.builder() - .selectedFolder(selectedFolder(APPLICATIONS)) - .build()) - .build(); - - underTest.initialise(CASE_REFERENCE, caseData); - - DocumentAmendDetails details = caseData.getDocumentAmendDetails(); - assertThat(details.getShowApplications()).isEqualTo(YesOrNo.YES); - assertThat(details.getShowStatementsOfCase()).isEqualTo(YesOrNo.NO); - assertThat(details.getShowPropertyDocuments()).isEqualTo(YesOrNo.NO); - assertThat(details.getShowEvidence()).isEqualTo(YesOrNo.NO); - assertThat(details.getShowHearingDocuments()).isEqualTo(YesOrNo.NO); - assertThat(details.getShowOrdersAndNoticeOfHearings()).isEqualTo(YesOrNo.NO); - assertThat(details.getShowAppeals()).isEqualTo(YesOrNo.NO); - assertThat(details.getShowCorrespondence()).isEqualTo(YesOrNo.NO); - assertThat(details.getShowUncategorisedDocuments()).isEqualTo(YesOrNo.NO); - } - - @Test - void shouldClearFolderDisplayFlagsWhenNoFolderSelected() { - when(pcsCaseService.loadCase(CASE_REFERENCE)).thenReturn(PcsCaseEntity.builder().build()); - PCSCase caseData = PCSCase.builder().build(); - - underTest.initialise(CASE_REFERENCE, caseData); - - DocumentAmendDetails details = caseData.getDocumentAmendDetails(); - assertThat(details.getShowStatementsOfCase()).isEqualTo(YesOrNo.NO); - assertThat(details.getShowPropertyDocuments()).isEqualTo(YesOrNo.NO); - assertThat(details.getShowEvidence()).isEqualTo(YesOrNo.NO); - assertThat(details.getShowHearingDocuments()).isEqualTo(YesOrNo.NO); - assertThat(details.getShowOrdersAndNoticeOfHearings()).isEqualTo(YesOrNo.NO); - assertThat(details.getShowApplications()).isEqualTo(YesOrNo.NO); - assertThat(details.getShowAppeals()).isEqualTo(YesOrNo.NO); - assertThat(details.getShowCorrespondence()).isEqualTo(YesOrNo.NO); - assertThat(details.getShowUncategorisedDocuments()).isEqualTo(YesOrNo.NO); - } - @Test void shouldOnlyShowDocumentsWithUncategorisedCategoryUnderUncategorisedDocuments() { DocumentEntity uncategorisedDocument = document("loose document.pdf", null, null); From fa83e1bc25c5da4bce7acb5b22084c7ca8ecd775 Mon Sep 17 00:00:00 2001 From: sadmanrahman Date: Wed, 1 Jul 2026 14:24:55 +0100 Subject: [PATCH 21/70] HDPI-7308: radiobutton fixed --- .../documentamend/DocumentAmendDetails.java | 46 ++++++++++--- .../documentamend/SelectDocumentPage.java | 37 +++------- .../DocumentAmendSelectionService.java | 47 +++++++------ .../DocumentAmendSelectionServiceTest.java | 68 ++++++++++++++++--- 4 files changed, 132 insertions(+), 66 deletions(-) diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendDetails.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendDetails.java index c14b3e21a0..01c48908ab 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendDetails.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendDetails.java @@ -2,13 +2,14 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.annotation.JsonProperty; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; import uk.gov.hmcts.ccd.sdk.api.CCD; +import uk.gov.hmcts.ccd.sdk.type.DynamicList; import uk.gov.hmcts.ccd.sdk.type.YesOrNo; -import uk.gov.hmcts.reform.pcs.ccd.type.DynamicStringList; import static uk.gov.hmcts.ccd.sdk.type.FieldType.DynamicRadioList; import static uk.gov.hmcts.ccd.sdk.type.FieldType.FixedList; @@ -26,12 +27,15 @@ public class DocumentAmendDetails { typeOverride = FixedList, typeParameterOverride = "DocumentAmendFolder" ) + @JsonProperty("SelectedFolder") private DocumentAmendFolder selectedFolder; @CCD(searchable = false) + @JsonProperty("PropertyAddressSummary") private String propertyAddressSummary; @CCD(searchable = false) + @JsonProperty("PartyNamesSummary") private String partyNamesSummary; @CCD( @@ -39,100 +43,122 @@ public class DocumentAmendDetails { searchable = false, typeOverride = DynamicRadioList ) - private DynamicStringList statementsOfCaseDocuments; + @JsonProperty("StatementsOfCaseDocuments") + private DynamicList statementsOfCaseDocuments; @CCD( label = "Which document do you want to amend?", searchable = false, typeOverride = DynamicRadioList ) - private DynamicStringList propertyDocuments; + @JsonProperty("PropertyDocuments") + private DynamicList propertyDocuments; @CCD( label = "Which document do you want to amend?", searchable = false, typeOverride = DynamicRadioList ) - private DynamicStringList evidenceDocuments; + @JsonProperty("EvidenceDocuments") + private DynamicList evidenceDocuments; @CCD( label = "Which document do you want to amend?", searchable = false, typeOverride = DynamicRadioList ) - private DynamicStringList hearingDocuments; + @JsonProperty("HearingDocuments") + private DynamicList hearingDocuments; @CCD( label = "Which document do you want to amend?", searchable = false, typeOverride = DynamicRadioList ) - private DynamicStringList ordersAndNoticeOfHearingsDocuments; + @JsonProperty("OrdersAndNoticeOfHearingsDocuments") + private DynamicList ordersAndNoticeOfHearingsDocuments; @CCD( label = "Which document do you want to amend?", searchable = false, typeOverride = DynamicRadioList ) - private DynamicStringList applicationsDocuments; + @JsonProperty("ApplicationsDocuments") + private DynamicList applicationsDocuments; @CCD( label = "Which document do you want to amend?", searchable = false, typeOverride = DynamicRadioList ) - private DynamicStringList appealsDocuments; + @JsonProperty("AppealsDocuments") + private DynamicList appealsDocuments; @CCD( label = "Which document do you want to amend?", searchable = false, typeOverride = DynamicRadioList ) - private DynamicStringList correspondenceDocuments; + @JsonProperty("CorrespondenceDocuments") + private DynamicList correspondenceDocuments; @CCD( label = "Which document do you want to amend?", searchable = false, typeOverride = DynamicRadioList ) - private DynamicStringList uncategorisedDocuments; + @JsonProperty("UncategorisedDocuments") + private DynamicList uncategorisedDocuments; @CCD(searchable = false) + @JsonProperty("StatementsOfCaseEmpty") private YesOrNo statementsOfCaseEmpty; @CCD(searchable = false) + @JsonProperty("PropertyDocumentsEmpty") private YesOrNo propertyDocumentsEmpty; @CCD(searchable = false) + @JsonProperty("EvidenceEmpty") private YesOrNo evidenceEmpty; @CCD(searchable = false) + @JsonProperty("HearingDocumentsEmpty") private YesOrNo hearingDocumentsEmpty; @CCD(searchable = false) + @JsonProperty("OrdersAndNoticeOfHearingsEmpty") private YesOrNo ordersAndNoticeOfHearingsEmpty; @CCD(searchable = false) + @JsonProperty("ApplicationsEmpty") private YesOrNo applicationsEmpty; @CCD(searchable = false) + @JsonProperty("AppealsEmpty") private YesOrNo appealsEmpty; @CCD(searchable = false) + @JsonProperty("CorrespondenceEmpty") private YesOrNo correspondenceEmpty; @CCD(searchable = false) + @JsonProperty("UncategorisedDocumentsEmpty") private YesOrNo uncategorisedDocumentsEmpty; @CCD(searchable = false) + @JsonProperty("SelectedFolderId") private String selectedFolderId; @CCD(searchable = false) + @JsonProperty("SelectedFolderLabel") private String selectedFolderLabel; @CCD(searchable = false) + @JsonProperty("SelectedDocumentId") private String selectedDocumentId; @CCD(searchable = false) + @JsonProperty("SelectedDocumentFileName") private String selectedDocumentFileName; } diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java index 9a78373b73..fbe5e303e4 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java @@ -23,7 +23,6 @@ public class SelectDocumentPage implements CcdPageConfiguration { private static final String PAGE_ID = "selectDocument"; private static final String FIELD_PREFIX = "documentAmend_"; private static final String YES = "=\"Yes\""; - private final DocumentAmendSelectionService documentAmendSelectionService; @Override @@ -42,58 +41,40 @@ public void addTo(PageBuilder pageBuilder) { .readonly(DocumentAmendDetails::getPartyNamesSummary, NEVER_SHOW, true) .mandatory(DocumentAmendDetails::getSelectedFolder) .mandatory(DocumentAmendDetails::getStatementsOfCaseDocuments, - documentsShowCondition(CaseFileCategory.STATEMENTS_OF_CASE)) - .label("statementsOfCaseNoDocumentsQuestion", "Which document do you want to amend?", - noDocumentsShowCondition(CaseFileCategory.STATEMENTS_OF_CASE)) + documentsShowCondition(CaseFileCategory.STATEMENTS_OF_CASE), true) .label("statementsOfCaseNoDocuments", noDocumentsMessage(CaseFileCategory.STATEMENTS_OF_CASE), noDocumentsShowCondition(CaseFileCategory.STATEMENTS_OF_CASE)) .mandatory(DocumentAmendDetails::getPropertyDocuments, - documentsShowCondition(CaseFileCategory.PROPERTY_DOCUMENTS)) - .label("propertyDocumentsNoDocumentsQuestion", "Which document do you want to amend?", - noDocumentsShowCondition(CaseFileCategory.PROPERTY_DOCUMENTS)) + documentsShowCondition(CaseFileCategory.PROPERTY_DOCUMENTS), true) .label("propertyDocumentsNoDocuments", noDocumentsMessage(CaseFileCategory.PROPERTY_DOCUMENTS), noDocumentsShowCondition(CaseFileCategory.PROPERTY_DOCUMENTS)) .mandatory(DocumentAmendDetails::getEvidenceDocuments, - documentsShowCondition(CaseFileCategory.EVIDENCE)) - .label("evidenceNoDocumentsQuestion", "Which document do you want to amend?", - noDocumentsShowCondition(CaseFileCategory.EVIDENCE)) + documentsShowCondition(CaseFileCategory.EVIDENCE), true) .label("evidenceNoDocuments", noDocumentsMessage(CaseFileCategory.EVIDENCE), noDocumentsShowCondition(CaseFileCategory.EVIDENCE)) .mandatory(DocumentAmendDetails::getHearingDocuments, - documentsShowCondition(CaseFileCategory.HEARING_DOCUMENTS)) - .label("hearingDocumentsNoDocumentsQuestion", "Which document do you want to amend?", - noDocumentsShowCondition(CaseFileCategory.HEARING_DOCUMENTS)) + documentsShowCondition(CaseFileCategory.HEARING_DOCUMENTS), true) .label("hearingDocumentsNoDocuments", noDocumentsMessage(CaseFileCategory.HEARING_DOCUMENTS), noDocumentsShowCondition(CaseFileCategory.HEARING_DOCUMENTS)) .mandatory(DocumentAmendDetails::getOrdersAndNoticeOfHearingsDocuments, - documentsShowCondition(CaseFileCategory.ORDERS_AND_NOTICE_OF_HEARINGS)) - .label("ordersAndNoticeOfHearingsNoDocumentsQuestion", "Which document do you want to amend?", - noDocumentsShowCondition(CaseFileCategory.ORDERS_AND_NOTICE_OF_HEARINGS)) + documentsShowCondition(CaseFileCategory.ORDERS_AND_NOTICE_OF_HEARINGS), true) .label("ordersAndNoticeOfHearingsNoDocuments", noDocumentsMessage(CaseFileCategory.ORDERS_AND_NOTICE_OF_HEARINGS), noDocumentsShowCondition(CaseFileCategory.ORDERS_AND_NOTICE_OF_HEARINGS)) .mandatory(DocumentAmendDetails::getApplicationsDocuments, - documentsShowCondition(CaseFileCategory.APPLICATIONS)) - .label("applicationsNoDocumentsQuestion", "Which document do you want to amend?", - noDocumentsShowCondition(CaseFileCategory.APPLICATIONS)) + documentsShowCondition(CaseFileCategory.APPLICATIONS), true) .label("applicationsNoDocuments", noDocumentsMessage(CaseFileCategory.APPLICATIONS), noDocumentsShowCondition(CaseFileCategory.APPLICATIONS)) .mandatory(DocumentAmendDetails::getAppealsDocuments, - documentsShowCondition(CaseFileCategory.APPEALS)) - .label("appealsNoDocumentsQuestion", "Which document do you want to amend?", - noDocumentsShowCondition(CaseFileCategory.APPEALS)) + documentsShowCondition(CaseFileCategory.APPEALS), true) .label("appealsNoDocuments", noDocumentsMessage(CaseFileCategory.APPEALS), noDocumentsShowCondition(CaseFileCategory.APPEALS)) .mandatory(DocumentAmendDetails::getCorrespondenceDocuments, - documentsShowCondition(CaseFileCategory.CORRESPONDENCE)) - .label("correspondenceNoDocumentsQuestion", "Which document do you want to amend?", - noDocumentsShowCondition(CaseFileCategory.CORRESPONDENCE)) + documentsShowCondition(CaseFileCategory.CORRESPONDENCE), true) .label("correspondenceNoDocuments", noDocumentsMessage(CaseFileCategory.CORRESPONDENCE), noDocumentsShowCondition(CaseFileCategory.CORRESPONDENCE)) .mandatory(DocumentAmendDetails::getUncategorisedDocuments, - documentsShowCondition(CaseFileCategory.UNCATEGORISED_DOCUMENTS)) - .label("uncategorisedDocumentsNoDocumentsQuestion", "Which document do you want to amend?", - noDocumentsShowCondition(CaseFileCategory.UNCATEGORISED_DOCUMENTS)) + documentsShowCondition(CaseFileCategory.UNCATEGORISED_DOCUMENTS), true) .label("uncategorisedDocumentsNoDocuments", noDocumentsMessage(CaseFileCategory.UNCATEGORISED_DOCUMENTS), noDocumentsShowCondition(CaseFileCategory.UNCATEGORISED_DOCUMENTS)) diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionService.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionService.java index f0d3e6d7ff..c2c18b72e0 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionService.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionService.java @@ -2,6 +2,8 @@ import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; +import uk.gov.hmcts.ccd.sdk.type.DynamicList; +import uk.gov.hmcts.ccd.sdk.type.DynamicListElement; import uk.gov.hmcts.ccd.sdk.type.YesOrNo; import uk.gov.hmcts.reform.pcs.ccd.domain.CaseFileCategory; import uk.gov.hmcts.reform.pcs.ccd.domain.PCSCase; @@ -10,8 +12,6 @@ import uk.gov.hmcts.reform.pcs.ccd.entity.PcsCaseEntity; import uk.gov.hmcts.reform.pcs.ccd.service.CaseNameFormatter; import uk.gov.hmcts.reform.pcs.ccd.service.PcsCaseService; -import uk.gov.hmcts.reform.pcs.ccd.type.DynamicStringList; -import uk.gov.hmcts.reform.pcs.ccd.type.DynamicStringListElement; import uk.gov.hmcts.reform.pcs.ccd.util.AddressFormatter; import java.util.Comparator; @@ -64,7 +64,7 @@ public List validateAndStoreSelection(PCSCase caseData) { } CaseFileCategory selectedFolder = details.getSelectedFolder().getCategory(); - DynamicStringList selectedDocuments = documentsForCategory(details, selectedFolder); + DynamicList selectedDocuments = documentsForCategory(details, selectedFolder); details.setSelectedFolderId(selectedFolder.getId()); details.setSelectedFolderLabel(selectedFolder.getLabel()); @@ -74,43 +74,43 @@ public List validateAndStoreSelection(PCSCase caseData) { return List.of(SELECT_DIFFERENT_FOLDER_ERROR); } - DynamicStringListElement selectedDocument = selectedDocuments.getValue(); + DynamicListElement selectedDocument = selectedDocuments.getValue(); if (selectedDocument == null || selectedDocument.getCode() == null) { details.setSelectedDocumentId(null); details.setSelectedDocumentFileName(null); return List.of(); } - details.setSelectedDocumentId(selectedDocument.getCode()); + details.setSelectedDocumentId(selectedDocument.getCode().toString()); details.setSelectedDocumentFileName(selectedDocument.getLabel()); return List.of(); } private void setDocumentsForCategory(DocumentAmendDetails details, PcsCaseEntity pcsCase, CaseFileCategory category) { - DynamicStringList documents = documentList(pcsCase, category, documentsForCategory(details, category)); + DynamicList documents = documentList(pcsCase, category, documentsForCategory(details, category)); applyDocumentsForCategory(details, category, documents); setEmptyForCategory(details, category, YesOrNo.from(isEmpty(documents))); } - private DynamicStringList documentList(PcsCaseEntity pcsCase, CaseFileCategory category, - DynamicStringList existingList) { - DynamicStringListElement selected = existingList == null ? null : existingList.getValue(); + private DynamicList documentList(PcsCaseEntity pcsCase, CaseFileCategory category, + DynamicList existingList) { + DynamicListElement selected = existingList == null ? null : existingList.getValue(); - List documents = CollectionUtils.isEmpty(pcsCase.getDocuments()) + List documents = CollectionUtils.isEmpty(pcsCase.getDocuments()) ? List.of() : pcsCase.getDocuments().stream() .filter(Objects::nonNull) .filter(document -> isInCategory(document, category)) .sorted(DOCUMENT_ORDER) - .map(document -> DynamicStringListElement.builder() - .code(document.getId().toString()) + .map(document -> DynamicListElement.builder() + .code(document.getId()) .label(document.getFileName()) .build()) .toList(); - return DynamicStringList.builder() - .value(retainSelectedValue(selected, documents)) + return DynamicList.builder() + .value(selectedValue(selected, documents)) .listItems(documents) .build(); } @@ -119,8 +119,8 @@ private boolean isInCategory(DocumentEntity document, CaseFileCategory category) return category.getId().equals(document.getCategoryId()); } - private DynamicStringListElement retainSelectedValue(DynamicStringListElement selected, - List options) { + private DynamicListElement retainSelectedValue(DynamicListElement selected, + List options) { if (selected == null || selected.getCode() == null) { return null; } @@ -131,7 +131,16 @@ private DynamicStringListElement retainSelectedValue(DynamicStringListElement se .orElse(null); } - private boolean isEmpty(DynamicStringList documents) { + private DynamicListElement selectedValue(DynamicListElement selected, + List options) { + DynamicListElement retainedSelectedValue = retainSelectedValue(selected, options); + if (retainedSelectedValue != null) { + return retainedSelectedValue; + } + return options.isEmpty() ? null : DynamicListElement.EMPTY; + } + + private boolean isEmpty(DynamicList documents) { return documents == null || CollectionUtils.isEmpty(documents.getListItems()); } @@ -153,7 +162,7 @@ private DocumentAmendDetails getOrCreateDetails(PCSCase caseData) { return caseData.getDocumentAmendDetails(); } - private DynamicStringList documentsForCategory(DocumentAmendDetails details, CaseFileCategory category) { + private DynamicList documentsForCategory(DocumentAmendDetails details, CaseFileCategory category) { return switch (category) { case STATEMENTS_OF_CASE -> details.getStatementsOfCaseDocuments(); case PROPERTY_DOCUMENTS -> details.getPropertyDocuments(); @@ -168,7 +177,7 @@ private DynamicStringList documentsForCategory(DocumentAmendDetails details, Cas } private void applyDocumentsForCategory(DocumentAmendDetails details, CaseFileCategory category, - DynamicStringList documents) { + DynamicList documents) { switch (category) { case STATEMENTS_OF_CASE -> details.setStatementsOfCaseDocuments(documents); case PROPERTY_DOCUMENTS -> details.setPropertyDocuments(documents); diff --git a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java index 4634d135ee..bfa5337a60 100644 --- a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java +++ b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java @@ -1,10 +1,14 @@ package uk.gov.hmcts.reform.pcs.ccd.service.document; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import uk.gov.hmcts.ccd.sdk.type.DynamicList; +import uk.gov.hmcts.ccd.sdk.type.DynamicListElement; import uk.gov.hmcts.ccd.sdk.type.YesOrNo; import uk.gov.hmcts.reform.pcs.ccd.domain.CaseFileCategory; import uk.gov.hmcts.reform.pcs.ccd.domain.PCSCase; @@ -17,8 +21,6 @@ import uk.gov.hmcts.reform.pcs.ccd.entity.PcsCaseEntity; import uk.gov.hmcts.reform.pcs.ccd.service.CaseNameFormatter; import uk.gov.hmcts.reform.pcs.ccd.service.PcsCaseService; -import uk.gov.hmcts.reform.pcs.ccd.type.DynamicStringList; -import uk.gov.hmcts.reform.pcs.ccd.type.DynamicStringListElement; import uk.gov.hmcts.reform.pcs.ccd.util.AddressFormatter; import java.time.Instant; @@ -85,6 +87,29 @@ void shouldPopulateCompactCaseSummaryFields() { .isEqualTo("Treetops Housing vs Billy Wright"); } + @Test + void shouldSerialiseDocumentAmendFieldsWithGeneratedCcdFieldIds() throws JsonProcessingException { + DynamicList applicationsDocuments = DynamicList.builder() + .value(DynamicListElement.EMPTY) + .listItems(List.of(DynamicListElement.builder() + .code(UUID.randomUUID()) + .label("application.pdf") + .build())) + .build(); + PCSCase caseData = PCSCase.builder() + .documentAmendDetails(DocumentAmendDetails.builder() + .applicationsDocuments(applicationsDocuments) + .applicationsEmpty(YesOrNo.NO) + .build()) + .build(); + + String serialisedCaseData = new ObjectMapper().writeValueAsString(caseData); + + assertThat(serialisedCaseData).contains("\"documentAmend_ApplicationsDocuments\""); + assertThat(serialisedCaseData).contains("\"documentAmend_ApplicationsEmpty\""); + assertThat(serialisedCaseData).doesNotContain("documentAmend_applicationsDocuments"); + } + @Test void shouldPopulatePartyNamesSummaryFromPartyCollectionsWhenSummaryFieldsAreMissing() { when(pcsCaseService.loadCase(CASE_REFERENCE)).thenReturn(PcsCaseEntity.builder().build()); @@ -128,11 +153,13 @@ void shouldPopulateDocumentsForSelectedCategoryAndIncludeWithoutNoticeApplicatio DocumentAmendDetails details = caseData.getDocumentAmendDetails(); assertThat(details.getEvidenceDocuments().getListItems()) - .extracting(DynamicStringListElement::getLabel) + .extracting(DynamicListElement::getLabel) .containsExactly("visible evidence.pdf"); assertThat(details.getApplicationsDocuments().getListItems()) - .extracting(DynamicStringListElement::getLabel) + .extracting(DynamicListElement::getLabel) .containsExactly("visible application.pdf", "without notice application.pdf"); + assertThat(details.getApplicationsDocuments().getValue()).isNotNull(); + assertThat(details.getApplicationsDocuments().getValue().getCode()).isNull(); } @Test @@ -151,7 +178,7 @@ void shouldOnlyShowDocumentsWithUncategorisedCategoryUnderUncategorisedDocuments underTest.initialise(CASE_REFERENCE, caseData); assertThat(caseData.getDocumentAmendDetails().getUncategorisedDocuments().getListItems()) - .extracting(DynamicStringListElement::getLabel) + .extracting(DynamicListElement::getLabel) .containsExactly("uncategorised document.pdf"); assertThat(caseData.getDocumentAmendDetails().getUncategorisedDocumentsEmpty()).isEqualTo(YesOrNo.NO); } @@ -172,6 +199,29 @@ void shouldReturnDifferentFolderErrorWhenSelectedFolderHasNoDocuments() { assertThat(caseData.getDocumentAmendDetails().getSelectedDocumentId()).isNull(); } + @Test + void shouldTreatEmptyDocumentSelectionAsNoSelection() { + DocumentEntity document = document("photo.pdf", EVIDENCE.getId(), null); + when(pcsCaseService.loadCase(CASE_REFERENCE)).thenReturn(PcsCaseEntity.builder() + .documents(List.of(document)) + .build()); + PCSCase caseData = PCSCase.builder() + .documentAmendDetails(DocumentAmendDetails.builder() + .selectedFolder(selectedFolder(EVIDENCE)) + .evidenceDocuments(DynamicList.builder() + .value(DynamicListElement.EMPTY) + .build()) + .build()) + .build(); + underTest.initialise(CASE_REFERENCE, caseData); + + List errors = underTest.validateAndStoreSelection(caseData); + + assertThat(errors).isEmpty(); + assertThat(caseData.getDocumentAmendDetails().getSelectedDocumentId()).isNull(); + assertThat(caseData.getDocumentAmendDetails().getSelectedDocumentFileName()).isNull(); + } + @Test void shouldPersistSelectedFolderAndDocumentDetails() { DocumentEntity document = document("photo.pdf", EVIDENCE.getId(), null); @@ -228,13 +278,13 @@ private static DocumentAmendFolder selectedFolder(CaseFileCategory category) { }; } - private static DynamicStringList selectedDocument(DocumentEntity document) { - DynamicStringListElement selectedDocument = DynamicStringListElement.builder() - .code(document.getId().toString()) + private static DynamicList selectedDocument(DocumentEntity document) { + DynamicListElement selectedDocument = DynamicListElement.builder() + .code(document.getId()) .label(document.getFileName()) .build(); - return DynamicStringList.builder() + return DynamicList.builder() .value(selectedDocument) .listItems(List.of(selectedDocument)) .build(); From 21272cbdb973f5644616a0220dc111a5193c89e6 Mon Sep 17 00:00:00 2001 From: sadmanrahman Date: Wed, 1 Jul 2026 16:12:31 +0100 Subject: [PATCH 22/70] HDPI-7308: page header fixed --- .../pcs/ccd/page/documentamend/SelectDocumentPage.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java index fbe5e303e4..521a992a09 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java @@ -30,15 +30,9 @@ public void addTo(PageBuilder pageBuilder) { pageBuilder .page(PAGE_ID, this::midEvent) .pageLabel("Select document") - .label(PAGE_ID + "-caseReference", "Case number: ${[CASE_REFERENCE]}") - .label(PAGE_ID + "-propertyAddress", "${documentAmend_PropertyAddressSummary}", - "documentAmend_PropertyAddressSummary!=\"\"") - .label(PAGE_ID + "-partyNames", "${documentAmend_PartyNamesSummary}", - "documentAmend_PartyNamesSummary!=\"\"") .label(PAGE_ID + "-separator", "---") .complex(PCSCase::getDocumentAmendDetails) .readonly(DocumentAmendDetails::getPropertyAddressSummary, NEVER_SHOW, true) - .readonly(DocumentAmendDetails::getPartyNamesSummary, NEVER_SHOW, true) .mandatory(DocumentAmendDetails::getSelectedFolder) .mandatory(DocumentAmendDetails::getStatementsOfCaseDocuments, documentsShowCondition(CaseFileCategory.STATEMENTS_OF_CASE), true) From 9825696031ec50628cb83d3860a8a114055b855b Mon Sep 17 00:00:00 2001 From: srinijg Date: Wed, 1 Jul 2026 16:17:26 +0100 Subject: [PATCH 23/70] new tests added --- src/e2eTest/data/api-data/index.ts | 2 + .../api-data/makeAnApplication.api.data.ts | 97 +++++++++++++++++++ .../makeAnApplicationEventToken.api.data.ts | 14 +++ .../data/api-data/submitCase.api.data.ts | 26 ++++- .../caseManagement.caseFileView.spec.ts | 53 ++++++++++ .../custom-actions/createCase.action.ts | 45 +++++++-- .../custom-actions/createCaseAPI.action.ts | 58 ++++++++++- src/e2eTest/utils/registry/action.registry.ts | 1 + 8 files changed, 282 insertions(+), 14 deletions(-) create mode 100644 src/e2eTest/data/api-data/makeAnApplication.api.data.ts create mode 100644 src/e2eTest/data/api-data/makeAnApplicationEventToken.api.data.ts create mode 100644 src/e2eTest/tests/test-caseManagement/caseManagement.caseFileView.spec.ts diff --git a/src/e2eTest/data/api-data/index.ts b/src/e2eTest/data/api-data/index.ts index e7e46c2a6e..d685620812 100644 --- a/src/e2eTest/data/api-data/index.ts +++ b/src/e2eTest/data/api-data/index.ts @@ -9,3 +9,5 @@ export * from '@data/api-data/getCase.api.data'; export * from '@data/api-data/createCaseEventTokenDynamic.api.data'; export * from '@data/api-data/submitCaseEventTokenDynamic.api.data'; export * from '@data/api-data/backDateTheCasePayment.api.data'; +export * from '@data/api-data/makeAnApplication.api.data'; +export * from '@data/api-data/makeAnApplicationEventToken.api.data'; diff --git a/src/e2eTest/data/api-data/makeAnApplication.api.data.ts b/src/e2eTest/data/api-data/makeAnApplication.api.data.ts new file mode 100644 index 0000000000..6626b3012c --- /dev/null +++ b/src/e2eTest/data/api-data/makeAnApplication.api.data.ts @@ -0,0 +1,97 @@ +export const makeAnApplicationApiData = { + + makeAnApplicationEventName: 'makeAnApplication', + makeAnApplicationAdjournPayload: (defendantId: string, defendantName: string) => ( + { + currentRepresentedPartyId: defendantId, + currentRepresentedPartyName: defendantName, + xui_genapp_StandardFee: '£123', + xui_genapp_MaxFee: '£313', + xui_genapp_ShowHwfScreens: 'YES', + xui_genapp_ApplicationType: 'ADJOURN', + multipleRepresentedParties: 'YES', + representedPartyNames: { + value: { + code: defendantId, + label: defendantName + }, + valueCode: defendantId, + valueLabel: defendantName + }, + xui_genapp_Within14Days: 'YES', + xui_genapp_NeedHwf: 'YES', + xui_genapp_AppliedForHwf: 'YES', + xui_genapp_HwfReference: 'EmHCkHbPkf', + xui_genapp_OtherPartiesAgreed: 'YES', + xui_genapp_WhatOrderWanted: 'test user input', + xui_genapp_HasSupportingDocuments: 'YES', + xui_genapp_UploadedDocuments: [ + { + value: { + documentType: 'WITNESS_STATEMENT', + contentType: null, + sizeInBytes: null, + document: { + document_url: `${process.env.DM_STORE}/documents/079b5999-5876-4bd9-9695-9147f4ded099`, + document_binary_url: `${process.env.DM_STORE}/documents/079b5999-5876-4bd9-9695-9147f4ded099/binary`, + document_filename: 'witnessStatement.pdf', + } + }, + id: null + }, + { + value: { + documentType: 'RENT_STATEMENT', + contentType: null, + sizeInBytes: null, + document: { + document_url: `${process.env.DM_STORE}/documents/103362f6-f2bb-47ad-ac71-97a5036d808c`, + document_binary_url: `${process.env.DM_STORE}/documents/103362f6-f2bb-47ad-ac71-97a5036d808c/binary`, + document_filename: `rentStatement.pdf`, + } + }, + id: null + }, + { + value: { + documentType: 'TENANCY_AGREEMENT', + contentType: null, + sizeInBytes: null, + document: { + document_url: `${process.env.DM_STORE}/documents/7ea36f71-b935-4cd0-8205-3332a4b4c8a7`, + document_binary_url: `${process.env.DM_STORE}/documents/7ea36f71-b935-4cd0-8205-3332a4b4c8a7/binary`, + document_filename: 'tenancy.pdf', + + } + }, + id: null + }, + { + value: { + documentType: 'OTHER', + contentType: null, + sizeInBytes: null, + document: { + document_url: `${process.env.DM_STORE}/documents/9a1694f1-d38c-4b6b-9ca5-4a61ce554fdd`, + document_binary_url: `${process.env.DM_STORE}/documents/9a1694f1-d38c-4b6b-9ca5-4a61ce554fdd/binary`, + document_filename: 'otherDocument.pdf', + } + }, + id: null + } + ], + xui_genapp_LanguageUsed: 'ENGLISH', + xui_genapp_AgreementDefendantLegalRep: [ + 'AGREED' + ], + xui_genapp_SotFullName: 'James Anderson', + xui_genapp_SotFirmName: 'Doe & Co Solicitors', + xui_genapp_SotPositionHeld: 'Solicitor' + + + + }), + + makeAnApplicationApiEndPoint: () => + `/cases/${process.env.CASE_NUMBER}/events`, +} diff --git a/src/e2eTest/data/api-data/makeAnApplicationEventToken.api.data.ts b/src/e2eTest/data/api-data/makeAnApplicationEventToken.api.data.ts new file mode 100644 index 0000000000..abbfd2f27c --- /dev/null +++ b/src/e2eTest/data/api-data/makeAnApplicationEventToken.api.data.ts @@ -0,0 +1,14 @@ +export const makeAnApplicationEventTokenApiData = { + makeAnApplicationEventTokenApiInstance: () => ({ + baseURL: process.env.DATA_STORE_URL_BASE, + headers: { + Authorization: `Bearer ${process.env.SOLICITOR_ACCESS_TOKEN}`, + ServiceAuthorization: `Bearer ${process.env.SERVICE_AUTH_TOKEN}`, + 'Content-Type': 'application/json', + 'experimental': 'experimental', + 'Accept': '*/*', + } + }), + makeAnApplicationEventTokenApiEndPoint: () => + `/cases/${process.env.CASE_NUMBER}/event-triggers/makeAnApplication`, +}; \ No newline at end of file diff --git a/src/e2eTest/data/api-data/submitCase.api.data.ts b/src/e2eTest/data/api-data/submitCase.api.data.ts index ea277a95f4..98cbb3caa8 100644 --- a/src/e2eTest/data/api-data/submitCase.api.data.ts +++ b/src/e2eTest/data/api-data/submitCase.api.data.ts @@ -681,8 +681,8 @@ export const submitCaseApiData = { claimantProvidePhoneNumber: 'NO', defendant1: { nameKnown: 'YES', - firstName: 'peter', - lastName: 'parker', + firstName: 'John', + lastName: 'Doe', addressKnown: 'NO', addressSameAsPossession: null, correspondenceAddress: { @@ -696,6 +696,28 @@ export const submitCaseApiData = { } }, addAnotherDefendant: 'NO', + additionalDefendants: [ + { + value: { + nameKnown: 'YES', + firstName: 'Peter', + lastName: 'Parker', + addressKnown: 'YES', + addressSameAsPossession: 'YES' + }, + id: null + }, + { + value: { + nameKnown: 'YES', + firstName: 'Jen', + lastName: 'Parker', + addressKnown: 'YES', + addressSameAsPossession: 'YES' + }, + id: null + }, + ], tenancy_TypeOfTenancyLicence: 'ASSURED_TENANCY', tenancy_TenancyLicenceDate: '2013-01-01', tenancy_HasCopyOfTenancyLicence: 'YES', diff --git a/src/e2eTest/tests/test-caseManagement/caseManagement.caseFileView.spec.ts b/src/e2eTest/tests/test-caseManagement/caseManagement.caseFileView.spec.ts new file mode 100644 index 0000000000..22e41acda3 --- /dev/null +++ b/src/e2eTest/tests/test-caseManagement/caseManagement.caseFileView.spec.ts @@ -0,0 +1,53 @@ +import { createCaseApiData, makeAnApplicationApiData, submitCaseApiData } from '@data/api-data'; +import { initializeExecutor, performAction, performValidation } from '@utils/controller'; +import test, { expect } from '@playwright/test'; +import { getCaseTypeId } from '@utils/common/caseType.utils'; +import { VERY_LONG_TIMEOUT } from 'playwright.config'; +import { caseInfo, defendantUserDetails } from '@utils/actions/custom-actions'; +import { PageContentValidation } from '@utils/validations/element-validations/pageContent.validation'; +import { home } from '@data/page-data'; + + +test.beforeEach(async ({ page }) => { + initializeExecutor(page); + await performAction('createCaseAPI', { data: createCaseApiData.createCasePayload }); + await performAction('submitCaseAPI', { data: submitCaseApiData.submitCasePayloadCaseFileView }); + await performAction('getCaseAPI', 'Link Solicitor'); + + for (const defendant of defendantUserDetails) { + await performAction('makeAnApplicationAPI', { + data: makeAnApplicationApiData.makeAnApplicationAdjournPayload( + defendant.id, + defendant.name + ), + }); + }; + await performAction('navigateToUrl', `${process.env.MANAGE_CASE_BASE_URL}/cases/case-details/PCS/${getCaseTypeId()}/${process.env.CASE_NUMBER}#Summary`); + await expect(async () => { + await page.waitForURL(`${process.env.MANAGE_CASE_BASE_URL}/cases/case-details/PCS/${getCaseTypeId()}/${process.env.CASE_NUMBER}#Summary`, { waitUntil: 'domcontentloaded' }); + }).toPass({ + timeout: VERY_LONG_TIMEOUT, + }); + +}); + +test.afterEach(async () => { + if (caseInfo.id) { + await performAction('deleteCaseRole', '[CLAIMANTSOLICITOR]'); + } + PageContentValidation.finaliseTest(); + +}); + +test.describe('Case management - e2e Journey @nightly', async () => { + + test('Case management - CaseFile View test @PR @regression', async () => { + await performValidation('mainHeader', home.caseSummary) + await performAction('clickTab', home.caseFileView); + await performAction('validateCaseFileViewFolders', home.caseFileFolders); + await performAction('validateCaseFileViewIndividualFolder', { + folder: 'Applications', + submitPayload: makeAnApplicationApiData.makeAnApplicationAdjournPayload(defendantUserDetails[0].id,defendantUserDetails[0].name), + }); + }); +}); diff --git a/src/e2eTest/utils/actions/custom-actions/createCase.action.ts b/src/e2eTest/utils/actions/custom-actions/createCase.action.ts index 12accc9067..3417fb2e19 100644 --- a/src/e2eTest/utils/actions/custom-actions/createCase.action.ts +++ b/src/e2eTest/utils/actions/custom-actions/createCase.action.ts @@ -55,7 +55,7 @@ import { } from '@data/page-data-figma'; import {MEDIUM_TIMEOUT, SHORT_TIMEOUT, VERY_LONG_TIMEOUT} from 'playwright.config'; import {compareMaps} from '@utils/common/compareMaps.util'; -import {caseInfo} from './createCaseAPI.action'; +import {caseInfo, defendantUserDetails} from './createCaseAPI.action'; import {createCaseApiData} from '@data/api-data'; import {formatCaseStateText, formatCurrency, formatDate, formatDateTime, formatUploadDocName, formatText, formatWord} from '@utils/common/string.utils'; export let caseNumber: string; @@ -1583,15 +1583,16 @@ export class CreateCaseAction implements IAction { }); const folderRetrieved = (await folderLocator.allTextContents()).map(item => item.slice(1)); const folder:string[] = caseFileView as string[]; - expect(folder.every(name => folderRetrieved.some(text => text.includes(name)))).toBeTruthy(); - + + const missingFolders = folder.filter(name => !folderRetrieved.some(text => text.includes(name))); + expect(missingFolders, `Missing folders: ${missingFolders.join(", ")}`).toHaveLength(0); } public async validateCaseFileViewIndividualFolder(page: Page ,caseFile: actionRecord){ const folderName = caseFile.folder as string; let submitPayLoad = caseFile.submitPayload as Record; - const userInputFiles:string[]= []; + let userInputFiles:string[]= []; switch (folderName) { case 'Property documents': this.readDocFilesFromPayLoad(userInputFiles, submitPayLoad.tenancy_TenancyLicenceDocuments); @@ -1618,6 +1619,11 @@ export class CreateCaseAction implements IAction { case 'Uncategorised documents': this.readDocFilesFromPayLoad(userInputFiles, submitPayLoad.additionalDocuments, 'Other document'); break; + + case 'Applications': + this.readDocFilesFromPayLoad(userInputFiles, submitPayLoad.xui_genapp_UploadedDocuments, 'All Files'); + userInputFiles=this.cleanGenAppFilesArray(userInputFiles,defendantUserDetails.length); + break; default: break; @@ -1637,8 +1643,7 @@ export class CreateCaseAction implements IAction { const actualFileCount = await fileLocator.count(); expect(actualFileCount, 'File count matching').toEqual(fileCount) - const fileArray = this.cleanFilesArray(await fileLocator.allTextContents()); - + const fileArray = this.cleanFilesArray(await fileLocator.allTextContents()); expect(userInputFiles.sort(), `validating upload files for "${folderName}"`).toEqual(fileArray.sort()); console.log(`\n✅ The files under section "${folderName}" are \n "${fileArray}"`); @@ -1661,14 +1666,17 @@ export class CreateCaseAction implements IAction { public readDocFilesFromPayLoad(mainArray: string[], subArray: any[], multiDocsLabel?: string) { if (subArray && Array.isArray(subArray)) { - subArray.forEach(doc => { - if (multiDocsLabel) { + subArray.forEach(doc => { + if (multiDocsLabel && multiDocsLabel !== 'All Files') { const valueLabel = doc.value?.documentType?.valueLabel; const filename = doc.value?.document?.document_filename; if (multiDocsLabel === valueLabel && filename) { mainArray.push(filename); } - } else if (doc.value?.document_filename) { + } else if (multiDocsLabel && multiDocsLabel === 'All Files') { + mainArray.push(doc.value.document.document_filename) + } + else if (doc.value?.document_filename) { mainArray.push(doc.value.document_filename); } }); @@ -1779,4 +1787,23 @@ export class CreateCaseAction implements IAction { }); } + + public cleanGenAppFilesArray(filesArray: string[], defendantCount: number) : string[] { + const result: string[] = []; + + for (let i = 1; i <= defendantCount; i++) { + for (const file of filesArray) { + result.push( + file.replace(/\.pdf$/i, ` GA${i}.pdf`) + ); + } + + result.push(`General Application GA${i}.pdf`); + } + + return result; +} + + + } \ No newline at end of file diff --git a/src/e2eTest/utils/actions/custom-actions/createCaseAPI.action.ts b/src/e2eTest/utils/actions/custom-actions/createCaseAPI.action.ts index 785ba55b43..d3f3da25e6 100644 --- a/src/e2eTest/utils/actions/custom-actions/createCaseAPI.action.ts +++ b/src/e2eTest/utils/actions/custom-actions/createCaseAPI.action.ts @@ -1,7 +1,7 @@ import Axios from 'axios'; import { actionData, actionRecord, IAction } from '@utils/interfaces'; import { Page } from '@playwright/test'; -import { createCaseApiData, createCaseEventTokenApiData, submitCaseApiData, submitCaseEventTokenApiData, caseUserRoleDeletionApiData, enforceOrderEventTokenApiData, enforceWarrantApiData, getCaseApiData, submitCaseEventTokenDynamicApiData, createCaseEventTokenDynamicApiData } from '@data/api-data'; +import { createCaseApiData, createCaseEventTokenApiData, submitCaseApiData, submitCaseEventTokenApiData, caseUserRoleDeletionApiData, enforceOrderEventTokenApiData, enforceWarrantApiData, getCaseApiData, submitCaseEventTokenDynamicApiData, createCaseEventTokenDynamicApiData, makeAnApplicationEventTokenApiData, makeAnApplicationApiData } from '@data/api-data'; import { user } from '@data/user-data'; import { caseNumber } from './createCase.action'; import { performAction } from '@utils/controller'; @@ -11,6 +11,8 @@ import { IdamUtils } from '@hmcts/playwright-common'; export let caseInfo: { id: string; fid: string; state: string } = { id: '', fid: '', state: '' }; +export let defendantUserDetails: { id: string; name: string }[] = []; + export class CreateCaseAPIAction implements IAction { async execute(page: Page, action: string, fieldName: actionData | actionRecord, data?: actionData): Promise { const actionsMap = new Map Promise>([ @@ -23,6 +25,7 @@ export class CreateCaseAPIAction implements IAction { ['getCaseAPIDynamic', () => this.getCaseAPIDynamic(fieldName as actionRecord)], ['createCaseAPIDynamicUsers', () => this.createCaseAPIDynamicUsers(fieldName as actionRecord)], ['submitCaseAPIDynamicUsers', () => this.submitCaseAPIDynamicUsers(fieldName as actionRecord)], + ['makeAnApplicationAPI', () => this.makeAnApplicationAPI(fieldName)], ]); const actionToPerform = actionsMap.get(action); if (!actionToPerform) throw new Error(`No action found for '${action}'`); @@ -185,11 +188,23 @@ export class CreateCaseAPIAction implements IAction { } else { await this.generateSolicitorAccessToken(user.defendantSolicitor.email as string,user.defendantSolicitor.password as string); const allDefendants = createResponse.data.data.allDefendants; + //console.log('all defe :'+JSON.stringify(allDefendants)); const defendantIds = allDefendants.map((d: any) => d.id); if (defendantIds.length === 0) throw new Error(`No Defendants ID retrieved and the status is ${createResponse.status}`); - for (const defendantId of defendantIds) { - process.env.Defendant_ID = defendantId; + for (const defendant of allDefendants) { + process.env.Defendant_ID = defendant.id; + const defendantName = + defendant.value?.nameKnown === 'YES' + ? `${defendant.value.firstName} ${defendant.value.lastName}` + : ''; + + defendantUserDetails.push({ + id: defendant.id, + name: defendantName, + }); + + await performAction('linkSolicitorAPI',user.defendantSolicitor.email as string); } @@ -397,4 +412,41 @@ export class CreateCaseAPIAction implements IAction { scope: 'profile openid roles' }); }; + + private async makeAnApplicationAPI(caseData: actionData): Promise { + const makeAnApplicationApi = Axios.create(makeAnApplicationEventTokenApiData.makeAnApplicationEventTokenApiInstance()); + let makeAnApplicationPayloadData = typeof caseData === "object" && "data" in caseData ? caseData.data : caseData; + try { + process.env.MAA_EVENT_TOKEN = (await makeAnApplicationApi.get(makeAnApplicationEventTokenApiData.makeAnApplicationEventTokenApiEndPoint())).data.token; + makeAnApplicationPayloadData = typeof caseData === "object" && "data" in caseData ? caseData.data : caseData; + const genAppResponse = await makeAnApplicationApi.post(makeAnApplicationApiData.makeAnApplicationApiEndPoint(), { + data: makeAnApplicationPayloadData, + event: { id: makeAnApplicationApiData.makeAnApplicationEventName }, + event_token: process.env.MAA_EVENT_TOKEN, + }); + caseInfo.id = genAppResponse.data.id; + caseInfo.fid = genAppResponse.data.id.replace(/(.{4})(?=.)/g, "$1-"); + caseInfo.state = genAppResponse.data.state; + } catch (error: any) { + const status = error?.response?.status; + const responseBody = error?.response?.data; + if (status === 404) { + console.error(makeAnApplicationPayloadData); + throw new Error(`Make an application failed: endpoint not found (404).please check the payload above \n ${error}`); + } + console.error("=== ERROR RESPONSE ==="); + console.error("HTTP Status:", status); + console.error("Exception:", responseBody?.exception); + console.error("Error:", responseBody?.error); + console.error("Message:", responseBody?.message); + console.error("Path:", responseBody?.path); + console.error("Timestamp:", responseBody?.timestamp); + console.error("Full response body:", JSON.stringify(responseBody, null, 2)); + + if (!status) { + throw new Error('Make an application: no response from server.'); + } + throw new Error(`Make an application failed with status ${status}.Response received is ${responseBody?.message}}`); + } + } } diff --git a/src/e2eTest/utils/registry/action.registry.ts b/src/e2eTest/utils/registry/action.registry.ts index 2e610b4ca5..7dade226ff 100644 --- a/src/e2eTest/utils/registry/action.registry.ts +++ b/src/e2eTest/utils/registry/action.registry.ts @@ -57,6 +57,7 @@ export class ActionRegistry { ['fetchCurrentUserAPI', new CreateCaseAPIAction()], ['createCaseAPIDynamicUsers', new CreateCaseAPIAction()], ['submitCaseAPIDynamicUsers', new CreateCaseAPIAction()], + ['makeAnApplicationAPI', new CreateCaseAPIAction()], ['selectClaimType', new CreateCaseAction()], ['selectClaimantName', new CreateCaseAction()], ['selectClaimantDetails', new CreateCaseWalesAction()], From b0b507d475b3ebaef2c8e0212feb2ce92fcb4d4b Mon Sep 17 00:00:00 2001 From: sadmanrahman Date: Thu, 2 Jul 2026 09:17:30 +0100 Subject: [PATCH 24/70] HDPI-7308: make amend visible for judges --- .../reform/pcs/ccd/accesscontrol/AccessProfile.java | 8 ++++---- .../pcs/ccd/accesscontrol/AccessProfileTest.java | 12 ++++++++++++ 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/AccessProfile.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/AccessProfile.java index 3938f5b9fc..f2fb204fb9 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/AccessProfile.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/AccessProfile.java @@ -22,10 +22,10 @@ public enum AccessProfile implements HasRole { PCS_CASE_WORKER("caseworker-pcs", Set.of(R)), PCS_SOLICITOR("caseworker-pcs-solicitor", CRU), - JUDGE("judge", Set.of(R)), - FEE_PAID_JUDGE("fee-paid-judge", Set.of(R)), - CIRCUIT_JUDGE("circuit-judge", Set.of(R)), - LEADERSHIP_JUDGE("leadership-judge", Set.of(R)), + JUDGE("judge", CRU), + FEE_PAID_JUDGE("fee-paid-judge", CRU), + CIRCUIT_JUDGE("circuit-judge", CRU), + LEADERSHIP_JUDGE("leadership-judge", CRU), CTSC_TEAM_LEADER("ctsc-team-leader", Permission.CRU), CTSC_ADMIN("ctsc", Permission.CRU), HEARING_CENTRE_TEAM_LEADER("hearing-centre-team-leader", Permission.CRU), diff --git a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/AccessProfileTest.java b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/AccessProfileTest.java index aa04539f75..fd42e060ea 100644 --- a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/AccessProfileTest.java +++ b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/AccessProfileTest.java @@ -1,6 +1,7 @@ package uk.gov.hmcts.reform.pcs.ccd.accesscontrol; import org.junit.jupiter.api.Test; +import uk.gov.hmcts.ccd.sdk.api.Permission; import static org.assertj.core.api.Assertions.assertThat; @@ -19,4 +20,15 @@ void shouldReturnEmptyArrayWhenNoProfilesGiven() { assertThat(roles).isEmpty(); } + + @Test + void shouldGrantCreateReadUpdateCaseTypeAccessToJudicialProfiles() { + assertThat(AccessProfile.JUDGE.getCaseTypePermissions()).isEqualTo(Permission.toString(Permission.CRU)); + assertThat(AccessProfile.FEE_PAID_JUDGE.getCaseTypePermissions()) + .isEqualTo(Permission.toString(Permission.CRU)); + assertThat(AccessProfile.CIRCUIT_JUDGE.getCaseTypePermissions()) + .isEqualTo(Permission.toString(Permission.CRU)); + assertThat(AccessProfile.LEADERSHIP_JUDGE.getCaseTypePermissions()) + .isEqualTo(Permission.toString(Permission.CRU)); + } } From 309bb6842c1e6dae924138ccb36418740afa2aa6 Mon Sep 17 00:00:00 2001 From: srinijg Date: Thu, 2 Jul 2026 12:02:56 +0100 Subject: [PATCH 25/70] new grep tag added --- Jenkinsfile_CNP | 3 +++ src/e2eTest/package.json | 1 + .../caseManagement.caseFileView.spec.ts | 2 +- .../custom-actions/createCase.action.ts | 26 +++++++++---------- .../custom-actions/createCaseAPI.action.ts | 3 +-- 5 files changed, 18 insertions(+), 17 deletions(-) diff --git a/Jenkinsfile_CNP b/Jenkinsfile_CNP index 14b68c48b9..69f3ff8e89 100644 --- a/Jenkinsfile_CNP +++ b/Jenkinsfile_CNP @@ -69,6 +69,9 @@ withPipeline(type, product, component) { else if (githubApi.getLabelsbyPattern(env.BRANCH_NAME, "enable_e2e_CC_test").size() > 0) { env.E2E_SUITE = "commonComponent" } + else if (githubApi.getLabelsbyPattern(env.BRANCH_NAME, "enable_e2e_CM_test").size() > 0) { + env.E2E_SUITE = "caseManagement" + } } onMaster() { diff --git a/src/e2eTest/package.json b/src/e2eTest/package.json index d460233324..5301b78df3 100644 --- a/src/e2eTest/package.json +++ b/src/e2eTest/package.json @@ -10,6 +10,7 @@ "test:regression": "yarn playwright install && yarn playwright test --project chrome --grep '@regression'; EXIT_CODE=$?; allure generate -o ../../e2e-output --clean; tsx ./config/clean-attachments.config.ts; exit $EXIT_CODE", "test:makeAClaim": "yarn playwright install && yarn playwright test --project chrome --grep '@MAC'; EXIT_CODE=$?; allure generate -o ../../e2e-output --clean; tsx ./config/clean-attachments.config.ts; exit $EXIT_CODE", "test:commonComponent": "yarn playwright install && yarn playwright test --project chrome --grep '@CC'; EXIT_CODE=$?; allure generate -o ../../e2e-output --clean; tsx ./config/clean-attachments.config.ts; exit $EXIT_CODE", + "test:caseManagement": "yarn playwright install && yarn playwright test --project chrome --grep '@CM'; EXIT_CODE=$?; allure generate -o ../../e2e-output --clean; tsx ./config/clean-attachments.config.ts; exit $EXIT_CODE", "test:chrome": "yarn playwright install && yarn playwright test --project chrome; EXIT_CODE=$?; allure generate -o ../../e2e-output --clean; tsx ./config/clean-attachments.config.ts; exit $EXIT_CODE", "test:firefox": "yarn playwright install && yarn playwright test --project firefox; EXIT_CODE=$?; allure generate -o ../../e2e-output --clean; tsx ./config/clean-attachments.config.ts; exit $EXIT_CODE", "test:webkit": "yarn playwright install && yarn playwright test --project webkit; EXIT_CODE=$?; allure generate -o ../../e2e-output --clean; tsx ./config/clean-attachments.config.ts; exit $EXIT_CODE", diff --git a/src/e2eTest/tests/test-caseManagement/caseManagement.caseFileView.spec.ts b/src/e2eTest/tests/test-caseManagement/caseManagement.caseFileView.spec.ts index 22e41acda3..c2b780924e 100644 --- a/src/e2eTest/tests/test-caseManagement/caseManagement.caseFileView.spec.ts +++ b/src/e2eTest/tests/test-caseManagement/caseManagement.caseFileView.spec.ts @@ -41,7 +41,7 @@ test.afterEach(async () => { test.describe('Case management - e2e Journey @nightly', async () => { - test('Case management - CaseFile View test @PR @regression', async () => { + test('Case management - CaseFile View test @CM @regression', async () => { await performValidation('mainHeader', home.caseSummary) await performAction('clickTab', home.caseFileView); await performAction('validateCaseFileViewFolders', home.caseFileFolders); diff --git a/src/e2eTest/utils/actions/custom-actions/createCase.action.ts b/src/e2eTest/utils/actions/custom-actions/createCase.action.ts index 3417fb2e19..7b03f2e70c 100644 --- a/src/e2eTest/utils/actions/custom-actions/createCase.action.ts +++ b/src/e2eTest/utils/actions/custom-actions/createCase.action.ts @@ -1682,6 +1682,7 @@ export class CreateCaseAction implements IAction { }); } } + public async validateCaseListTable(page: Page, caseList: actionRecord){ let submitPayLoad = caseList.submitPayload as Record; let createPayLoad = caseList.createPayload as Record; @@ -1786,24 +1787,21 @@ export class CreateCaseAction implements IAction { }); } - - public cleanGenAppFilesArray(filesArray: string[], defendantCount: number) : string[] { - const result: string[] = []; + public cleanGenAppFilesArray(filesArray: string[], defendantCount: number): string[] { + const result: string[] = []; - for (let i = 1; i <= defendantCount; i++) { - for (const file of filesArray) { - result.push( - file.replace(/\.pdf$/i, ` GA${i}.pdf`) - ); + for (let i = 1; i <= defendantCount; i++) { + for (const file of filesArray) { + result.push( + file.replace(/\.pdf$/i, ` GA${i}.pdf`) + ); + } + + result.push(`General Application GA${i}.pdf`); } - result.push(`General Application GA${i}.pdf`); + return result; } - return result; -} - - - } \ No newline at end of file diff --git a/src/e2eTest/utils/actions/custom-actions/createCaseAPI.action.ts b/src/e2eTest/utils/actions/custom-actions/createCaseAPI.action.ts index d3f3da25e6..1f74592408 100644 --- a/src/e2eTest/utils/actions/custom-actions/createCaseAPI.action.ts +++ b/src/e2eTest/utils/actions/custom-actions/createCaseAPI.action.ts @@ -187,8 +187,7 @@ export class CreateCaseAPIAction implements IAction { console.log(`\n✅ The claim was submitted on "${process.env.Submission_TIME}"`) } else { await this.generateSolicitorAccessToken(user.defendantSolicitor.email as string,user.defendantSolicitor.password as string); - const allDefendants = createResponse.data.data.allDefendants; - //console.log('all defe :'+JSON.stringify(allDefendants)); + const allDefendants = createResponse.data.data.allDefendants; const defendantIds = allDefendants.map((d: any) => d.id); if (defendantIds.length === 0) throw new Error(`No Defendants ID retrieved and the status is ${createResponse.status}`); From e8aa5130b47f201de3326f986358382daf790d09 Mon Sep 17 00:00:00 2001 From: sadmanrahman Date: Thu, 2 Jul 2026 12:39:38 +0100 Subject: [PATCH 26/70] HDPI-6835: flyway version fix --- ..._app_case_level_rank.sql => V131__gen_app_case_level_rank.sql} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/main/resources/db/migration/{V129__gen_app_case_level_rank.sql => V131__gen_app_case_level_rank.sql} (100%) diff --git a/src/main/resources/db/migration/V129__gen_app_case_level_rank.sql b/src/main/resources/db/migration/V131__gen_app_case_level_rank.sql similarity index 100% rename from src/main/resources/db/migration/V129__gen_app_case_level_rank.sql rename to src/main/resources/db/migration/V131__gen_app_case_level_rank.sql From 2c6a8d7dca993248c4ba492c5df7ec0fe25a9023 Mon Sep 17 00:00:00 2001 From: sadmanrahman Date: Thu, 2 Jul 2026 14:10:48 +0100 Subject: [PATCH 27/70] HDPI-7308: fix error handling --- .../documentamend/SelectDocumentPage.java | 58 ++++++++++++++++++- .../DocumentAmendSelectionService.java | 13 +---- .../DocumentAmendSelectionServiceTest.java | 4 +- 3 files changed, 59 insertions(+), 16 deletions(-) diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java index 521a992a09..eefe2d6be7 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java @@ -11,6 +11,7 @@ import uk.gov.hmcts.reform.pcs.ccd.domain.State; import uk.gov.hmcts.reform.pcs.ccd.domain.documentamend.DocumentAmendDetails; import uk.gov.hmcts.reform.pcs.ccd.service.document.DocumentAmendSelectionService; +import uk.gov.hmcts.reform.pcs.ccd.util.StringUtils; import java.util.List; @@ -23,6 +24,8 @@ public class SelectDocumentPage implements CcdPageConfiguration { private static final String PAGE_ID = "selectDocument"; private static final String FIELD_PREFIX = "documentAmend_"; private static final String YES = "=\"Yes\""; + private static final String NO = "=\"No\""; + private static final String SELECT_DIFFERENT_FOLDER_ERROR = "Select a different folder to continue"; private final DocumentAmendSelectionService documentAmendSelectionService; @Override @@ -34,6 +37,45 @@ public void addTo(PageBuilder pageBuilder) { .complex(PCSCase::getDocumentAmendDetails) .readonly(DocumentAmendDetails::getPropertyAddressSummary, NEVER_SHOW, true) .mandatory(DocumentAmendDetails::getSelectedFolder) + .label("emptyFolderDocumentError", "", NEVER_SHOW) + .label("selectedFolderEmptyErrorMessage", "", NEVER_SHOW) + .label("emptyFolderDocumentQuestion", "", NEVER_SHOW) + .label("statementsOfCaseEmptyFolderError", errorMessage(SELECT_DIFFERENT_FOLDER_ERROR), + emptyFolderErrorShowCondition(CaseFileCategory.STATEMENTS_OF_CASE)) + .label("statementsOfCaseEmptyFolderQuestion", documentQuestion(), + noDocumentsShowCondition(CaseFileCategory.STATEMENTS_OF_CASE)) + .label("propertyDocumentsEmptyFolderError", errorMessage(SELECT_DIFFERENT_FOLDER_ERROR), + emptyFolderErrorShowCondition(CaseFileCategory.PROPERTY_DOCUMENTS)) + .label("propertyDocumentsEmptyFolderQuestion", documentQuestion(), + noDocumentsShowCondition(CaseFileCategory.PROPERTY_DOCUMENTS)) + .label("evidenceEmptyFolderError", errorMessage(SELECT_DIFFERENT_FOLDER_ERROR), + emptyFolderErrorShowCondition(CaseFileCategory.EVIDENCE)) + .label("evidenceEmptyFolderQuestion", documentQuestion(), + noDocumentsShowCondition(CaseFileCategory.EVIDENCE)) + .label("hearingDocumentsEmptyFolderError", errorMessage(SELECT_DIFFERENT_FOLDER_ERROR), + emptyFolderErrorShowCondition(CaseFileCategory.HEARING_DOCUMENTS)) + .label("hearingDocumentsEmptyFolderQuestion", documentQuestion(), + noDocumentsShowCondition(CaseFileCategory.HEARING_DOCUMENTS)) + .label("ordersAndNoticeOfHearingsEmptyFolderError", errorMessage(SELECT_DIFFERENT_FOLDER_ERROR), + emptyFolderErrorShowCondition(CaseFileCategory.ORDERS_AND_NOTICE_OF_HEARINGS)) + .label("ordersAndNoticeOfHearingsEmptyFolderQuestion", documentQuestion(), + noDocumentsShowCondition(CaseFileCategory.ORDERS_AND_NOTICE_OF_HEARINGS)) + .label("applicationsEmptyFolderError", errorMessage(SELECT_DIFFERENT_FOLDER_ERROR), + emptyFolderErrorShowCondition(CaseFileCategory.APPLICATIONS)) + .label("applicationsEmptyFolderQuestion", documentQuestion(), + noDocumentsShowCondition(CaseFileCategory.APPLICATIONS)) + .label("appealsEmptyFolderError", errorMessage(SELECT_DIFFERENT_FOLDER_ERROR), + emptyFolderErrorShowCondition(CaseFileCategory.APPEALS)) + .label("appealsEmptyFolderQuestion", documentQuestion(), + noDocumentsShowCondition(CaseFileCategory.APPEALS)) + .label("correspondenceEmptyFolderError", errorMessage(SELECT_DIFFERENT_FOLDER_ERROR), + emptyFolderErrorShowCondition(CaseFileCategory.CORRESPONDENCE)) + .label("correspondenceEmptyFolderQuestion", documentQuestion(), + noDocumentsShowCondition(CaseFileCategory.CORRESPONDENCE)) + .label("uncategorisedDocumentsEmptyFolderError", errorMessage(SELECT_DIFFERENT_FOLDER_ERROR), + emptyFolderErrorShowCondition(CaseFileCategory.UNCATEGORISED_DOCUMENTS)) + .label("uncategorisedDocumentsEmptyFolderQuestion", documentQuestion(), + noDocumentsShowCondition(CaseFileCategory.UNCATEGORISED_DOCUMENTS)) .mandatory(DocumentAmendDetails::getStatementsOfCaseDocuments, documentsShowCondition(CaseFileCategory.STATEMENTS_OF_CASE), true) .label("statementsOfCaseNoDocuments", noDocumentsMessage(CaseFileCategory.STATEMENTS_OF_CASE), @@ -97,18 +139,22 @@ private AboutToStartOrSubmitResponse midEvent(CaseDetailsbuilder() .data(caseData) - .errors(errors.isEmpty() ? null : errors) + .errorMessageOverride(StringUtils.joinIfNotEmpty("\n", errors)) .build(); } private String documentsShowCondition(CaseFileCategory category) { - return selectedFolderCondition(category); + return selectedFolderCondition(category) + " AND " + emptyFieldId(category) + NO; } private String noDocumentsShowCondition(CaseFileCategory category) { return selectedFolderCondition(category) + " AND " + emptyFieldId(category) + YES; } + private String emptyFolderErrorShowCondition(CaseFileCategory category) { + return noDocumentsShowCondition(category); + } + private String selectedFolderCondition(CaseFileCategory category) { return FIELD_PREFIX + "SelectedFolder=\"" + category.name() + "\""; } @@ -130,4 +176,12 @@ private String emptyFieldId(CaseFileCategory category) { private String noDocumentsMessage(CaseFileCategory category) { return "No documents in '" + category.getLabel() + "'"; } + + private String documentQuestion() { + return "Which document do you want to amend?"; + } + + private String errorMessage(String message) { + return "

" + message + "

"; + } } diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionService.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionService.java index c2c18b72e0..ab70f762a6 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionService.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionService.java @@ -110,7 +110,7 @@ private DynamicList documentList(PcsCaseEntity pcsCase, CaseFileCategory categor .toList(); return DynamicList.builder() - .value(selectedValue(selected, documents)) + .value(retainSelectedValue(selected, documents)) .listItems(documents) .build(); } @@ -126,20 +126,11 @@ private DynamicListElement retainSelectedValue(DynamicListElement selected, } return options.stream() - .filter(option -> selected.getCode().equals(option.getCode())) + .filter(option -> selected.getCode().toString().equals(option.getCode().toString())) .findFirst() .orElse(null); } - private DynamicListElement selectedValue(DynamicListElement selected, - List options) { - DynamicListElement retainedSelectedValue = retainSelectedValue(selected, options); - if (retainedSelectedValue != null) { - return retainedSelectedValue; - } - return options.isEmpty() ? null : DynamicListElement.EMPTY; - } - private boolean isEmpty(DynamicList documents) { return documents == null || CollectionUtils.isEmpty(documents.getListItems()); } diff --git a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java index bfa5337a60..350d3cf605 100644 --- a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java +++ b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java @@ -158,8 +158,7 @@ void shouldPopulateDocumentsForSelectedCategoryAndIncludeWithoutNoticeApplicatio assertThat(details.getApplicationsDocuments().getListItems()) .extracting(DynamicListElement::getLabel) .containsExactly("visible application.pdf", "without notice application.pdf"); - assertThat(details.getApplicationsDocuments().getValue()).isNotNull(); - assertThat(details.getApplicationsDocuments().getValue().getCode()).isNull(); + assertThat(details.getApplicationsDocuments().getValue()).isNull(); } @Test @@ -209,7 +208,6 @@ void shouldTreatEmptyDocumentSelectionAsNoSelection() { .documentAmendDetails(DocumentAmendDetails.builder() .selectedFolder(selectedFolder(EVIDENCE)) .evidenceDocuments(DynamicList.builder() - .value(DynamicListElement.EMPTY) .build()) .build()) .build(); From 60127aa952e5f31ef630e52900c546dd55703dfc Mon Sep 17 00:00:00 2001 From: sadmanrahman Date: Thu, 2 Jul 2026 15:07:28 +0100 Subject: [PATCH 28/70] HDPI-7308: refactor to enum --- .../documentamend/SelectDocumentPage.java | 186 ++++++++++-------- .../DocumentAmendSelectionService.java | 12 +- 2 files changed, 104 insertions(+), 94 deletions(-) diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java index eefe2d6be7..c1577d203a 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java @@ -3,7 +3,11 @@ import lombok.AllArgsConstructor; import org.springframework.stereotype.Component; import uk.gov.hmcts.ccd.sdk.api.CaseDetails; +import uk.gov.hmcts.ccd.sdk.api.FieldCollection.FieldCollectionBuilder; +import uk.gov.hmcts.ccd.sdk.api.TypedPropertyGetter; import uk.gov.hmcts.ccd.sdk.api.callback.AboutToStartOrSubmitResponse; +import uk.gov.hmcts.ccd.sdk.type.DynamicList; +import uk.gov.hmcts.ccd.sdk.type.YesOrNo; import uk.gov.hmcts.reform.pcs.ccd.common.CcdPageConfiguration; import uk.gov.hmcts.reform.pcs.ccd.common.PageBuilder; import uk.gov.hmcts.reform.pcs.ccd.domain.CaseFileCategory; @@ -30,7 +34,7 @@ public class SelectDocumentPage implements CcdPageConfiguration { @Override public void addTo(PageBuilder pageBuilder) { - pageBuilder + FieldCollectionBuilder documentAmendPage = pageBuilder .page(PAGE_ID, this::midEvent) .pageLabel("Select document") .label(PAGE_ID + "-separator", "---") @@ -39,90 +43,17 @@ public void addTo(PageBuilder pageBuilder) { .mandatory(DocumentAmendDetails::getSelectedFolder) .label("emptyFolderDocumentError", "", NEVER_SHOW) .label("selectedFolderEmptyErrorMessage", "", NEVER_SHOW) - .label("emptyFolderDocumentQuestion", "", NEVER_SHOW) - .label("statementsOfCaseEmptyFolderError", errorMessage(SELECT_DIFFERENT_FOLDER_ERROR), - emptyFolderErrorShowCondition(CaseFileCategory.STATEMENTS_OF_CASE)) - .label("statementsOfCaseEmptyFolderQuestion", documentQuestion(), - noDocumentsShowCondition(CaseFileCategory.STATEMENTS_OF_CASE)) - .label("propertyDocumentsEmptyFolderError", errorMessage(SELECT_DIFFERENT_FOLDER_ERROR), - emptyFolderErrorShowCondition(CaseFileCategory.PROPERTY_DOCUMENTS)) - .label("propertyDocumentsEmptyFolderQuestion", documentQuestion(), - noDocumentsShowCondition(CaseFileCategory.PROPERTY_DOCUMENTS)) - .label("evidenceEmptyFolderError", errorMessage(SELECT_DIFFERENT_FOLDER_ERROR), - emptyFolderErrorShowCondition(CaseFileCategory.EVIDENCE)) - .label("evidenceEmptyFolderQuestion", documentQuestion(), - noDocumentsShowCondition(CaseFileCategory.EVIDENCE)) - .label("hearingDocumentsEmptyFolderError", errorMessage(SELECT_DIFFERENT_FOLDER_ERROR), - emptyFolderErrorShowCondition(CaseFileCategory.HEARING_DOCUMENTS)) - .label("hearingDocumentsEmptyFolderQuestion", documentQuestion(), - noDocumentsShowCondition(CaseFileCategory.HEARING_DOCUMENTS)) - .label("ordersAndNoticeOfHearingsEmptyFolderError", errorMessage(SELECT_DIFFERENT_FOLDER_ERROR), - emptyFolderErrorShowCondition(CaseFileCategory.ORDERS_AND_NOTICE_OF_HEARINGS)) - .label("ordersAndNoticeOfHearingsEmptyFolderQuestion", documentQuestion(), - noDocumentsShowCondition(CaseFileCategory.ORDERS_AND_NOTICE_OF_HEARINGS)) - .label("applicationsEmptyFolderError", errorMessage(SELECT_DIFFERENT_FOLDER_ERROR), - emptyFolderErrorShowCondition(CaseFileCategory.APPLICATIONS)) - .label("applicationsEmptyFolderQuestion", documentQuestion(), - noDocumentsShowCondition(CaseFileCategory.APPLICATIONS)) - .label("appealsEmptyFolderError", errorMessage(SELECT_DIFFERENT_FOLDER_ERROR), - emptyFolderErrorShowCondition(CaseFileCategory.APPEALS)) - .label("appealsEmptyFolderQuestion", documentQuestion(), - noDocumentsShowCondition(CaseFileCategory.APPEALS)) - .label("correspondenceEmptyFolderError", errorMessage(SELECT_DIFFERENT_FOLDER_ERROR), - emptyFolderErrorShowCondition(CaseFileCategory.CORRESPONDENCE)) - .label("correspondenceEmptyFolderQuestion", documentQuestion(), - noDocumentsShowCondition(CaseFileCategory.CORRESPONDENCE)) - .label("uncategorisedDocumentsEmptyFolderError", errorMessage(SELECT_DIFFERENT_FOLDER_ERROR), - emptyFolderErrorShowCondition(CaseFileCategory.UNCATEGORISED_DOCUMENTS)) - .label("uncategorisedDocumentsEmptyFolderQuestion", documentQuestion(), - noDocumentsShowCondition(CaseFileCategory.UNCATEGORISED_DOCUMENTS)) - .mandatory(DocumentAmendDetails::getStatementsOfCaseDocuments, - documentsShowCondition(CaseFileCategory.STATEMENTS_OF_CASE), true) - .label("statementsOfCaseNoDocuments", noDocumentsMessage(CaseFileCategory.STATEMENTS_OF_CASE), - noDocumentsShowCondition(CaseFileCategory.STATEMENTS_OF_CASE)) - .mandatory(DocumentAmendDetails::getPropertyDocuments, - documentsShowCondition(CaseFileCategory.PROPERTY_DOCUMENTS), true) - .label("propertyDocumentsNoDocuments", noDocumentsMessage(CaseFileCategory.PROPERTY_DOCUMENTS), - noDocumentsShowCondition(CaseFileCategory.PROPERTY_DOCUMENTS)) - .mandatory(DocumentAmendDetails::getEvidenceDocuments, - documentsShowCondition(CaseFileCategory.EVIDENCE), true) - .label("evidenceNoDocuments", noDocumentsMessage(CaseFileCategory.EVIDENCE), - noDocumentsShowCondition(CaseFileCategory.EVIDENCE)) - .mandatory(DocumentAmendDetails::getHearingDocuments, - documentsShowCondition(CaseFileCategory.HEARING_DOCUMENTS), true) - .label("hearingDocumentsNoDocuments", noDocumentsMessage(CaseFileCategory.HEARING_DOCUMENTS), - noDocumentsShowCondition(CaseFileCategory.HEARING_DOCUMENTS)) - .mandatory(DocumentAmendDetails::getOrdersAndNoticeOfHearingsDocuments, - documentsShowCondition(CaseFileCategory.ORDERS_AND_NOTICE_OF_HEARINGS), true) - .label("ordersAndNoticeOfHearingsNoDocuments", - noDocumentsMessage(CaseFileCategory.ORDERS_AND_NOTICE_OF_HEARINGS), - noDocumentsShowCondition(CaseFileCategory.ORDERS_AND_NOTICE_OF_HEARINGS)) - .mandatory(DocumentAmendDetails::getApplicationsDocuments, - documentsShowCondition(CaseFileCategory.APPLICATIONS), true) - .label("applicationsNoDocuments", noDocumentsMessage(CaseFileCategory.APPLICATIONS), - noDocumentsShowCondition(CaseFileCategory.APPLICATIONS)) - .mandatory(DocumentAmendDetails::getAppealsDocuments, - documentsShowCondition(CaseFileCategory.APPEALS), true) - .label("appealsNoDocuments", noDocumentsMessage(CaseFileCategory.APPEALS), - noDocumentsShowCondition(CaseFileCategory.APPEALS)) - .mandatory(DocumentAmendDetails::getCorrespondenceDocuments, - documentsShowCondition(CaseFileCategory.CORRESPONDENCE), true) - .label("correspondenceNoDocuments", noDocumentsMessage(CaseFileCategory.CORRESPONDENCE), - noDocumentsShowCondition(CaseFileCategory.CORRESPONDENCE)) - .mandatory(DocumentAmendDetails::getUncategorisedDocuments, - documentsShowCondition(CaseFileCategory.UNCATEGORISED_DOCUMENTS), true) - .label("uncategorisedDocumentsNoDocuments", - noDocumentsMessage(CaseFileCategory.UNCATEGORISED_DOCUMENTS), - noDocumentsShowCondition(CaseFileCategory.UNCATEGORISED_DOCUMENTS)) - .readonly(DocumentAmendDetails::getStatementsOfCaseEmpty, NEVER_SHOW, true) - .readonly(DocumentAmendDetails::getPropertyDocumentsEmpty, NEVER_SHOW, true) - .readonly(DocumentAmendDetails::getEvidenceEmpty, NEVER_SHOW, true) - .readonly(DocumentAmendDetails::getHearingDocumentsEmpty, NEVER_SHOW, true) - .readonly(DocumentAmendDetails::getOrdersAndNoticeOfHearingsEmpty, NEVER_SHOW, true) - .readonly(DocumentAmendDetails::getApplicationsEmpty, NEVER_SHOW, true) - .readonly(DocumentAmendDetails::getAppealsEmpty, NEVER_SHOW, true) - .readonly(DocumentAmendDetails::getCorrespondenceEmpty, NEVER_SHOW, true) - .readonly(DocumentAmendDetails::getUncategorisedDocumentsEmpty, NEVER_SHOW, true) + .label("emptyFolderDocumentQuestion", "", NEVER_SHOW); + + for (DocumentCategoryField categoryField : DocumentCategoryField.values()) { + addCategoryFields(documentAmendPage, categoryField); + } + + for (DocumentCategoryField categoryField : DocumentCategoryField.values()) { + documentAmendPage.readonly(categoryField.emptyGetter, NEVER_SHOW, true); + } + + documentAmendPage .readonly(DocumentAmendDetails::getSelectedFolderId, NEVER_SHOW, true) .readonly(DocumentAmendDetails::getSelectedFolderLabel, NEVER_SHOW, true) .readonly(DocumentAmendDetails::getSelectedDocumentId, NEVER_SHOW, true) @@ -130,6 +61,19 @@ public void addTo(PageBuilder pageBuilder) { .done(); } + private void addCategoryFields(FieldCollectionBuilder page, + DocumentCategoryField categoryField) { + CaseFileCategory category = categoryField.category; + page + .label(categoryField.idPrefix + "EmptyFolderError", errorMessage(SELECT_DIFFERENT_FOLDER_ERROR), + emptyFolderErrorShowCondition(category)) + .label(categoryField.idPrefix + "EmptyFolderQuestion", documentQuestion(), + noDocumentsShowCondition(category)) + .mandatory(categoryField.documentsGetter, documentsShowCondition(category), true) + .label(categoryField.idPrefix + "NoDocuments", noDocumentsMessage(category), + noDocumentsShowCondition(category)); + } + private AboutToStartOrSubmitResponse midEvent(CaseDetails details, CaseDetails detailsBefore) { PCSCase caseData = details.getData(); @@ -184,4 +128,76 @@ private String documentQuestion() { private String errorMessage(String message) { return "

" + message + "

"; } + + private enum DocumentCategoryField { + STATEMENTS_OF_CASE( + CaseFileCategory.STATEMENTS_OF_CASE, + "statementsOfCase", + DocumentAmendDetails::getStatementsOfCaseDocuments, + DocumentAmendDetails::getStatementsOfCaseEmpty + ), + PROPERTY_DOCUMENTS( + CaseFileCategory.PROPERTY_DOCUMENTS, + "propertyDocuments", + DocumentAmendDetails::getPropertyDocuments, + DocumentAmendDetails::getPropertyDocumentsEmpty + ), + EVIDENCE( + CaseFileCategory.EVIDENCE, + "evidence", + DocumentAmendDetails::getEvidenceDocuments, + DocumentAmendDetails::getEvidenceEmpty + ), + HEARING_DOCUMENTS( + CaseFileCategory.HEARING_DOCUMENTS, + "hearingDocuments", + DocumentAmendDetails::getHearingDocuments, + DocumentAmendDetails::getHearingDocumentsEmpty + ), + ORDERS_AND_NOTICE_OF_HEARINGS( + CaseFileCategory.ORDERS_AND_NOTICE_OF_HEARINGS, + "ordersAndNoticeOfHearings", + DocumentAmendDetails::getOrdersAndNoticeOfHearingsDocuments, + DocumentAmendDetails::getOrdersAndNoticeOfHearingsEmpty + ), + APPLICATIONS( + CaseFileCategory.APPLICATIONS, + "applications", + DocumentAmendDetails::getApplicationsDocuments, + DocumentAmendDetails::getApplicationsEmpty + ), + APPEALS( + CaseFileCategory.APPEALS, + "appeals", + DocumentAmendDetails::getAppealsDocuments, + DocumentAmendDetails::getAppealsEmpty + ), + CORRESPONDENCE( + CaseFileCategory.CORRESPONDENCE, + "correspondence", + DocumentAmendDetails::getCorrespondenceDocuments, + DocumentAmendDetails::getCorrespondenceEmpty + ), + UNCATEGORISED_DOCUMENTS( + CaseFileCategory.UNCATEGORISED_DOCUMENTS, + "uncategorisedDocuments", + DocumentAmendDetails::getUncategorisedDocuments, + DocumentAmendDetails::getUncategorisedDocumentsEmpty + ); + + private final CaseFileCategory category; + private final String idPrefix; + private final TypedPropertyGetter documentsGetter; + private final TypedPropertyGetter emptyGetter; + + DocumentCategoryField(CaseFileCategory category, + String idPrefix, + TypedPropertyGetter documentsGetter, + TypedPropertyGetter emptyGetter) { + this.category = category; + this.idPrefix = idPrefix; + this.documentsGetter = documentsGetter; + this.emptyGetter = emptyGetter; + } + } } diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionService.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionService.java index ab70f762a6..eaecf80f04 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionService.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionService.java @@ -46,15 +46,9 @@ public void initialise(long caseReference, PCSCase caseData) { details.setPropertyAddressSummary(addressFormatter.formatShortAddress(caseData.getPropertyAddress(), COMMA_DELIMITER)); details.setPartyNamesSummary(buildPartyNamesSummary(caseData)); - setDocumentsForCategory(details, pcsCase, CaseFileCategory.STATEMENTS_OF_CASE); - setDocumentsForCategory(details, pcsCase, CaseFileCategory.PROPERTY_DOCUMENTS); - setDocumentsForCategory(details, pcsCase, CaseFileCategory.EVIDENCE); - setDocumentsForCategory(details, pcsCase, CaseFileCategory.HEARING_DOCUMENTS); - setDocumentsForCategory(details, pcsCase, CaseFileCategory.ORDERS_AND_NOTICE_OF_HEARINGS); - setDocumentsForCategory(details, pcsCase, CaseFileCategory.APPLICATIONS); - setDocumentsForCategory(details, pcsCase, CaseFileCategory.APPEALS); - setDocumentsForCategory(details, pcsCase, CaseFileCategory.CORRESPONDENCE); - setDocumentsForCategory(details, pcsCase, CaseFileCategory.UNCATEGORISED_DOCUMENTS); + for (CaseFileCategory category : CaseFileCategory.values()) { + setDocumentsForCategory(details, pcsCase, category); + } } public List validateAndStoreSelection(PCSCase caseData) { From 1d5a9c2ce46baf33bb71d57f43054668e5c1bd62 Mon Sep 17 00:00:00 2001 From: sadmanrahman Date: Thu, 2 Jul 2026 15:28:53 +0100 Subject: [PATCH 29/70] HDPI-7308: add tests --- .../documentamend/DocumentAmendDetails.java | 4 - .../documentamend/SelectDocumentPage.java | 8 +- .../DocumentAmendSelectionService.java | 20 +--- .../DocumentAmendSelectionServiceTest.java | 94 ++++++++++++------- 4 files changed, 65 insertions(+), 61 deletions(-) diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendDetails.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendDetails.java index 01c48908ab..fbc4668543 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendDetails.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendDetails.java @@ -34,10 +34,6 @@ public class DocumentAmendDetails { @JsonProperty("PropertyAddressSummary") private String propertyAddressSummary; - @CCD(searchable = false) - @JsonProperty("PartyNamesSummary") - private String partyNamesSummary; - @CCD( label = "Which document do you want to amend?", searchable = false, diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java index c1577d203a..59e7851a66 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java @@ -20,6 +20,7 @@ import java.util.List; import static uk.gov.hmcts.reform.pcs.ccd.ShowConditions.NEVER_SHOW; +import static uk.gov.hmcts.reform.pcs.ccd.service.document.DocumentAmendSelectionService.SELECT_DIFFERENT_FOLDER_ERROR; @AllArgsConstructor @Component @@ -29,7 +30,6 @@ public class SelectDocumentPage implements CcdPageConfiguration { private static final String FIELD_PREFIX = "documentAmend_"; private static final String YES = "=\"Yes\""; private static final String NO = "=\"No\""; - private static final String SELECT_DIFFERENT_FOLDER_ERROR = "Select a different folder to continue"; private final DocumentAmendSelectionService documentAmendSelectionService; @Override @@ -66,7 +66,7 @@ private void addCategoryFields(FieldCollectionBuilder DOCUMENT_ORDER = Comparator .comparing(DocumentEntity::getSubmittedDate, Comparator.nullsLast(Comparator.reverseOrder())) .thenComparing(DocumentEntity::getFileName, Comparator.nullsLast(String::compareToIgnoreCase)); private final PcsCaseService pcsCaseService; private final AddressFormatter addressFormatter; - private final CaseNameFormatter caseNameFormatter; - public DocumentAmendSelectionService(PcsCaseService pcsCaseService, AddressFormatter addressFormatter, - CaseNameFormatter caseNameFormatter) { + public DocumentAmendSelectionService(PcsCaseService pcsCaseService, AddressFormatter addressFormatter) { this.pcsCaseService = pcsCaseService; this.addressFormatter = addressFormatter; - this.caseNameFormatter = caseNameFormatter; } public void initialise(long caseReference, PCSCase caseData) { @@ -45,7 +41,6 @@ public void initialise(long caseReference, PCSCase caseData) { details.setPropertyAddressSummary(addressFormatter.formatShortAddress(caseData.getPropertyAddress(), COMMA_DELIMITER)); - details.setPartyNamesSummary(buildPartyNamesSummary(caseData)); for (CaseFileCategory category : CaseFileCategory.values()) { setDocumentsForCategory(details, pcsCase, category); } @@ -129,17 +124,6 @@ private boolean isEmpty(DynamicList documents) { return documents == null || CollectionUtils.isEmpty(documents.getListItems()); } - private String buildPartyNamesSummary(PCSCase caseData) { - if (caseData.getClaimantNames() != null && caseData.getDefendantNames() != null) { - return caseData.getClaimantNames() + " vs " + caseData.getDefendantNames(); - } - if (CollectionUtils.isEmpty(caseData.getAllClaimants()) - && CollectionUtils.isEmpty(caseData.getAllDefendants())) { - return null; - } - return caseNameFormatter.formatCaseName(caseData); - } - private DocumentAmendDetails getOrCreateDetails(PCSCase caseData) { if (caseData.getDocumentAmendDetails() == null) { caseData.setDocumentAmendDetails(new DocumentAmendDetails()); diff --git a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java index 350d3cf605..3b219b1347 100644 --- a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java +++ b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java @@ -12,14 +12,12 @@ import uk.gov.hmcts.ccd.sdk.type.YesOrNo; import uk.gov.hmcts.reform.pcs.ccd.domain.CaseFileCategory; import uk.gov.hmcts.reform.pcs.ccd.domain.PCSCase; -import uk.gov.hmcts.reform.pcs.ccd.domain.Party; import uk.gov.hmcts.reform.pcs.ccd.domain.VerticalYesNo; import uk.gov.hmcts.reform.pcs.ccd.domain.documentamend.DocumentAmendDetails; import uk.gov.hmcts.reform.pcs.ccd.domain.documentamend.DocumentAmendFolder; import uk.gov.hmcts.reform.pcs.ccd.entity.DocumentEntity; import uk.gov.hmcts.reform.pcs.ccd.entity.GenAppEntity; import uk.gov.hmcts.reform.pcs.ccd.entity.PcsCaseEntity; -import uk.gov.hmcts.reform.pcs.ccd.service.CaseNameFormatter; import uk.gov.hmcts.reform.pcs.ccd.service.PcsCaseService; import uk.gov.hmcts.reform.pcs.ccd.util.AddressFormatter; @@ -32,7 +30,6 @@ import static uk.gov.hmcts.reform.pcs.ccd.domain.CaseFileCategory.APPLICATIONS; import static uk.gov.hmcts.reform.pcs.ccd.domain.CaseFileCategory.EVIDENCE; import static uk.gov.hmcts.reform.pcs.ccd.domain.CaseFileCategory.UNCATEGORISED_DOCUMENTS; -import static uk.gov.hmcts.reform.pcs.ccd.util.ListValueUtils.wrapListItems; @ExtendWith(MockitoExtension.class) class DocumentAmendSelectionServiceTest { @@ -46,7 +43,7 @@ class DocumentAmendSelectionServiceTest { @BeforeEach void setUp() { - underTest = new DocumentAmendSelectionService(pcsCaseService, new AddressFormatter(), new CaseNameFormatter()); + underTest = new DocumentAmendSelectionService(pcsCaseService, new AddressFormatter()); } @Test @@ -67,7 +64,7 @@ void shouldDefineFolderDropdownWithCaseFileViewFolders() { } @Test - void shouldPopulateCompactCaseSummaryFields() { + void shouldPopulatePropertyAddressSummary() { when(pcsCaseService.loadCase(CASE_REFERENCE)).thenReturn(PcsCaseEntity.builder().build()); PCSCase caseData = PCSCase.builder() .propertyAddress(uk.gov.hmcts.ccd.sdk.type.AddressUK.builder() @@ -75,16 +72,12 @@ void shouldPopulateCompactCaseSummaryFields() { .postTown("Luton") .postCode("LU1 1AB") .build()) - .claimantNames("Treetops Housing") - .defendantNames("Billy Wright") .build(); underTest.initialise(CASE_REFERENCE, caseData); assertThat(caseData.getDocumentAmendDetails().getPropertyAddressSummary()) .isEqualTo("15 Garden Drive, Luton, LU1 1AB"); - assertThat(caseData.getDocumentAmendDetails().getPartyNamesSummary()) - .isEqualTo("Treetops Housing vs Billy Wright"); } @Test @@ -110,26 +103,6 @@ void shouldSerialiseDocumentAmendFieldsWithGeneratedCcdFieldIds() throws JsonPro assertThat(serialisedCaseData).doesNotContain("documentAmend_applicationsDocuments"); } - @Test - void shouldPopulatePartyNamesSummaryFromPartyCollectionsWhenSummaryFieldsAreMissing() { - when(pcsCaseService.loadCase(CASE_REFERENCE)).thenReturn(PcsCaseEntity.builder().build()); - PCSCase caseData = PCSCase.builder() - .allClaimants(wrapListItems(List.of(Party.builder() - .orgName("Treetops Housing") - .build()))) - .allDefendants(wrapListItems(List.of(Party.builder() - .firstName("Billy") - .lastName("Wright") - .nameKnown(VerticalYesNo.YES) - .build()))) - .build(); - - underTest.initialise(CASE_REFERENCE, caseData); - - assertThat(caseData.getDocumentAmendDetails().getPartyNamesSummary()) - .isEqualTo("Treetops Housing vs Billy Wright"); - } - @Test void shouldPopulateDocumentsForSelectedCategoryAndIncludeWithoutNoticeApplicationDocuments() { DocumentEntity visibleEvidence = document("visible evidence.pdf", EVIDENCE.getId(), null); @@ -162,15 +135,15 @@ void shouldPopulateDocumentsForSelectedCategoryAndIncludeWithoutNoticeApplicatio } @Test - void shouldOnlyShowDocumentsWithUncategorisedCategoryUnderUncategorisedDocuments() { - DocumentEntity uncategorisedDocument = document("loose document.pdf", null, null); + void shouldExcludeDocumentsWithNullCategoryIdFromUncategorisedDocuments() { + DocumentEntity nullCategoryDocument = document("loose document.pdf", null, null); DocumentEntity categorisedDocument = document( "uncategorised document.pdf", UNCATEGORISED_DOCUMENTS.getId(), null ); when(pcsCaseService.loadCase(CASE_REFERENCE)).thenReturn(PcsCaseEntity.builder() - .documents(List.of(uncategorisedDocument, categorisedDocument)) + .documents(List.of(nullCategoryDocument, categorisedDocument)) .build()); PCSCase caseData = PCSCase.builder().build(); @@ -182,6 +155,51 @@ void shouldOnlyShowDocumentsWithUncategorisedCategoryUnderUncategorisedDocuments assertThat(caseData.getDocumentAmendDetails().getUncategorisedDocumentsEmpty()).isEqualTo(YesOrNo.NO); } + @Test + void shouldOrderDocumentsBySubmittedDateDescendingThenFileNameWithNullDatesLast() { + DocumentEntity older = document( + "b older evidence.pdf", + EVIDENCE.getId(), + null, + Instant.parse("2026-01-01T10:00:00Z") + ); + DocumentEntity newerA = document( + "a newer evidence.pdf", + EVIDENCE.getId(), + null, + Instant.parse("2026-01-02T10:00:00Z") + ); + DocumentEntity newerB = document( + "b newer evidence.pdf", + EVIDENCE.getId(), + null, + Instant.parse("2026-01-02T10:00:00Z") + ); + DocumentEntity nullDate = document("null date evidence.pdf", EVIDENCE.getId(), null, null); + when(pcsCaseService.loadCase(CASE_REFERENCE)).thenReturn(PcsCaseEntity.builder() + .documents(List.of(older, nullDate, newerB, newerA)) + .build()); + PCSCase caseData = PCSCase.builder().build(); + + underTest.initialise(CASE_REFERENCE, caseData); + + assertThat(caseData.getDocumentAmendDetails().getEvidenceDocuments().getListItems()) + .extracting(DynamicListElement::getLabel) + .containsExactly( + "a newer evidence.pdf", + "b newer evidence.pdf", + "b older evidence.pdf", + "null date evidence.pdf" + ); + } + + @Test + void shouldReturnNoErrorsWhenDocumentAmendDetailsIsNull() { + List errors = underTest.validateAndStoreSelection(PCSCase.builder().build()); + + assertThat(errors).isEmpty(); + } + @Test void shouldReturnDifferentFolderErrorWhenSelectedFolderHasNoDocuments() { when(pcsCaseService.loadCase(CASE_REFERENCE)).thenReturn(PcsCaseEntity.builder().build()); @@ -195,7 +213,12 @@ void shouldReturnDifferentFolderErrorWhenSelectedFolderHasNoDocuments() { List errors = underTest.validateAndStoreSelection(caseData); assertThat(errors).containsExactly("Select a different folder to continue"); + assertThat(caseData.getDocumentAmendDetails().getSelectedFolderId()) + .isEqualTo(UNCATEGORISED_DOCUMENTS.getId()); + assertThat(caseData.getDocumentAmendDetails().getSelectedFolderLabel()) + .isEqualTo(UNCATEGORISED_DOCUMENTS.getLabel()); assertThat(caseData.getDocumentAmendDetails().getSelectedDocumentId()).isNull(); + assertThat(caseData.getDocumentAmendDetails().getSelectedDocumentFileName()).isNull(); } @Test @@ -289,12 +312,17 @@ private static DynamicList selectedDocument(DocumentEntity document) { } private static DocumentEntity document(String fileName, String categoryId, GenAppEntity generalApplication) { + return document(fileName, categoryId, generalApplication, Instant.now()); + } + + private static DocumentEntity document(String fileName, String categoryId, GenAppEntity generalApplication, + Instant submittedDate) { return DocumentEntity.builder() .id(UUID.randomUUID()) .fileName(fileName) .categoryId(categoryId) .generalApplication(generalApplication) - .submittedDate(Instant.now()) + .submittedDate(submittedDate) .build(); } } From ea4c96fe7196b94b518b36f31b721df532447254 Mon Sep 17 00:00:00 2001 From: sadmanrahman Date: Thu, 2 Jul 2026 16:39:36 +0100 Subject: [PATCH 30/70] HDPI-7308: resolve pr comments --- .../pcs/ccd/domain/CaseFileCategory.java | 3 +- .../documentamend/DocumentAmendDetails.java | 5 +- .../documentamend/DocumentAmendFolder.java | 27 ------- .../documentamend/DocumentCategoryField.java | 79 +++++++++++++++++++ .../documentamend/SelectDocumentPage.java | 75 ------------------ .../DocumentAmendSelectionService.java | 2 +- .../DocumentAmendSelectionServiceTest.java | 27 ++----- 7 files changed, 91 insertions(+), 127 deletions(-) delete mode 100644 src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendFolder.java create mode 100644 src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/DocumentCategoryField.java diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/CaseFileCategory.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/CaseFileCategory.java index b60f2e0e88..037290f7fc 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/CaseFileCategory.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/CaseFileCategory.java @@ -2,10 +2,11 @@ import lombok.AllArgsConstructor; import lombok.Getter; +import uk.gov.hmcts.ccd.sdk.api.HasLabel; @AllArgsConstructor @Getter -public enum CaseFileCategory { +public enum CaseFileCategory implements HasLabel { STATEMENTS_OF_CASE("statementsOfCase", "Statements of case", 1), PROPERTY_DOCUMENTS("propertyDocuments", "Property documents", 2), diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendDetails.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendDetails.java index fbc4668543..7973419d6f 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendDetails.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendDetails.java @@ -8,6 +8,7 @@ import lombok.Data; import lombok.NoArgsConstructor; import uk.gov.hmcts.ccd.sdk.api.CCD; +import uk.gov.hmcts.reform.pcs.ccd.domain.CaseFileCategory; import uk.gov.hmcts.ccd.sdk.type.DynamicList; import uk.gov.hmcts.ccd.sdk.type.YesOrNo; @@ -25,10 +26,10 @@ public class DocumentAmendDetails { label = "Which folder is the document in?", searchable = false, typeOverride = FixedList, - typeParameterOverride = "DocumentAmendFolder" + typeParameterOverride = "CaseFileCategory" ) @JsonProperty("SelectedFolder") - private DocumentAmendFolder selectedFolder; + private CaseFileCategory selectedFolder; @CCD(searchable = false) @JsonProperty("PropertyAddressSummary") diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendFolder.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendFolder.java deleted file mode 100644 index 073c023397..0000000000 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendFolder.java +++ /dev/null @@ -1,27 +0,0 @@ -package uk.gov.hmcts.reform.pcs.ccd.domain.documentamend; - -import lombok.Getter; -import uk.gov.hmcts.ccd.sdk.api.HasLabel; -import uk.gov.hmcts.reform.pcs.ccd.domain.CaseFileCategory; - -@Getter -public enum DocumentAmendFolder implements HasLabel { - - STATEMENTS_OF_CASE(CaseFileCategory.STATEMENTS_OF_CASE), - PROPERTY_DOCUMENTS(CaseFileCategory.PROPERTY_DOCUMENTS), - EVIDENCE(CaseFileCategory.EVIDENCE), - HEARING_DOCUMENTS(CaseFileCategory.HEARING_DOCUMENTS), - ORDERS_AND_NOTICE_OF_HEARINGS(CaseFileCategory.ORDERS_AND_NOTICE_OF_HEARINGS), - APPLICATIONS(CaseFileCategory.APPLICATIONS), - APPEALS(CaseFileCategory.APPEALS), - CORRESPONDENCE(CaseFileCategory.CORRESPONDENCE), - UNCATEGORISED_DOCUMENTS(CaseFileCategory.UNCATEGORISED_DOCUMENTS); - - private final CaseFileCategory category; - private final String label; - - DocumentAmendFolder(CaseFileCategory category) { - this.category = category; - this.label = category.getLabel(); - } -} diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/DocumentCategoryField.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/DocumentCategoryField.java new file mode 100644 index 0000000000..f00bd1792c --- /dev/null +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/DocumentCategoryField.java @@ -0,0 +1,79 @@ +package uk.gov.hmcts.reform.pcs.ccd.page.documentamend; + +import uk.gov.hmcts.ccd.sdk.api.TypedPropertyGetter; +import uk.gov.hmcts.ccd.sdk.type.DynamicList; +import uk.gov.hmcts.ccd.sdk.type.YesOrNo; +import uk.gov.hmcts.reform.pcs.ccd.domain.CaseFileCategory; +import uk.gov.hmcts.reform.pcs.ccd.domain.documentamend.DocumentAmendDetails; + +enum DocumentCategoryField { + STATEMENTS_OF_CASE( + CaseFileCategory.STATEMENTS_OF_CASE, + "statementsOfCase", + DocumentAmendDetails::getStatementsOfCaseDocuments, + DocumentAmendDetails::getStatementsOfCaseEmpty + ), + PROPERTY_DOCUMENTS( + CaseFileCategory.PROPERTY_DOCUMENTS, + "propertyDocuments", + DocumentAmendDetails::getPropertyDocuments, + DocumentAmendDetails::getPropertyDocumentsEmpty + ), + EVIDENCE( + CaseFileCategory.EVIDENCE, + "evidence", + DocumentAmendDetails::getEvidenceDocuments, + DocumentAmendDetails::getEvidenceEmpty + ), + HEARING_DOCUMENTS( + CaseFileCategory.HEARING_DOCUMENTS, + "hearingDocuments", + DocumentAmendDetails::getHearingDocuments, + DocumentAmendDetails::getHearingDocumentsEmpty + ), + ORDERS_AND_NOTICE_OF_HEARINGS( + CaseFileCategory.ORDERS_AND_NOTICE_OF_HEARINGS, + "ordersAndNoticeOfHearings", + DocumentAmendDetails::getOrdersAndNoticeOfHearingsDocuments, + DocumentAmendDetails::getOrdersAndNoticeOfHearingsEmpty + ), + APPLICATIONS( + CaseFileCategory.APPLICATIONS, + "applications", + DocumentAmendDetails::getApplicationsDocuments, + DocumentAmendDetails::getApplicationsEmpty + ), + APPEALS( + CaseFileCategory.APPEALS, + "appeals", + DocumentAmendDetails::getAppealsDocuments, + DocumentAmendDetails::getAppealsEmpty + ), + CORRESPONDENCE( + CaseFileCategory.CORRESPONDENCE, + "correspondence", + DocumentAmendDetails::getCorrespondenceDocuments, + DocumentAmendDetails::getCorrespondenceEmpty + ), + UNCATEGORISED_DOCUMENTS( + CaseFileCategory.UNCATEGORISED_DOCUMENTS, + "uncategorisedDocuments", + DocumentAmendDetails::getUncategorisedDocuments, + DocumentAmendDetails::getUncategorisedDocumentsEmpty + ); + + final CaseFileCategory category; + final String idPrefix; + final TypedPropertyGetter documentsGetter; + final TypedPropertyGetter emptyGetter; + + DocumentCategoryField(CaseFileCategory category, + String idPrefix, + TypedPropertyGetter documentsGetter, + TypedPropertyGetter emptyGetter) { + this.category = category; + this.idPrefix = idPrefix; + this.documentsGetter = documentsGetter; + this.emptyGetter = emptyGetter; + } +} diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java index 59e7851a66..ff8f1c08d1 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java @@ -4,10 +4,7 @@ import org.springframework.stereotype.Component; import uk.gov.hmcts.ccd.sdk.api.CaseDetails; import uk.gov.hmcts.ccd.sdk.api.FieldCollection.FieldCollectionBuilder; -import uk.gov.hmcts.ccd.sdk.api.TypedPropertyGetter; import uk.gov.hmcts.ccd.sdk.api.callback.AboutToStartOrSubmitResponse; -import uk.gov.hmcts.ccd.sdk.type.DynamicList; -import uk.gov.hmcts.ccd.sdk.type.YesOrNo; import uk.gov.hmcts.reform.pcs.ccd.common.CcdPageConfiguration; import uk.gov.hmcts.reform.pcs.ccd.common.PageBuilder; import uk.gov.hmcts.reform.pcs.ccd.domain.CaseFileCategory; @@ -124,76 +121,4 @@ private String documentQuestion() { private String errorMessage(String message) { return "

" + message + "

"; } - - private enum DocumentCategoryField { - STATEMENTS_OF_CASE( - CaseFileCategory.STATEMENTS_OF_CASE, - "statementsOfCase", - DocumentAmendDetails::getStatementsOfCaseDocuments, - DocumentAmendDetails::getStatementsOfCaseEmpty - ), - PROPERTY_DOCUMENTS( - CaseFileCategory.PROPERTY_DOCUMENTS, - "propertyDocuments", - DocumentAmendDetails::getPropertyDocuments, - DocumentAmendDetails::getPropertyDocumentsEmpty - ), - EVIDENCE( - CaseFileCategory.EVIDENCE, - "evidence", - DocumentAmendDetails::getEvidenceDocuments, - DocumentAmendDetails::getEvidenceEmpty - ), - HEARING_DOCUMENTS( - CaseFileCategory.HEARING_DOCUMENTS, - "hearingDocuments", - DocumentAmendDetails::getHearingDocuments, - DocumentAmendDetails::getHearingDocumentsEmpty - ), - ORDERS_AND_NOTICE_OF_HEARINGS( - CaseFileCategory.ORDERS_AND_NOTICE_OF_HEARINGS, - "ordersAndNoticeOfHearings", - DocumentAmendDetails::getOrdersAndNoticeOfHearingsDocuments, - DocumentAmendDetails::getOrdersAndNoticeOfHearingsEmpty - ), - APPLICATIONS( - CaseFileCategory.APPLICATIONS, - "applications", - DocumentAmendDetails::getApplicationsDocuments, - DocumentAmendDetails::getApplicationsEmpty - ), - APPEALS( - CaseFileCategory.APPEALS, - "appeals", - DocumentAmendDetails::getAppealsDocuments, - DocumentAmendDetails::getAppealsEmpty - ), - CORRESPONDENCE( - CaseFileCategory.CORRESPONDENCE, - "correspondence", - DocumentAmendDetails::getCorrespondenceDocuments, - DocumentAmendDetails::getCorrespondenceEmpty - ), - UNCATEGORISED_DOCUMENTS( - CaseFileCategory.UNCATEGORISED_DOCUMENTS, - "uncategorisedDocuments", - DocumentAmendDetails::getUncategorisedDocuments, - DocumentAmendDetails::getUncategorisedDocumentsEmpty - ); - - private final CaseFileCategory category; - private final String idPrefix; - private final TypedPropertyGetter documentsGetter; - private final TypedPropertyGetter emptyGetter; - - DocumentCategoryField(CaseFileCategory category, - String idPrefix, - TypedPropertyGetter documentsGetter, - TypedPropertyGetter emptyGetter) { - this.category = category; - this.idPrefix = idPrefix; - this.documentsGetter = documentsGetter; - this.emptyGetter = emptyGetter; - } - } } diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionService.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionService.java index d3469c171f..d79cdd874b 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionService.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionService.java @@ -52,7 +52,7 @@ public List validateAndStoreSelection(PCSCase caseData) { return List.of(); } - CaseFileCategory selectedFolder = details.getSelectedFolder().getCategory(); + CaseFileCategory selectedFolder = details.getSelectedFolder(); DynamicList selectedDocuments = documentsForCategory(details, selectedFolder); details.setSelectedFolderId(selectedFolder.getId()); details.setSelectedFolderLabel(selectedFolder.getLabel()); diff --git a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java index 3b219b1347..50b16bd77b 100644 --- a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java +++ b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java @@ -14,7 +14,6 @@ import uk.gov.hmcts.reform.pcs.ccd.domain.PCSCase; import uk.gov.hmcts.reform.pcs.ccd.domain.VerticalYesNo; import uk.gov.hmcts.reform.pcs.ccd.domain.documentamend.DocumentAmendDetails; -import uk.gov.hmcts.reform.pcs.ccd.domain.documentamend.DocumentAmendFolder; import uk.gov.hmcts.reform.pcs.ccd.entity.DocumentEntity; import uk.gov.hmcts.reform.pcs.ccd.entity.GenAppEntity; import uk.gov.hmcts.reform.pcs.ccd.entity.PcsCaseEntity; @@ -48,8 +47,8 @@ void setUp() { @Test void shouldDefineFolderDropdownWithCaseFileViewFolders() { - assertThat(DocumentAmendFolder.values()) - .extracting(DocumentAmendFolder::getLabel) + assertThat(CaseFileCategory.values()) + .extracting(CaseFileCategory::getLabel) .containsExactly( "Statements of case", "Property documents", @@ -205,7 +204,7 @@ void shouldReturnDifferentFolderErrorWhenSelectedFolderHasNoDocuments() { when(pcsCaseService.loadCase(CASE_REFERENCE)).thenReturn(PcsCaseEntity.builder().build()); PCSCase caseData = PCSCase.builder() .documentAmendDetails(DocumentAmendDetails.builder() - .selectedFolder(selectedFolder(UNCATEGORISED_DOCUMENTS)) + .selectedFolder(UNCATEGORISED_DOCUMENTS) .build()) .build(); underTest.initialise(CASE_REFERENCE, caseData); @@ -229,7 +228,7 @@ void shouldTreatEmptyDocumentSelectionAsNoSelection() { .build()); PCSCase caseData = PCSCase.builder() .documentAmendDetails(DocumentAmendDetails.builder() - .selectedFolder(selectedFolder(EVIDENCE)) + .selectedFolder(EVIDENCE) .evidenceDocuments(DynamicList.builder() .build()) .build()) @@ -251,7 +250,7 @@ void shouldPersistSelectedFolderAndDocumentDetails() { .build()); PCSCase caseData = PCSCase.builder() .documentAmendDetails(DocumentAmendDetails.builder() - .selectedFolder(selectedFolder(EVIDENCE)) + .selectedFolder(EVIDENCE) .evidenceDocuments(selectedDocument(document)) .build()) .build(); @@ -274,7 +273,7 @@ void shouldLeaveMissingDocumentSelectionToExuiMandatoryValidation() { .build()); PCSCase caseData = PCSCase.builder() .documentAmendDetails(DocumentAmendDetails.builder() - .selectedFolder(selectedFolder(EVIDENCE)) + .selectedFolder(EVIDENCE) .build()) .build(); underTest.initialise(CASE_REFERENCE, caseData); @@ -285,20 +284,6 @@ void shouldLeaveMissingDocumentSelectionToExuiMandatoryValidation() { assertThat(caseData.getDocumentAmendDetails().getSelectedDocumentId()).isNull(); } - private static DocumentAmendFolder selectedFolder(CaseFileCategory category) { - return switch (category) { - case STATEMENTS_OF_CASE -> DocumentAmendFolder.STATEMENTS_OF_CASE; - case PROPERTY_DOCUMENTS -> DocumentAmendFolder.PROPERTY_DOCUMENTS; - case EVIDENCE -> DocumentAmendFolder.EVIDENCE; - case HEARING_DOCUMENTS -> DocumentAmendFolder.HEARING_DOCUMENTS; - case ORDERS_AND_NOTICE_OF_HEARINGS -> DocumentAmendFolder.ORDERS_AND_NOTICE_OF_HEARINGS; - case APPLICATIONS -> DocumentAmendFolder.APPLICATIONS; - case APPEALS -> DocumentAmendFolder.APPEALS; - case CORRESPONDENCE -> DocumentAmendFolder.CORRESPONDENCE; - case UNCATEGORISED_DOCUMENTS -> DocumentAmendFolder.UNCATEGORISED_DOCUMENTS; - }; - } - private static DynamicList selectedDocument(DocumentEntity document) { DynamicListElement selectedDocument = DynamicListElement.builder() .code(document.getId()) From 519663a5121cbf337461dd57bf56671985a12a63 Mon Sep 17 00:00:00 2001 From: sadmanrahman Date: Fri, 3 Jul 2026 09:34:09 +0100 Subject: [PATCH 31/70] HDPI-7308: uncategorisedDocuments fix --- .../ccd/service/document/DocumentService.java | 21 +++++++++++++------ ...efault_uncategorised_document_category.sql | 6 ++++++ .../service/document/DocumentServiceTest.java | 11 +++++----- 3 files changed, 27 insertions(+), 11 deletions(-) create mode 100644 src/main/resources/db/migration/V129__default_uncategorised_document_category.sql diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentService.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentService.java index 0a023e0b77..3553d7d93a 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentService.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentService.java @@ -54,6 +54,7 @@ public class DocumentService { private final DocumentNameService documentNameService; private static final String CLAIMANT_1 = "Claimant 1"; + private static final String DEFAULT_CATEGORY_ID = CaseFileCategory.UNCATEGORISED_DOCUMENTS.getId(); public List createAllDocuments(PCSCase pcsCase) { @@ -188,9 +189,7 @@ private List createDocumentEntities( .documentId(documentIdExtractor.extractDocumentId(holder.getDocument().getUrl())) .fileName(holder.getDocument().getFilename()) .binaryUrl(holder.getDocument().getBinaryUrl()) - .categoryId(mapDocumentTypeToCategory(holder.getType()) - .map(CaseFileCategory::getId) - .orElse(null)) + .categoryId(categoryIdFor(holder.getType())) .type(holder.getType()) .description(StringUtils.isEmpty(holder.getDescription()) ? null : holder.getDescription()) .build()) @@ -249,8 +248,6 @@ public List linkAdditionalDocumentsToCase( .collect(Collectors.toSet()); ClaimEntity mainClaim = getMainClaim(pcsCase); - String applicationsCategoryId = CaseFileCategory.APPLICATIONS.getId(); - List documentEntities = uploadedDocuments.stream() .map(ListValue::getValue) .filter(Objects::nonNull) @@ -272,7 +269,7 @@ public List linkAdditionalDocumentsToCase( .contentType(uploaded.getContentType()) .size(uploaded.getSizeInBytes()) .type(DocumentType.OTHER) - .categoryId(selectedGenApp != null ? applicationsCategoryId : null) + .categoryId(selectedGenApp != null ? CaseFileCategory.APPLICATIONS.getId() : DEFAULT_CATEGORY_ID) .build(); }) .toList(); @@ -329,6 +326,7 @@ public List createDefendantUploadedDocuments( .binaryUrl(defDoc.getDocument().getBinaryUrl()) .contentType(defDoc.getContentType()) .size(defDoc.getSizeInBytes()) + .categoryId(DEFAULT_CATEGORY_ID) .build(); }) .toList(); @@ -364,6 +362,7 @@ public List createCounterClaimUploadedDocuments( .binaryUrl(ccDoc.getDocument().getBinaryUrl()) .contentType(ccDoc.getContentType()) .size(ccDoc.getSizeInBytes()) + .categoryId(DEFAULT_CATEGORY_ID) .build()) .toList(); @@ -405,6 +404,16 @@ private Optional mapDocumentTypeToCategory(DocumentType docume }; } + private String categoryIdFor(DocumentType documentType) { + if (documentType == null) { + return DEFAULT_CATEGORY_ID; + } + + return mapDocumentTypeToCategory(documentType) + .map(CaseFileCategory::getId) + .orElse(DEFAULT_CATEGORY_ID); + } + private DocumentType mapEvidenceDocumentTypeToDocumentType(EvidenceDocumentType evidenceDocumentType) { return switch (evidenceDocumentType) { case PHOTOGRAPHIC_EVIDENCE -> DocumentType.PHOTOGRAPHIC_EVIDENCE; diff --git a/src/main/resources/db/migration/V129__default_uncategorised_document_category.sql b/src/main/resources/db/migration/V129__default_uncategorised_document_category.sql new file mode 100644 index 0000000000..313d680ff8 --- /dev/null +++ b/src/main/resources/db/migration/V129__default_uncategorised_document_category.sql @@ -0,0 +1,6 @@ +UPDATE document +SET category_id = 'uncategorisedDocuments' +WHERE category_id IS NULL; + +ALTER TABLE document +ALTER COLUMN category_id SET DEFAULT 'uncategorisedDocuments'; diff --git a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentServiceTest.java b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentServiceTest.java index f9114762d7..0b3078b695 100644 --- a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentServiceTest.java +++ b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentServiceTest.java @@ -485,7 +485,8 @@ void shouldPersistNullCategoryForPoliceReportEvidenceDocuments() { List capturedEntities = documentEntityListCaptor.getValue(); assertThat(capturedEntities).hasSize(1); - assertThat(capturedEntities.getFirst().getCategoryId()).isNull(); + assertThat(capturedEntities.getFirst().getCategoryId()) + .isEqualTo(CaseFileCategory.UNCATEGORISED_DOCUMENTS.getId()); } @Test @@ -769,7 +770,7 @@ void shouldSaveDefendantEvidenceDocuments() { assertThat(entities).allSatisfy(entity -> { assertThat(entity.getType()).isNull(); - assertThat(entity.getCategoryId()).isNull(); + assertThat(entity.getCategoryId()).isEqualTo(CaseFileCategory.UNCATEGORISED_DOCUMENTS.getId()); assertThat(entity.getDefendantResponse()).isEqualTo(response); assertThat(entity.getPcsCase()).isEqualTo(pcsCase); assertThat(entity.getParty()).isEqualTo(party); @@ -967,7 +968,7 @@ void shouldSaveAdditionalDocumentsForPartyAsOtherTypeWithPartyPostfixWhenNoGenAp assertThat(entities).hasSize(1); DocumentEntity entity = entities.getFirst(); assertThat(entity.getType()).isEqualTo(DocumentType.OTHER); - assertThat(entity.getCategoryId()).isNull(); + assertThat(entity.getCategoryId()).isEqualTo(CaseFileCategory.UNCATEGORISED_DOCUMENTS.getId()); assertThat(entity.getGeneralApplication()).isNull(); assertThat(entity.getUrl()).isEqualTo("url-new"); assertThat(entity.getFileName()).isEqualTo("file-new - Defendant 1.pdf"); @@ -1169,7 +1170,7 @@ private static Stream additionalDocumentCategoryScenarios() { Arguments.of(AdditionalDocumentType.CERTIFICATE_OF_SUITABILITY_AS_LF, CaseFileCategory.CORRESPONDENCE.getId()), Arguments.of(AdditionalDocumentType.LEGAL_AID_CERTIFICATE, CaseFileCategory.CORRESPONDENCE.getId()), - Arguments.of(AdditionalDocumentType.OTHER, null) + Arguments.of(AdditionalDocumentType.OTHER, CaseFileCategory.UNCATEGORISED_DOCUMENTS.getId()) ); } @@ -1213,7 +1214,7 @@ void shouldSaveCounterClaimDocuments() { assertThat(entities).allSatisfy(entity -> { assertThat(entity.getType()).isNull(); - assertThat(entity.getCategoryId()).isNull(); + assertThat(entity.getCategoryId()).isEqualTo(CaseFileCategory.UNCATEGORISED_DOCUMENTS.getId()); assertThat(entity.getCounterClaim()).isEqualTo(counterClaim); assertThat(entity.getPcsCase()).isEqualTo(pcsCase); assertThat(entity.getParty()).isEqualTo(party); From 9d9932bc55171f470fde2e39688270cf27c67aff Mon Sep 17 00:00:00 2001 From: sadmanrahman Date: Fri, 3 Jul 2026 09:41:46 +0100 Subject: [PATCH 32/70] HDPI-7308: Fix JsonNaming --- .../documentamend/DocumentAmendDetails.java | 28 ++----------------- 1 file changed, 3 insertions(+), 25 deletions(-) diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendDetails.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendDetails.java index 7973419d6f..bd0f751490 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendDetails.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendDetails.java @@ -2,7 +2,8 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; -import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.PropertyNamingStrategies; +import com.fasterxml.jackson.databind.annotation.JsonNaming; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -20,6 +21,7 @@ @NoArgsConstructor @AllArgsConstructor @JsonInclude(Include.NON_NULL) +@JsonNaming(PropertyNamingStrategies.UpperCamelCaseStrategy.class) public class DocumentAmendDetails { @CCD( @@ -28,11 +30,9 @@ public class DocumentAmendDetails { typeOverride = FixedList, typeParameterOverride = "CaseFileCategory" ) - @JsonProperty("SelectedFolder") private CaseFileCategory selectedFolder; @CCD(searchable = false) - @JsonProperty("PropertyAddressSummary") private String propertyAddressSummary; @CCD( @@ -40,7 +40,6 @@ public class DocumentAmendDetails { searchable = false, typeOverride = DynamicRadioList ) - @JsonProperty("StatementsOfCaseDocuments") private DynamicList statementsOfCaseDocuments; @CCD( @@ -48,7 +47,6 @@ public class DocumentAmendDetails { searchable = false, typeOverride = DynamicRadioList ) - @JsonProperty("PropertyDocuments") private DynamicList propertyDocuments; @CCD( @@ -56,7 +54,6 @@ public class DocumentAmendDetails { searchable = false, typeOverride = DynamicRadioList ) - @JsonProperty("EvidenceDocuments") private DynamicList evidenceDocuments; @CCD( @@ -64,7 +61,6 @@ public class DocumentAmendDetails { searchable = false, typeOverride = DynamicRadioList ) - @JsonProperty("HearingDocuments") private DynamicList hearingDocuments; @CCD( @@ -72,7 +68,6 @@ public class DocumentAmendDetails { searchable = false, typeOverride = DynamicRadioList ) - @JsonProperty("OrdersAndNoticeOfHearingsDocuments") private DynamicList ordersAndNoticeOfHearingsDocuments; @CCD( @@ -80,7 +75,6 @@ public class DocumentAmendDetails { searchable = false, typeOverride = DynamicRadioList ) - @JsonProperty("ApplicationsDocuments") private DynamicList applicationsDocuments; @CCD( @@ -88,7 +82,6 @@ public class DocumentAmendDetails { searchable = false, typeOverride = DynamicRadioList ) - @JsonProperty("AppealsDocuments") private DynamicList appealsDocuments; @CCD( @@ -96,7 +89,6 @@ public class DocumentAmendDetails { searchable = false, typeOverride = DynamicRadioList ) - @JsonProperty("CorrespondenceDocuments") private DynamicList correspondenceDocuments; @CCD( @@ -104,58 +96,44 @@ public class DocumentAmendDetails { searchable = false, typeOverride = DynamicRadioList ) - @JsonProperty("UncategorisedDocuments") private DynamicList uncategorisedDocuments; @CCD(searchable = false) - @JsonProperty("StatementsOfCaseEmpty") private YesOrNo statementsOfCaseEmpty; @CCD(searchable = false) - @JsonProperty("PropertyDocumentsEmpty") private YesOrNo propertyDocumentsEmpty; @CCD(searchable = false) - @JsonProperty("EvidenceEmpty") private YesOrNo evidenceEmpty; @CCD(searchable = false) - @JsonProperty("HearingDocumentsEmpty") private YesOrNo hearingDocumentsEmpty; @CCD(searchable = false) - @JsonProperty("OrdersAndNoticeOfHearingsEmpty") private YesOrNo ordersAndNoticeOfHearingsEmpty; @CCD(searchable = false) - @JsonProperty("ApplicationsEmpty") private YesOrNo applicationsEmpty; @CCD(searchable = false) - @JsonProperty("AppealsEmpty") private YesOrNo appealsEmpty; @CCD(searchable = false) - @JsonProperty("CorrespondenceEmpty") private YesOrNo correspondenceEmpty; @CCD(searchable = false) - @JsonProperty("UncategorisedDocumentsEmpty") private YesOrNo uncategorisedDocumentsEmpty; @CCD(searchable = false) - @JsonProperty("SelectedFolderId") private String selectedFolderId; @CCD(searchable = false) - @JsonProperty("SelectedFolderLabel") private String selectedFolderLabel; @CCD(searchable = false) - @JsonProperty("SelectedDocumentId") private String selectedDocumentId; @CCD(searchable = false) - @JsonProperty("SelectedDocumentFileName") private String selectedDocumentFileName; } From df2efa44c00f7c6fb683e90a2617b098f12e0cd2 Mon Sep 17 00:00:00 2001 From: Liban Abdirahman Date: Fri, 3 Jul 2026 10:27:35 +0100 Subject: [PATCH 33/70] HDPI-6502:Updating roles and adding tests --- .../uk/gov/hmcts/reform/pcs/ccd/CaseType.java | 6 +- .../pcs/ccd/accesscontrol/AccessGrants.java | 7 +- .../pcs/ccd/accesscontrol/AccessProfile.java | 20 ++--- .../ccd/accesscontrol/CaseworkerRoles.java | 17 +++++ .../pcs/ccd/accesscontrol/UserRole.java | 1 + .../hmcts/reform/pcs/ccd/domain/State.java | 4 +- .../changecasestate/ChangeCaseState.java | 11 +-- .../accesscontrol/CaseworkerRolesTest.java | 29 +++++++ .../changecasestate/ChangeCaseStateTest.java | 76 +++++++++++++++++++ 9 files changed, 151 insertions(+), 20 deletions(-) create mode 100644 src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/CaseworkerRoles.java create mode 100644 src/test/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/CaseworkerRolesTest.java create mode 100644 src/test/java/uk/gov/hmcts/reform/pcs/ccd/event/changecasestate/ChangeCaseStateTest.java diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/CaseType.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/CaseType.java index 077dd4c12b..002d9ed400 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/CaseType.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/CaseType.java @@ -40,7 +40,8 @@ public class CaseType implements CCDConfig { AccessProfile.LEADERSHIP_JUDGE, AccessProfile.HEARING_CENTRE_ADMIN, AccessProfile.CTSC_ADMIN, - AccessProfile.WLU_ADMIN + AccessProfile.WLU_ADMIN, + AccessProfile.BAILIFF_ADMIN }; static final AccessProfile[] INTERNAL_TAB_ROLES = { AccessProfile.JUDGE, @@ -49,7 +50,8 @@ public class CaseType implements CCDConfig { AccessProfile.LEADERSHIP_JUDGE, AccessProfile.HEARING_CENTRE_ADMIN, AccessProfile.CTSC_ADMIN, - AccessProfile.WLU_ADMIN + AccessProfile.WLU_ADMIN, + AccessProfile.BAILIFF_ADMIN }; static final AccessProfile[] NON_INTERNAL_HISTORY_ROLES = nonInternalHistoryRoles(); diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/AccessGrants.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/AccessGrants.java index 33882d4cfb..e797f44552 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/AccessGrants.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/AccessGrants.java @@ -5,6 +5,7 @@ import uk.gov.hmcts.ccd.sdk.api.HasRole; import uk.gov.hmcts.ccd.sdk.api.Permission; +import static uk.gov.hmcts.reform.pcs.ccd.accesscontrol.UserRole.BAILIFF_ADMIN; import static uk.gov.hmcts.reform.pcs.ccd.accesscontrol.UserRole.CIRCUIT_JUDGE; import static uk.gov.hmcts.reform.pcs.ccd.accesscontrol.UserRole.CITIZEN; import static uk.gov.hmcts.reform.pcs.ccd.accesscontrol.UserRole.CLAIMANT_SOLICITOR; @@ -32,7 +33,8 @@ final class AccessGrants { LEADERSHIP_JUDGE, HEARING_CENTRE_ADMIN, CTSC_ADMIN, - WLU_ADMIN + WLU_ADMIN, + BAILIFF_ADMIN }; static final UserRole[] INTERNAL_READ_ROLES = { @@ -42,7 +44,8 @@ final class AccessGrants { LEADERSHIP_JUDGE, HEARING_CENTRE_ADMIN, CTSC_ADMIN, - WLU_ADMIN + WLU_ADMIN, + BAILIFF_ADMIN }; private AccessGrants() { diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/AccessProfile.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/AccessProfile.java index e0bfb043d1..ca596cca0a 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/AccessProfile.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/AccessProfile.java @@ -1,15 +1,16 @@ package uk.gov.hmcts.reform.pcs.ccd.accesscontrol; -import static java.util.Arrays.stream; -import static uk.gov.hmcts.ccd.sdk.api.Permission.CRU; -import static uk.gov.hmcts.ccd.sdk.api.Permission.R; - import com.fasterxml.jackson.annotation.JsonValue; -import java.util.Set; import lombok.Getter; import uk.gov.hmcts.ccd.sdk.api.HasRole; import uk.gov.hmcts.ccd.sdk.api.Permission; +import java.util.Set; + +import static java.util.Arrays.stream; +import static uk.gov.hmcts.ccd.sdk.api.Permission.CRU; +import static uk.gov.hmcts.ccd.sdk.api.Permission.R; + @Getter public enum AccessProfile implements HasRole { @@ -22,10 +23,11 @@ public enum AccessProfile implements HasRole { PCS_CASE_WORKER("caseworker-pcs", CRU), PCS_SOLICITOR("caseworker-pcs-solicitor", CRU), - JUDGE("judge", Set.of(R)), - FEE_PAID_JUDGE("fee-paid-judge", Set.of(R)), - CIRCUIT_JUDGE("circuit-judge", Set.of(R)), - LEADERSHIP_JUDGE("leadership-judge", Set.of(R)), + JUDGE("judge", CRU), + FEE_PAID_JUDGE("fee-paid-judge", CRU), + CIRCUIT_JUDGE("circuit-judge", CRU), + LEADERSHIP_JUDGE("leadership-judge", CRU), + BAILIFF_ADMIN("bailiff-admin", CRU), CTSC_TEAM_LEADER("ctsc-team-leader", Permission.CRU), CTSC_ADMIN("ctsc", Permission.CRU), HEARING_CENTRE_TEAM_LEADER("hearing-centre-team-leader", Permission.CRU), diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/CaseworkerRoles.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/CaseworkerRoles.java new file mode 100644 index 0000000000..7ac2005148 --- /dev/null +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/CaseworkerRoles.java @@ -0,0 +1,17 @@ +package uk.gov.hmcts.reform.pcs.ccd.accesscontrol; + +public final class CaseworkerRoles { + + public static final UserRole[] CASEWORKER_ROLES = { + UserRole.HEARING_CENTRE_TEAM_LEADER, + UserRole.HEARING_CENTRE_ADMIN, + UserRole.CTSC_TEAM_LEADER, + UserRole.CTSC_ADMIN, + UserRole.BAILIFF_ADMIN, + UserRole.WLU_TEAM_LEADER, + UserRole.WLU_ADMIN + }; + + private CaseworkerRoles() { + } +} \ No newline at end of file diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/UserRole.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/UserRole.java index d2220d1733..39ada7d410 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/UserRole.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/UserRole.java @@ -45,6 +45,7 @@ public enum UserRole implements HasRole { LEADERSHIP_JUDGE("leadership-judge", Set.of(R), RAS), CIRCUIT_JUDGE("circuit-judge", Set.of(R), RAS), JUDGE("judge", Set.of(R), RAS), + BAILIFF_ADMIN("bailiff-admin", Permission.CRU, RAS), SYSTEM_USER("pcs-system-update", Permission.CRU, IDAM); diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/State.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/State.java index 5289fff263..243dcd4217 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/State.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/State.java @@ -21,7 +21,7 @@ public enum State { @CCD( label = "Awaiting Submission to HMCTS", - access = {ClaimantAccess.class, CitizenAccess.class, RasValidationAccess.class,CaseworkerReadAccess.class}, + access = {ClaimantAccess.class, CitizenAccess.class, RasValidationAccess.class}, hint = "${caseTitleMarkdown}" ) AWAITING_SUBMISSION_TO_HMCTS, @@ -29,7 +29,7 @@ public enum State { @CCD( label = "Pending Case Issued", access = {ClaimantAccess.class, CitizenAccess.class, RasValidationAccess.class, - InternalCaseFlagAccess.class, GlobalSearchAccess.class,CaseworkerReadAccess.class}, + InternalCaseFlagAccess.class, GlobalSearchAccess.class}, hint = "${caseTitleMarkdown}" ) PENDING_CASE_ISSUED, diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/changecasestate/ChangeCaseState.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/changecasestate/ChangeCaseState.java index 19ee402cf0..997d841a2d 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/changecasestate/ChangeCaseState.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/changecasestate/ChangeCaseState.java @@ -15,6 +15,7 @@ import uk.gov.hmcts.reform.pcs.ccd.page.changecasestate.ChangeCaseStatePage; import uk.gov.hmcts.reform.pcs.ccd.util.AddressFormatter; +import static uk.gov.hmcts.reform.pcs.ccd.accesscontrol.CaseworkerRoles.CASEWORKER_ROLES; import static uk.gov.hmcts.reform.pcs.ccd.accesscontrol.JudicialHistoryRoles.JUDICIAL_HISTORY_ROLES; import static uk.gov.hmcts.reform.pcs.ccd.event.EventId.changeCaseState; import static uk.gov.hmcts.reform.pcs.ccd.util.AddressFormatter.COMMA_DELIMITER; @@ -30,6 +31,7 @@ public void configureDecentralised(DecentralisedConfigBuilder eventBuilder = configBuilder .decentralisedEvent(changeCaseState.name(), this::submit) .forStates( + State.CASE_ISSUED, State.JUDICIAL_REFERRAL, State.HEARING_READINESS, State.PREPARE_FOR_HEARING_CONDUCT_HEARING, @@ -40,6 +42,7 @@ public void configureDecentralised(DecentralisedConfigBuilder - Case state changed -
- Case number: %s
- Property address: %s -
+ Case state changed
+ Case number: %s
+ Property address: %s

What happens next

diff --git a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/CaseworkerRolesTest.java b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/CaseworkerRolesTest.java new file mode 100644 index 0000000000..3f5bfc2475 --- /dev/null +++ b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/CaseworkerRolesTest.java @@ -0,0 +1,29 @@ +package uk.gov.hmcts.reform.pcs.ccd.accesscontrol; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static uk.gov.hmcts.reform.pcs.ccd.accesscontrol.CaseworkerRoles.CASEWORKER_ROLES; +import static uk.gov.hmcts.reform.pcs.ccd.accesscontrol.UserRole.BAILIFF_ADMIN; +import static uk.gov.hmcts.reform.pcs.ccd.accesscontrol.UserRole.CTSC_ADMIN; +import static uk.gov.hmcts.reform.pcs.ccd.accesscontrol.UserRole.CTSC_TEAM_LEADER; +import static uk.gov.hmcts.reform.pcs.ccd.accesscontrol.UserRole.HEARING_CENTRE_ADMIN; +import static uk.gov.hmcts.reform.pcs.ccd.accesscontrol.UserRole.HEARING_CENTRE_TEAM_LEADER; +import static uk.gov.hmcts.reform.pcs.ccd.accesscontrol.UserRole.WLU_ADMIN; +import static uk.gov.hmcts.reform.pcs.ccd.accesscontrol.UserRole.WLU_TEAM_LEADER; + +class CaseworkerRolesTest { + + @Test + void shouldContainAllCaseworkerRasRoles() { + assertThat(CASEWORKER_ROLES).containsExactlyInAnyOrder( + HEARING_CENTRE_TEAM_LEADER, + HEARING_CENTRE_ADMIN, + CTSC_TEAM_LEADER, + CTSC_ADMIN, + BAILIFF_ADMIN, + WLU_TEAM_LEADER, + WLU_ADMIN + ); + } +} diff --git a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/event/changecasestate/ChangeCaseStateTest.java b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/event/changecasestate/ChangeCaseStateTest.java new file mode 100644 index 0000000000..26d469c42e --- /dev/null +++ b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/event/changecasestate/ChangeCaseStateTest.java @@ -0,0 +1,76 @@ +package uk.gov.hmcts.reform.pcs.ccd.event.changecasestate; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import uk.gov.hmcts.ccd.sdk.api.callback.SubmitResponse; +import uk.gov.hmcts.reform.pcs.ccd.domain.CaseStateOption; +import uk.gov.hmcts.reform.pcs.ccd.domain.PCSCase; +import uk.gov.hmcts.reform.pcs.ccd.domain.State; +import uk.gov.hmcts.reform.pcs.ccd.event.BaseEventTest; +import uk.gov.hmcts.reform.pcs.ccd.util.AddressFormatter; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.isNull; +import static org.mockito.Mockito.when; +import static uk.gov.hmcts.reform.pcs.ccd.util.AddressFormatter.COMMA_DELIMITER; + +@ExtendWith(MockitoExtension.class) +class ChangeCaseStateTest extends BaseEventTest { + + private static final String FORMATTED_ADDRESS = "1 Test Street, London, SW1A 1AA"; + + @Mock + private AddressFormatter addressFormatter; + + @InjectMocks + private ChangeCaseState changeCaseState; + + @BeforeEach + void setUp() { + setEventUnderTest(changeCaseState); + when(addressFormatter.formatShortAddress(isNull(), eq(COMMA_DELIMITER))) + .thenReturn(FORMATTED_ADDRESS); + } + + @ParameterizedTest + @EnumSource(CaseStateOption.class) + void shouldTransitionToSelectedTargetState(CaseStateOption targetState) { + PCSCase pcsCase = PCSCase.builder() + .targetState(targetState) + .build(); + + SubmitResponse response = callSubmitHandler(pcsCase); + + assertThat(response.getState()).isEqualTo(targetState.toState()); + } + + @Test + void shouldIncludeCaseReferenceInConfirmationBody() { + PCSCase pcsCase = PCSCase.builder() + .targetState(CaseStateOption.JUDICIAL_REFERRAL) + .build(); + + SubmitResponse response = callSubmitHandler(pcsCase); + + assertThat(response.getConfirmationBody()) + .contains(String.valueOf(TEST_CASE_REFERENCE)); + } + + @Test + void shouldIncludeFormattedAddressInConfirmationBody() { + PCSCase pcsCase = PCSCase.builder() + .targetState(CaseStateOption.HEARING_READINESS) + .build(); + + SubmitResponse response = callSubmitHandler(pcsCase); + + assertThat(response.getConfirmationBody()).contains(FORMATTED_ADDRESS); + } +} \ No newline at end of file From 90dcdddaa1932023eef26ccbe5fcec8bb8ffde2b Mon Sep 17 00:00:00 2001 From: Liban Abdirahman Date: Fri, 3 Jul 2026 10:39:20 +0100 Subject: [PATCH 34/70] HDPI-6502:Fixing checkstyle issues --- .../uk/gov/hmcts/reform/pcs/ccd/domain/CaseStateOption.java | 6 +++--- .../pcs/ccd/event/changecasestate/ChangeCaseState.java | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/CaseStateOption.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/CaseStateOption.java index 349bf889ee..d9230aeac6 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/CaseStateOption.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/CaseStateOption.java @@ -15,11 +15,11 @@ public enum CaseStateOption implements HasLabel { JUDICIAL_REFERRAL("Judicial Referral"), HEARING_READINESS("Hearing Readiness"), - PREPARE_FOR_HEARING_CONDUCT_HEARING ("Prepare For Hearing Conduct Hearing"), + PREPARE_FOR_HEARING_CONDUCT_HEARING("Prepare For Hearing Conduct Hearing"), DECISION_OUTCOME("Decision Outcome"), CASE_PROGRESSION("Case Progression"), - ALL_FINAL_ORDERS_ISSUED ("All Final Orders"), - CASE_STAYED ("Case Stayed"), + ALL_FINAL_ORDERS_ISSUED("All Final Orders"), + CASE_STAYED("Case Stayed"), BREATHING_SPACE("Breathing space"); private final String label; diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/changecasestate/ChangeCaseState.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/changecasestate/ChangeCaseState.java index 997d841a2d..951790ab80 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/changecasestate/ChangeCaseState.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/changecasestate/ChangeCaseState.java @@ -72,7 +72,8 @@ private String buildConfirmationMarkdown(PCSCase pcsCase, long caseReference) {

What happens next

-

The case will progress according to the state it has been changed to.

+

The case will progress according to the state it has been + changed to.

""".formatted(caseReference, address); } } From 66b9ba27a0ce106f192f00ac374684d4341f283b Mon Sep 17 00:00:00 2001 From: Liban Abdirahman Date: Fri, 3 Jul 2026 10:49:50 +0100 Subject: [PATCH 35/70] HDPI-6502:Adding missing access on new states --- .../gov/hmcts/reform/pcs/ccd/domain/State.java | 16 ++++++++-------- .../event/changecasestate/ChangeCaseState.java | 1 - 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/State.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/State.java index 243dcd4217..405b6273e3 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/State.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/State.java @@ -44,56 +44,56 @@ public enum State { @CCD( label = "Judicial Referral", - access = {CaseworkerReadAccess.class, ClaimantAccess.class}, + access = {CaseworkerReadAccess.class, ClaimantAccess.class, RasValidationAccess.class, GlobalSearchAccess.class}, hint = "${caseTitleMarkdown}" ) JUDICIAL_REFERRAL, @CCD( label = "Hearing Readiness", - access = {CaseworkerReadAccess.class, ClaimantAccess.class}, + access = {CaseworkerReadAccess.class, ClaimantAccess.class, RasValidationAccess.class, GlobalSearchAccess.class}, hint = "${caseTitleMarkdown}" ) HEARING_READINESS, @CCD( label = "Prepare For Hearing Conduct Hearing", - access = {CaseworkerReadAccess.class, ClaimantAccess.class}, + access = {CaseworkerReadAccess.class, ClaimantAccess.class, RasValidationAccess.class, GlobalSearchAccess.class}, hint = "${caseTitleMarkdown}" ) PREPARE_FOR_HEARING_CONDUCT_HEARING, @CCD( label = "Decision Outcome", - access = {CaseworkerReadAccess.class, ClaimantAccess.class}, + access = {CaseworkerReadAccess.class, ClaimantAccess.class, RasValidationAccess.class, GlobalSearchAccess.class}, hint = "${caseTitleMarkdown}" ) DECISION_OUTCOME, @CCD( label = "Case Progression", - access = {CaseworkerReadAccess.class, ClaimantAccess.class}, + access = {CaseworkerReadAccess.class, ClaimantAccess.class, RasValidationAccess.class, GlobalSearchAccess.class}, hint = "${caseTitleMarkdown}" ) CASE_PROGRESSION, @CCD( label = "All Final Orders", - access = {CaseworkerReadAccess.class, ClaimantAccess.class}, + access = {CaseworkerReadAccess.class, ClaimantAccess.class, RasValidationAccess.class, GlobalSearchAccess.class}, hint = "${caseTitleMarkdown}" ) ALL_FINAL_ORDERS_ISSUED, @CCD( label = "Case Stayed", - access = {CaseworkerReadAccess.class, ClaimantAccess.class}, + access = {CaseworkerReadAccess.class, ClaimantAccess.class, RasValidationAccess.class, GlobalSearchAccess.class}, hint = "${caseTitleMarkdown}" ) CASE_STAYED, @CCD( label = "Breathing Space", - access = {CaseworkerReadAccess.class, ClaimantAccess.class}, + access = {CaseworkerReadAccess.class, ClaimantAccess.class, RasValidationAccess.class, GlobalSearchAccess.class}, hint = "${caseTitleMarkdown}" ) BREATHING_SPACE diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/changecasestate/ChangeCaseState.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/changecasestate/ChangeCaseState.java index 951790ab80..ae6d94c2f8 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/changecasestate/ChangeCaseState.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/changecasestate/ChangeCaseState.java @@ -43,7 +43,6 @@ public void configureDecentralised(DecentralisedConfigBuilder Date: Fri, 3 Jul 2026 11:20:01 +0100 Subject: [PATCH 36/70] HDPI-6502:Fixing checkstyle issues --- .../hmcts/reform/pcs/ccd/domain/State.java | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/State.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/State.java index 405b6273e3..0e2a2ed6f5 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/State.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/State.java @@ -44,56 +44,64 @@ public enum State { @CCD( label = "Judicial Referral", - access = {CaseworkerReadAccess.class, ClaimantAccess.class, RasValidationAccess.class, GlobalSearchAccess.class}, + access = {CaseworkerReadAccess.class, ClaimantAccess.class, RasValidationAccess.class, + GlobalSearchAccess.class}, hint = "${caseTitleMarkdown}" ) JUDICIAL_REFERRAL, @CCD( label = "Hearing Readiness", - access = {CaseworkerReadAccess.class, ClaimantAccess.class, RasValidationAccess.class, GlobalSearchAccess.class}, + access = {CaseworkerReadAccess.class, ClaimantAccess.class, RasValidationAccess.class, + GlobalSearchAccess.class}, hint = "${caseTitleMarkdown}" ) HEARING_READINESS, @CCD( label = "Prepare For Hearing Conduct Hearing", - access = {CaseworkerReadAccess.class, ClaimantAccess.class, RasValidationAccess.class, GlobalSearchAccess.class}, + access = {CaseworkerReadAccess.class, ClaimantAccess.class, RasValidationAccess.class, + GlobalSearchAccess.class}, hint = "${caseTitleMarkdown}" ) PREPARE_FOR_HEARING_CONDUCT_HEARING, @CCD( label = "Decision Outcome", - access = {CaseworkerReadAccess.class, ClaimantAccess.class, RasValidationAccess.class, GlobalSearchAccess.class}, + access = {CaseworkerReadAccess.class, ClaimantAccess.class, RasValidationAccess.class, + GlobalSearchAccess.class}, hint = "${caseTitleMarkdown}" ) DECISION_OUTCOME, @CCD( label = "Case Progression", - access = {CaseworkerReadAccess.class, ClaimantAccess.class, RasValidationAccess.class, GlobalSearchAccess.class}, + access = {CaseworkerReadAccess.class, ClaimantAccess.class, RasValidationAccess.class, + GlobalSearchAccess.class}, hint = "${caseTitleMarkdown}" ) CASE_PROGRESSION, @CCD( label = "All Final Orders", - access = {CaseworkerReadAccess.class, ClaimantAccess.class, RasValidationAccess.class, GlobalSearchAccess.class}, + access = {CaseworkerReadAccess.class, ClaimantAccess.class, RasValidationAccess.class, + GlobalSearchAccess.class}, hint = "${caseTitleMarkdown}" ) ALL_FINAL_ORDERS_ISSUED, @CCD( label = "Case Stayed", - access = {CaseworkerReadAccess.class, ClaimantAccess.class, RasValidationAccess.class, GlobalSearchAccess.class}, + access = {CaseworkerReadAccess.class, ClaimantAccess.class, RasValidationAccess.class, + GlobalSearchAccess.class}, hint = "${caseTitleMarkdown}" ) CASE_STAYED, @CCD( label = "Breathing Space", - access = {CaseworkerReadAccess.class, ClaimantAccess.class, RasValidationAccess.class, GlobalSearchAccess.class}, + access = {CaseworkerReadAccess.class, ClaimantAccess.class, RasValidationAccess.class, + GlobalSearchAccess.class}, hint = "${caseTitleMarkdown}" ) BREATHING_SPACE From 139c6dde8841cc650a6d755253434d0c9c3be624 Mon Sep 17 00:00:00 2001 From: sadmanrahman Date: Fri, 3 Jul 2026 11:59:08 +0100 Subject: [PATCH 37/70] HDPI-7308: add not null constraint --- .../reform/pcs/ccd/service/DefendantAccessCodeService.java | 2 ++ .../V133__default_uncategorised_document_category.sql | 3 +++ .../reform/pcs/ccd/service/DefendantAccessCodeServiceTest.java | 3 ++- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/DefendantAccessCodeService.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/DefendantAccessCodeService.java index c01f7eb17e..5ac1884004 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/DefendantAccessCodeService.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/DefendantAccessCodeService.java @@ -4,6 +4,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import uk.gov.hmcts.reform.pcs.ccd.domain.CaseFileCategory; import uk.gov.hmcts.reform.pcs.ccd.domain.DocumentType; import uk.gov.hmcts.reform.pcs.ccd.domain.claimactivitylog.ClaimActivityType; import uk.gov.hmcts.reform.pcs.ccd.entity.ClaimEntity; @@ -84,6 +85,7 @@ public void generateForDefendant(long caseReference, UUID defendantPartyId, bool .party(defendant) .url(documentUrl) .type(DocumentType.DEFENDANT_ACCESS_CODE) + .categoryId(CaseFileCategory.UNCATEGORISED_DOCUMENTS.getId()) .build() ); diff --git a/src/main/resources/db/migration/V133__default_uncategorised_document_category.sql b/src/main/resources/db/migration/V133__default_uncategorised_document_category.sql index 313d680ff8..496ee14494 100644 --- a/src/main/resources/db/migration/V133__default_uncategorised_document_category.sql +++ b/src/main/resources/db/migration/V133__default_uncategorised_document_category.sql @@ -4,3 +4,6 @@ WHERE category_id IS NULL; ALTER TABLE document ALTER COLUMN category_id SET DEFAULT 'uncategorisedDocuments'; + +ALTER TABLE document +ALTER COLUMN category_id SET NOT NULL; diff --git a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/DefendantAccessCodeServiceTest.java b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/DefendantAccessCodeServiceTest.java index 3117895757..73458adb9f 100644 --- a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/DefendantAccessCodeServiceTest.java +++ b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/DefendantAccessCodeServiceTest.java @@ -7,6 +7,7 @@ import org.mockito.Captor; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import uk.gov.hmcts.reform.pcs.ccd.domain.CaseFileCategory; import uk.gov.hmcts.reform.pcs.ccd.domain.DocumentType; import uk.gov.hmcts.reform.pcs.ccd.domain.claimactivitylog.ClaimActivityType; import uk.gov.hmcts.reform.pcs.ccd.entity.ClaimEntity; @@ -98,7 +99,7 @@ void generateForDefendant_savesDocumentEncryptedCodePinAndLogsSuccess() { verify(documentRepository).save(documentCaptor.capture()); DocumentEntity savedDoc = documentCaptor.getValue(); assertThat(savedDoc.getType()).isEqualTo(DocumentType.DEFENDANT_ACCESS_CODE); - assertThat(savedDoc.getCategoryId()).isNull(); + assertThat(savedDoc.getCategoryId()).isEqualTo(CaseFileCategory.UNCATEGORISED_DOCUMENTS.getId()); assertThat(savedDoc.getUrl()).isEqualTo(DOC_URL); assertThat(savedDoc.getParty().getId()).isEqualTo(partyId); assertThat(savedDoc.getPcsCase()).isEqualTo(caseEntity); From fa0a8a2edd8b4a585809bcacd1ce027f910c39a8 Mon Sep 17 00:00:00 2001 From: Liban Abdirahman Date: Fri, 3 Jul 2026 12:27:33 +0100 Subject: [PATCH 38/70] HDPI-6502:Minor refactoring --- src/main/java/uk/gov/hmcts/reform/pcs/ccd/CaseType.java | 6 ++---- .../hmcts/reform/pcs/ccd/accesscontrol/AccessGrants.java | 7 ++----- .../hmcts/reform/pcs/ccd/accesscontrol/AccessProfile.java | 1 - .../reform/pcs/ccd/accesscontrol/CaseworkerRoles.java | 1 - .../gov/hmcts/reform/pcs/ccd/accesscontrol/UserRole.java | 1 - .../reform/pcs/ccd/accesscontrol/CaseworkerRolesTest.java | 2 -- 6 files changed, 4 insertions(+), 14 deletions(-) diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/CaseType.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/CaseType.java index 002d9ed400..077dd4c12b 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/CaseType.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/CaseType.java @@ -40,8 +40,7 @@ public class CaseType implements CCDConfig { AccessProfile.LEADERSHIP_JUDGE, AccessProfile.HEARING_CENTRE_ADMIN, AccessProfile.CTSC_ADMIN, - AccessProfile.WLU_ADMIN, - AccessProfile.BAILIFF_ADMIN + AccessProfile.WLU_ADMIN }; static final AccessProfile[] INTERNAL_TAB_ROLES = { AccessProfile.JUDGE, @@ -50,8 +49,7 @@ public class CaseType implements CCDConfig { AccessProfile.LEADERSHIP_JUDGE, AccessProfile.HEARING_CENTRE_ADMIN, AccessProfile.CTSC_ADMIN, - AccessProfile.WLU_ADMIN, - AccessProfile.BAILIFF_ADMIN + AccessProfile.WLU_ADMIN }; static final AccessProfile[] NON_INTERNAL_HISTORY_ROLES = nonInternalHistoryRoles(); diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/AccessGrants.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/AccessGrants.java index e797f44552..33882d4cfb 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/AccessGrants.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/AccessGrants.java @@ -5,7 +5,6 @@ import uk.gov.hmcts.ccd.sdk.api.HasRole; import uk.gov.hmcts.ccd.sdk.api.Permission; -import static uk.gov.hmcts.reform.pcs.ccd.accesscontrol.UserRole.BAILIFF_ADMIN; import static uk.gov.hmcts.reform.pcs.ccd.accesscontrol.UserRole.CIRCUIT_JUDGE; import static uk.gov.hmcts.reform.pcs.ccd.accesscontrol.UserRole.CITIZEN; import static uk.gov.hmcts.reform.pcs.ccd.accesscontrol.UserRole.CLAIMANT_SOLICITOR; @@ -33,8 +32,7 @@ final class AccessGrants { LEADERSHIP_JUDGE, HEARING_CENTRE_ADMIN, CTSC_ADMIN, - WLU_ADMIN, - BAILIFF_ADMIN + WLU_ADMIN }; static final UserRole[] INTERNAL_READ_ROLES = { @@ -44,8 +42,7 @@ final class AccessGrants { LEADERSHIP_JUDGE, HEARING_CENTRE_ADMIN, CTSC_ADMIN, - WLU_ADMIN, - BAILIFF_ADMIN + WLU_ADMIN }; private AccessGrants() { diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/AccessProfile.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/AccessProfile.java index ca596cca0a..6a46e19192 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/AccessProfile.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/AccessProfile.java @@ -27,7 +27,6 @@ public enum AccessProfile implements HasRole { FEE_PAID_JUDGE("fee-paid-judge", CRU), CIRCUIT_JUDGE("circuit-judge", CRU), LEADERSHIP_JUDGE("leadership-judge", CRU), - BAILIFF_ADMIN("bailiff-admin", CRU), CTSC_TEAM_LEADER("ctsc-team-leader", Permission.CRU), CTSC_ADMIN("ctsc", Permission.CRU), HEARING_CENTRE_TEAM_LEADER("hearing-centre-team-leader", Permission.CRU), diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/CaseworkerRoles.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/CaseworkerRoles.java index 7ac2005148..fbf4903d87 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/CaseworkerRoles.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/CaseworkerRoles.java @@ -7,7 +7,6 @@ public final class CaseworkerRoles { UserRole.HEARING_CENTRE_ADMIN, UserRole.CTSC_TEAM_LEADER, UserRole.CTSC_ADMIN, - UserRole.BAILIFF_ADMIN, UserRole.WLU_TEAM_LEADER, UserRole.WLU_ADMIN }; diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/UserRole.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/UserRole.java index 39ada7d410..d2220d1733 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/UserRole.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/UserRole.java @@ -45,7 +45,6 @@ public enum UserRole implements HasRole { LEADERSHIP_JUDGE("leadership-judge", Set.of(R), RAS), CIRCUIT_JUDGE("circuit-judge", Set.of(R), RAS), JUDGE("judge", Set.of(R), RAS), - BAILIFF_ADMIN("bailiff-admin", Permission.CRU, RAS), SYSTEM_USER("pcs-system-update", Permission.CRU, IDAM); diff --git a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/CaseworkerRolesTest.java b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/CaseworkerRolesTest.java index 3f5bfc2475..0c29c0d95a 100644 --- a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/CaseworkerRolesTest.java +++ b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/CaseworkerRolesTest.java @@ -4,7 +4,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static uk.gov.hmcts.reform.pcs.ccd.accesscontrol.CaseworkerRoles.CASEWORKER_ROLES; -import static uk.gov.hmcts.reform.pcs.ccd.accesscontrol.UserRole.BAILIFF_ADMIN; import static uk.gov.hmcts.reform.pcs.ccd.accesscontrol.UserRole.CTSC_ADMIN; import static uk.gov.hmcts.reform.pcs.ccd.accesscontrol.UserRole.CTSC_TEAM_LEADER; import static uk.gov.hmcts.reform.pcs.ccd.accesscontrol.UserRole.HEARING_CENTRE_ADMIN; @@ -21,7 +20,6 @@ void shouldContainAllCaseworkerRasRoles() { HEARING_CENTRE_ADMIN, CTSC_TEAM_LEADER, CTSC_ADMIN, - BAILIFF_ADMIN, WLU_TEAM_LEADER, WLU_ADMIN ); From f0ef5bd5f67f1f43c01788b755c20f1c59c14fae Mon Sep 17 00:00:00 2001 From: Liban Abdirahman Date: Fri, 3 Jul 2026 16:48:19 +0100 Subject: [PATCH 39/70] HDPI-6502:Actioning review comments --- .../pcs/ccd/accesscontrol/AccessProfile.java | 2 +- .../pcs/ccd/domain/CaseStateOptionTest.java | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 src/test/java/uk/gov/hmcts/reform/pcs/ccd/domain/CaseStateOptionTest.java diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/AccessProfile.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/AccessProfile.java index 6a46e19192..e0f01ac691 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/AccessProfile.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/AccessProfile.java @@ -20,7 +20,7 @@ public enum AccessProfile implements HasRole { DEFENDANT("[DEFENDANT]", CRU), CLAIMANT_SOLICITOR("[CLAIMANTSOLICITOR]", CRU), DEFENDANT_SOLICITOR("[DEFENDANTSOLICITOR]", CRU), - PCS_CASE_WORKER("caseworker-pcs", CRU), + PCS_CASE_WORKER("caseworker-pcs", Set.of(R)), PCS_SOLICITOR("caseworker-pcs-solicitor", CRU), JUDGE("judge", CRU), diff --git a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/domain/CaseStateOptionTest.java b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/domain/CaseStateOptionTest.java new file mode 100644 index 0000000000..1475f6e163 --- /dev/null +++ b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/domain/CaseStateOptionTest.java @@ -0,0 +1,16 @@ +package uk.gov.hmcts.reform.pcs.ccd.domain; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; + +import static org.assertj.core.api.Assertions.assertThatCode; + +class CaseStateOptionTest { + + @ParameterizedTest + @EnumSource(CaseStateOption.class) + void shouldConvertToMatchingStateWithoutThrowing(CaseStateOption caseStateOption) { + assertThatCode(caseStateOption::toState).doesNotThrowAnyException(); + } + +} \ No newline at end of file From 5e9b2834affab2354dad6931861a5dfc6c8ec0a5 Mon Sep 17 00:00:00 2001 From: sadmanrahman Date: Mon, 6 Jul 2026 14:49:25 +0100 Subject: [PATCH 40/70] HDPI-6835: fix build --- ..._app_case_level_rank.sql => V133__gen_app_case_level_rank.sql} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/main/resources/db/migration/{V131__gen_app_case_level_rank.sql => V133__gen_app_case_level_rank.sql} (100%) diff --git a/src/main/resources/db/migration/V131__gen_app_case_level_rank.sql b/src/main/resources/db/migration/V133__gen_app_case_level_rank.sql similarity index 100% rename from src/main/resources/db/migration/V131__gen_app_case_level_rank.sql rename to src/main/resources/db/migration/V133__gen_app_case_level_rank.sql From 4b82dcda2518bfe7bc096af455a8d61b8ba2e640 Mon Sep 17 00:00:00 2001 From: Liban Abdirahman Date: Mon, 6 Jul 2026 17:28:56 +0100 Subject: [PATCH 41/70] HDPI-6502:Fixing changeCaseState event access --- .../reform/pcs/ccd/event/changecasestate/ChangeCaseState.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/changecasestate/ChangeCaseState.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/changecasestate/ChangeCaseState.java index ae6d94c2f8..3b1246a12c 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/changecasestate/ChangeCaseState.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/changecasestate/ChangeCaseState.java @@ -16,7 +16,6 @@ import uk.gov.hmcts.reform.pcs.ccd.util.AddressFormatter; import static uk.gov.hmcts.reform.pcs.ccd.accesscontrol.CaseworkerRoles.CASEWORKER_ROLES; -import static uk.gov.hmcts.reform.pcs.ccd.accesscontrol.JudicialHistoryRoles.JUDICIAL_HISTORY_ROLES; import static uk.gov.hmcts.reform.pcs.ccd.event.EventId.changeCaseState; import static uk.gov.hmcts.reform.pcs.ccd.util.AddressFormatter.COMMA_DELIMITER; @@ -43,7 +42,8 @@ public void configureDecentralised(DecentralisedConfigBuilder Date: Tue, 7 Jul 2026 14:07:24 +0100 Subject: [PATCH 42/70] HDPI-7308: fix UI --- .../documentamend/SelectDocumentPage.java | 22 ++++-------- .../DocumentAmendSelectionService.java | 2 ++ .../DocumentAmendSelectionServiceTest.java | 36 +++++++++++++++++++ 3 files changed, 44 insertions(+), 16 deletions(-) diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java index ff8f1c08d1..c15e9da9aa 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java @@ -17,7 +17,6 @@ import java.util.List; import static uk.gov.hmcts.reform.pcs.ccd.ShowConditions.NEVER_SHOW; -import static uk.gov.hmcts.reform.pcs.ccd.service.document.DocumentAmendSelectionService.SELECT_DIFFERENT_FOLDER_ERROR; @AllArgsConstructor @Component @@ -62,13 +61,9 @@ private void addCategoryFields(FieldCollectionBuilder midEvent(CaseDetails details, @@ -110,15 +105,10 @@ private String emptyFieldId(CaseFileCategory category) { }; } - private String noDocumentsMessage(CaseFileCategory category) { - return "No documents in '" + category.getLabel() + "'"; - } - - private String documentQuestion() { - return "Which document do you want to amend?"; + private String emptyFolderMessage(CaseFileCategory category) { + return "Which document do you want to amend?" + + "
" + + "No documents in '" + category.getLabel() + "'"; } - private String errorMessage(String message) { - return "

" + message + "

"; - } } diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionService.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionService.java index d79cdd874b..3cfbd8e8cc 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionService.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionService.java @@ -6,6 +6,7 @@ import uk.gov.hmcts.ccd.sdk.type.DynamicListElement; import uk.gov.hmcts.ccd.sdk.type.YesOrNo; import uk.gov.hmcts.reform.pcs.ccd.domain.CaseFileCategory; +import uk.gov.hmcts.reform.pcs.ccd.domain.DocumentType; import uk.gov.hmcts.reform.pcs.ccd.domain.PCSCase; import uk.gov.hmcts.reform.pcs.ccd.domain.documentamend.DocumentAmendDetails; import uk.gov.hmcts.reform.pcs.ccd.entity.DocumentEntity; @@ -91,6 +92,7 @@ private DynamicList documentList(PcsCaseEntity pcsCase, CaseFileCategory categor : pcsCase.getDocuments().stream() .filter(Objects::nonNull) .filter(document -> isInCategory(document, category)) + .filter(document -> document.getType() != DocumentType.DEFENDANT_ACCESS_CODE) .sorted(DOCUMENT_ORDER) .map(document -> DynamicListElement.builder() .code(document.getId()) diff --git a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java index 50b16bd77b..bd89aa8488 100644 --- a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java +++ b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java @@ -11,6 +11,7 @@ import uk.gov.hmcts.ccd.sdk.type.DynamicListElement; import uk.gov.hmcts.ccd.sdk.type.YesOrNo; import uk.gov.hmcts.reform.pcs.ccd.domain.CaseFileCategory; +import uk.gov.hmcts.reform.pcs.ccd.domain.DocumentType; import uk.gov.hmcts.reform.pcs.ccd.domain.PCSCase; import uk.gov.hmcts.reform.pcs.ccd.domain.VerticalYesNo; import uk.gov.hmcts.reform.pcs.ccd.domain.documentamend.DocumentAmendDetails; @@ -154,6 +155,31 @@ void shouldExcludeDocumentsWithNullCategoryIdFromUncategorisedDocuments() { assertThat(caseData.getDocumentAmendDetails().getUncategorisedDocumentsEmpty()).isEqualTo(YesOrNo.NO); } + @Test + void shouldExcludeDefendantAccessCodeDocumentsFromUncategorisedDocuments() { + DocumentEntity accessCodeDocument = documentWithType( + null, + UNCATEGORISED_DOCUMENTS.getId(), + DocumentType.DEFENDANT_ACCESS_CODE + ); + DocumentEntity visibleDocument = documentWithType( + "uncategorised document.pdf", + UNCATEGORISED_DOCUMENTS.getId(), + DocumentType.OTHER + ); + when(pcsCaseService.loadCase(CASE_REFERENCE)).thenReturn(PcsCaseEntity.builder() + .documents(List.of(accessCodeDocument, visibleDocument)) + .build()); + PCSCase caseData = PCSCase.builder().build(); + + underTest.initialise(CASE_REFERENCE, caseData); + + assertThat(caseData.getDocumentAmendDetails().getUncategorisedDocuments().getListItems()) + .extracting(DynamicListElement::getLabel) + .containsExactly("uncategorised document.pdf"); + assertThat(caseData.getDocumentAmendDetails().getUncategorisedDocumentsEmpty()).isEqualTo(YesOrNo.NO); + } + @Test void shouldOrderDocumentsBySubmittedDateDescendingThenFileNameWithNullDatesLast() { DocumentEntity older = document( @@ -310,4 +336,14 @@ private static DocumentEntity document(String fileName, String categoryId, GenAp .submittedDate(submittedDate) .build(); } + + private static DocumentEntity documentWithType(String fileName, String categoryId, DocumentType type) { + return DocumentEntity.builder() + .id(UUID.randomUUID()) + .fileName(fileName) + .categoryId(categoryId) + .type(type) + .submittedDate(Instant.now()) + .build(); + } } From 8908d5b4f59cb10c0e741ce3801e192c4eceb540 Mon Sep 17 00:00:00 2001 From: srinijg Date: Tue, 7 Jul 2026 16:42:36 +0100 Subject: [PATCH 43/70] payload updated --- src/e2eTest/data/api-data/submitCase.api.data.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/e2eTest/data/api-data/submitCase.api.data.ts b/src/e2eTest/data/api-data/submitCase.api.data.ts index 6e3e50e483..7b31a240df 100644 --- a/src/e2eTest/data/api-data/submitCase.api.data.ts +++ b/src/e2eTest/data/api-data/submitCase.api.data.ts @@ -698,7 +698,7 @@ export const submitCaseApiData = { PostCode: null } }, - addAnotherDefendant: 'NO', + addAnotherDefendant: 'YES', additionalDefendants: [ { value: { From 674c3cc2031e74f118b3e76c672c4f5f277dcd7d Mon Sep 17 00:00:00 2001 From: sadmanrahman Date: Wed, 8 Jul 2026 09:47:51 +0100 Subject: [PATCH 44/70] HDPI-6835: fix docs not showing --- .../reform/pcs/ccd/view/DocumentsView.java | 4 +++ .../pcs/ccd/view/DocumentsViewTest.java | 27 +++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/view/DocumentsView.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/view/DocumentsView.java index 3a0ffd2307..fb639dcf16 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/view/DocumentsView.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/view/DocumentsView.java @@ -86,6 +86,10 @@ public static boolean isDescriptionEmpty(DocumentEntity documentEntity) { } private boolean isNotInCaseDetailsTab(DocumentEntity documentEntity) { + if (documentEntity.getGeneralApplication() != null) { + return true; + } + List caseDetailsDocuments = List.of( DocumentType.TENANCY_AGREEMENT, DocumentType.POSSESSION_NOTICE, diff --git a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/view/DocumentsViewTest.java b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/view/DocumentsViewTest.java index eaf64dcf94..1511bf79dc 100644 --- a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/view/DocumentsViewTest.java +++ b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/view/DocumentsViewTest.java @@ -308,6 +308,33 @@ void shouldNotFilterOutDocumentsThatHaveADescription(DocumentType documentType) assertThat(allDocuments.getFirst().getValue().getFilename()).isEqualTo("filename"); } + @ParameterizedTest + @MethodSource("caseDetailsTabDocuments") + void shouldNotFilterOutGenAppDocumentsThatAppearInCaseDetailsTab(DocumentType documentType) { + // Given + GenAppEntity genAppEntity = mock(GenAppEntity.class); + UUID document1Id = UUID.randomUUID(); + DocumentEntity documentEntity = DocumentEntity.builder() + .id(document1Id) + .fileName("genApps GA1 - Defendant 2.docx") + .type(documentType) + .generalApplication(genAppEntity) + .build(); + + when(securityContextService.getCurrentUserId()).thenReturn(CURRENT_USER_ID); + when(genAppVisibilityService.isGenAppVisibleToUser(genAppEntity, CURRENT_USER_ID)) + .thenReturn(true); + when(pcsCaseEntity.getDocuments()).thenReturn(List.of(documentEntity)); + + // When + underTest.setCaseFields(pcsCase, pcsCaseEntity); + + // Then + List> allDocuments = pcsCase.getAllDocuments(); + assertThat(allDocuments).hasSize(1); + assertThat(allDocuments.getFirst().getValue().getFilename()).isEqualTo("genApps GA1 - Defendant 2.docx"); + } + @ParameterizedTest @MethodSource("nonCaseDetailsTabDocuments") void shouldNotFilterOutDocumentsThatDoNotAppearInCaseDetailsTab(DocumentType documentType) { From 8f649a3dc9ba29132e8e40c05d9f3593d88dd103 Mon Sep 17 00:00:00 2001 From: srinijg Date: Wed, 8 Jul 2026 15:47:42 +0100 Subject: [PATCH 45/70] new tests added --- src/e2eTest/data/api-data/index.ts | 1 + src/e2eTest/data/api-data/payment.api.data.ts | 31 ++++ .../data/page-data/caseSummary.page.data.ts | 5 +- .../data/user-data/permanent.user.data.ts | 4 + .../caseManagement.manageDocuments.spec.ts | 61 ++++++ .../custom-actions/createCaseAPI.action.ts | 44 ++++- .../caseManagement.action.ts | 52 ++++++ .../custom-actions-caseManagement/index.ts | 1 + .../utils/controller-caseManagement.ts | 173 ++++++++++++++++++ src/e2eTest/utils/registry/action.registry.ts | 1 + .../action-caseManagement.registry.ts | 53 ++++++ 11 files changed, 424 insertions(+), 2 deletions(-) create mode 100644 src/e2eTest/data/api-data/payment.api.data.ts create mode 100644 src/e2eTest/tests/test-caseManagement/caseManagement.manageDocuments.spec.ts create mode 100644 src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagement.action.ts create mode 100644 src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/index.ts create mode 100644 src/e2eTest/utils/controller-caseManagement.ts create mode 100644 src/e2eTest/utils/registry/registry-caseManagement/action-caseManagement.registry.ts diff --git a/src/e2eTest/data/api-data/index.ts b/src/e2eTest/data/api-data/index.ts index d685620812..ae97987537 100644 --- a/src/e2eTest/data/api-data/index.ts +++ b/src/e2eTest/data/api-data/index.ts @@ -11,3 +11,4 @@ export * from '@data/api-data/submitCaseEventTokenDynamic.api.data'; export * from '@data/api-data/backDateTheCasePayment.api.data'; export * from '@data/api-data/makeAnApplication.api.data'; export * from '@data/api-data/makeAnApplicationEventToken.api.data'; +export * from '@data/api-data/payment.api.data'; diff --git a/src/e2eTest/data/api-data/payment.api.data.ts b/src/e2eTest/data/api-data/payment.api.data.ts new file mode 100644 index 0000000000..c08fdc166a --- /dev/null +++ b/src/e2eTest/data/api-data/payment.api.data.ts @@ -0,0 +1,31 @@ +import { AxiosRequestConfig } from 'axios'; + +export const paymentApiData = { + paymentApiInstance: (): AxiosRequestConfig => ({ + baseURL: process.env.PCS_API_URL, + headers: { + ServiceAuthorization: `Bearer ${process.env.SERVICE_AUTH_TOKEN}`, + 'Content-Type': 'application/json', + Accept: '*/*', + experimental: 'experimental', + }, + }), + + getFeePaymentInfoApiEndPoint: (): string => `/testing-support/fee-payment-info/${process.env.CASE_NUMBER}`, + + updatePaymentApiEndPoint: '/payment-update', + + paymentUpdatePayload: (requestReference: string) => ({ + service_request_reference: requestReference, + ccd_case_number: process.env.CASE_NUMBER, + service_request_amount: 41500, + service_request_status: 'Paid', + payments: { + payment_amount: 2500, + payment_reference: 'RC-1780-3235-2218-3722', + payment_method: 'payment by account', + case_reference: '098DC868', + account_number: 'PBA0084541', + }, + }), +}; diff --git a/src/e2eTest/data/page-data/caseSummary.page.data.ts b/src/e2eTest/data/page-data/caseSummary.page.data.ts index 16a3c47d19..3ebffafb43 100644 --- a/src/e2eTest/data/page-data/caseSummary.page.data.ts +++ b/src/e2eTest/data/page-data/caseSummary.page.data.ts @@ -12,5 +12,8 @@ export const caseSummary = { addCaseNote: 'Add a case note', go: "Go", HistoryTab: 'History', - serviceRequestTab: 'Service Request' + serviceRequestTab: 'Service Request', + manageDocuments:{ + amend : 'Manage documents: Amend' + } } diff --git a/src/e2eTest/data/user-data/permanent.user.data.ts b/src/e2eTest/data/user-data/permanent.user.data.ts index c8aa5cbaed..0cca4aafec 100644 --- a/src/e2eTest/data/user-data/permanent.user.data.ts +++ b/src/e2eTest/data/user-data/permanent.user.data.ts @@ -11,5 +11,9 @@ export const user = { caseworker: { email: 'pcs-caseworker@test.com', password: process.env.IDAM_PCS_USER_PASSWORD + }, + staffAdmin: { + email: 'pcs-ctsc-admin-01@justice.gov.uk', + password: process.env.IDAM_PCS_USER_PASSWORD } }; diff --git a/src/e2eTest/tests/test-caseManagement/caseManagement.manageDocuments.spec.ts b/src/e2eTest/tests/test-caseManagement/caseManagement.manageDocuments.spec.ts new file mode 100644 index 0000000000..232f9e37ab --- /dev/null +++ b/src/e2eTest/tests/test-caseManagement/caseManagement.manageDocuments.spec.ts @@ -0,0 +1,61 @@ +import { createCaseApiData, makeAnApplicationApiData, submitCaseApiData } from '@data/api-data'; +import { initializeExecutor, performValidation } from '@utils/controller'; +import test, { expect } from '@playwright/test'; +import { caseInfo, defendantUserDetails } from '@utils/actions/custom-actions'; +import { PageContentValidation } from '@utils/validations/element-validations/pageContent.validation'; +import { caseSummary, home, user } from '@data/page-data'; +import { dismissCookieBanner } from '@config/cookie-banner'; +import { initializeCMExecutor, performAction } from '@utils/controller-caseManagement'; +import { getCaseTypeId } from '@utils/common/caseType.utils'; +import { VERY_LONG_TIMEOUT } from 'playwright.config'; + +test.use({ storageState: undefined }) + +test.beforeEach(async ({ page, context }) => { + await context.clearCookies(); + initializeExecutor(page); + initializeCMExecutor(page); + await performAction('createCaseAPI', { data: createCaseApiData.createCasePayload }); + await performAction('submitCaseAPI', { data: submitCaseApiData.submitCasePayloadCaseFileView }); + await performAction('updatePaymentAPI'); + await performAction('getCaseAPI', 'Link Solicitor'); + + for (const defendant of defendantUserDetails) { + await performAction('makeAnApplicationAPI', { + data: makeAnApplicationApiData.makeAnApplicationAdjournPayload( + defendant.id, + defendant.name + ), + }); + }; + await performAction('navigateToUrl', process.env.MANAGE_CASE_BASE_URL); + await dismissCookieBanner(page, 'additional'); + await performAction('login', user.staffAdmin); + await dismissCookieBanner(page, 'analytics'); + await performAction('navigateToSummaryPage'); + // await performAction('navigateToUrl', `${process.env.MANAGE_CASE_BASE_URL}/cases/case-details/PCS/${getCaseTypeId()}/${process.env.CASE_NUMBER}#Summary`); + // await expect(async () => { + // await page.waitForURL(`${process.env.MANAGE_CASE_BASE_URL}/cases/case-details/PCS/${getCaseTypeId()}/${process.env.CASE_NUMBER}#Summary`, { waitUntil: 'domcontentloaded' }); + // }).toPass({ + // timeout: VERY_LONG_TIMEOUT, + // }); + // await page.waitForLoadState(); + // await page.locator('.spinner-container').waitFor({ state: 'detached' }); + // await performValidation('mainHeader', home.caseSummary); + + +}); + +test.afterEach(async () => { + if (caseInfo.id) { + await performAction('deleteCaseRole', '[CLAIMANTSOLICITOR]'); + } + PageContentValidation.finaliseTest(); + +}); + +test.describe('Case management - Manage documents e2e Journey @nightly', async () => { + test('Case management - Manage documents - Amend @CM @regression', async () => { + await performAction('selectAnEvent', { eventType: caseSummary.manageDocuments.amend }); + }); +}); diff --git a/src/e2eTest/utils/actions/custom-actions/createCaseAPI.action.ts b/src/e2eTest/utils/actions/custom-actions/createCaseAPI.action.ts index 1f74592408..d4e7435ba5 100644 --- a/src/e2eTest/utils/actions/custom-actions/createCaseAPI.action.ts +++ b/src/e2eTest/utils/actions/custom-actions/createCaseAPI.action.ts @@ -1,13 +1,14 @@ import Axios from 'axios'; import { actionData, actionRecord, IAction } from '@utils/interfaces'; import { Page } from '@playwright/test'; -import { createCaseApiData, createCaseEventTokenApiData, submitCaseApiData, submitCaseEventTokenApiData, caseUserRoleDeletionApiData, enforceOrderEventTokenApiData, enforceWarrantApiData, getCaseApiData, submitCaseEventTokenDynamicApiData, createCaseEventTokenDynamicApiData, makeAnApplicationEventTokenApiData, makeAnApplicationApiData } from '@data/api-data'; +import { createCaseApiData, createCaseEventTokenApiData, submitCaseApiData, submitCaseEventTokenApiData, caseUserRoleDeletionApiData, enforceOrderEventTokenApiData, enforceWarrantApiData, getCaseApiData, submitCaseEventTokenDynamicApiData, createCaseEventTokenDynamicApiData, makeAnApplicationEventTokenApiData, makeAnApplicationApiData, paymentApiData } from '@data/api-data'; import { user } from '@data/user-data'; import { caseNumber } from './createCase.action'; import { performAction } from '@utils/controller'; import { fetchCurrentUserTokenApiData } from '@data/api-data/fetchCurrentUser.api.data'; import { formatDateTimeBST } from '@utils/common/string.utils'; import { IdamUtils } from '@hmcts/playwright-common'; +import { actionRetries, VERY_SHORT_TIMEOUT } from 'playwright.config'; export let caseInfo: { id: string; fid: string; state: string } = { id: '', fid: '', state: '' }; @@ -26,6 +27,7 @@ export class CreateCaseAPIAction implements IAction { ['createCaseAPIDynamicUsers', () => this.createCaseAPIDynamicUsers(fieldName as actionRecord)], ['submitCaseAPIDynamicUsers', () => this.submitCaseAPIDynamicUsers(fieldName as actionRecord)], ['makeAnApplicationAPI', () => this.makeAnApplicationAPI(fieldName)], + ['updatePaymentAPI', () => this.updatePaymentAPI()], ]); const actionToPerform = actionsMap.get(action); if (!actionToPerform) throw new Error(`No action found for '${action}'`); @@ -45,6 +47,7 @@ export class CreateCaseAPIAction implements IAction { }); process.env.CASE_NUMBER = createResponse.data.id; caseInfo.id = createResponse.data.id; + console.log('id:'+caseInfo.id) caseInfo.fid = createResponse.data.id.replace(/(.{4})(?=.)/g, "$1-"); caseInfo.state = createResponse.data.state; } catch (error: any) { @@ -448,4 +451,43 @@ export class CreateCaseAPIAction implements IAction { throw new Error(`Make an application failed with status ${status}.Response received is ${responseBody?.message}}`); } } + + private async updatePaymentAPI(): Promise { + const paymentApi = Axios.create(paymentApiData.paymentApiInstance()); + const maxRetries = actionRetries; + const delayMs = VERY_SHORT_TIMEOUT; + for (let attempt = 1; attempt <= maxRetries; attempt++) { + try { + const response = await paymentApi.get(paymentApiData.getFeePaymentInfoApiEndPoint()); + console.log('payment info'+JSON.stringify(response)); + const paymentInfo = response.data; + console.log('payment info'+JSON.stringify(paymentInfo)); + if (!paymentInfo?.length) { + throw new Error('No payment information found.'); + } + const requestReference = paymentInfo[0].serviceRequestReference; + const updateResponse = await paymentApi.put( + paymentApiData.updatePaymentApiEndPoint, + paymentApiData.paymentUpdatePayload(requestReference) + ); + console.log(JSON.stringify(updateResponse)); + if (updateResponse.status === 200 || updateResponse.status === 204) { + return; + } + throw new Error(`Payment update failed with status ${updateResponse.status}`); + } catch (error: any) { + const status = error?.response?.status; + const responseBody = error?.response?.data; + if (attempt === maxRetries) { + if (Axios.isAxiosError(error)) { + throw new Error(`Payment API failed after retries: ${error.response?.status}`); + } + console.error("HTTP Status:", status); + throw new Error(`Payment API failed unexpectedly after retries.${error}`); + } + await new Promise(res => setTimeout(res, delayMs)); + } + } + throw new Error('Payment API failed after multiple retries'); + } } diff --git a/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagement.action.ts b/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagement.action.ts new file mode 100644 index 0000000000..6084efec5a --- /dev/null +++ b/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagement.action.ts @@ -0,0 +1,52 @@ + +import { expect, Page } from '@playwright/test'; +import { IAction, actionData, actionRecord } from '@utils/interfaces'; +import { createCaseApiData } from '@data/api-data'; +import { getCaseTypeId } from '@utils/common/caseType.utils'; +import { performAction, performValidation } from '@utils/controller-caseManagement'; +import { VERY_LONG_TIMEOUT } from 'playwright.config'; +import { caseSummary, home } from '@data/page-data'; + + +export const addressInfo = { + buildingStreet: createCaseApiData.createCasePayload.propertyAddress.AddressLine1, + addressLine2: createCaseApiData.createCasePayload.propertyAddress.AddressLine2, + townCity: createCaseApiData.createCasePayload.propertyAddress.PostTown, + engOrWalPostcode: createCaseApiData.createCasePayload.propertyAddress.PostCode +}; +const cyaMap = new Map(); +export let defendantDetails: string[] = []; + +export class CaseManagementAction implements IAction { + async execute(page: Page, action: string, fieldName: actionData | actionRecord): Promise { + const actionsMap = new Map Promise>([ + ['navigateToSummaryPage', () => this.navigateToSummaryPage(page)], + ['selectAnEvent', () => this.selectAnEvent(fieldName as actionRecord)], + + ]); + const actionToPerform = actionsMap.get(action); + if (!actionToPerform) { + throw new Error(`No action found for '${action}'`); + } + await actionToPerform(); + } + + private async navigateToSummaryPage(page: Page) { + console.log(process.env.CASE_NUMBER); + console.log(`${process.env.MANAGE_CASE_BASE_URL}/cases/case-details/PCS/${getCaseTypeId()}/${process.env.CASE_NUMBER}#Summary`) + await performAction('navigateToUrl', `${process.env.MANAGE_CASE_BASE_URL}/cases/case-details/PCS/${getCaseTypeId()}/${process.env.CASE_NUMBER}#Summary`); + await expect(async () => { + await page.waitForURL(`${process.env.MANAGE_CASE_BASE_URL}/cases/case-details/PCS/${getCaseTypeId()}/${process.env.CASE_NUMBER}#Summary`, { waitUntil: 'domcontentloaded' }); + }).toPass({ + timeout: VERY_LONG_TIMEOUT, + }); + await page.waitForLoadState(); + await page.locator('.spinner-container').waitFor({ state: 'detached' }); + await performValidation('mainHeader', home.caseSummary); + } + + private async selectAnEvent(event: actionRecord) { + await performAction('select', caseSummary.nextStepEventList, event.eventType); + await performAction('clickButton', caseSummary.go); + } +} diff --git a/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/index.ts b/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/index.ts new file mode 100644 index 0000000000..0973999dd0 --- /dev/null +++ b/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/index.ts @@ -0,0 +1 @@ +export * from './caseManagement.action'; diff --git a/src/e2eTest/utils/controller-caseManagement.ts b/src/e2eTest/utils/controller-caseManagement.ts new file mode 100644 index 0000000000..0a09f377b3 --- /dev/null +++ b/src/e2eTest/utils/controller-caseManagement.ts @@ -0,0 +1,173 @@ +import { Page, test } from '@playwright/test'; +import { actionData, actionRecord, actionTuple } from './interfaces/action.interface'; +import { validationData, validationRecord, validationTuple } from './interfaces/validation.interface'; +import { ValidationRegistry } from './registry/registry-enforcement/validation-enforcement.registry'; +import { AxeUtils } from "@hmcts/playwright-common"; +import { cyaStore } from '@utils/validations/custom-validations/CYA/cyaPage.validation'; +import { logToBrowser } from './test-logger'; +import { ActionCMRegistry } from './registry/registry-caseManagement/action-caseManagement.registry'; + +let testExecutor: { page: Page }; +let previousUrl: string = ''; +let captureDataForCYAPage = false; + +export function initializeCMExecutor(page: Page): void { + testExecutor = { page }; + previousUrl = page.url(); + captureDataForCYAPage = false; +} + +function getExecutor(): { page: Page } { + if (!testExecutor) { + throw new Error('Test executor not initialized. Call initializeExecutor(page) first.'); + } + return testExecutor; +} + +async function detectPageNavigation(): Promise { + const executor = getExecutor(); + const currentUrl = executor.page.url(); + + const pageNavigated = currentUrl !== previousUrl; + + if (pageNavigated) { + previousUrl = currentUrl; + } + + return pageNavigated; +} + +async function validatePageIfNavigated(action: string): Promise { + if (action.includes('click')) { + const pageNavigated = await detectPageNavigation(); + if (pageNavigated) { + const executor = getExecutor(); + const currentUrl = executor.page.url(); + + // Skip accessibility audit for login/auth pages + if (currentUrl.includes('/login') || currentUrl.includes('/sign-in') || + currentUrl.includes('idam') || currentUrl.includes('auth')) { + await performValidation('autoValidatePageContent'); + return; + } + + await performValidation('autoValidatePageContent'); + try { + await test.step("Running Accessibility Scan", async () => { + await new AxeUtils(executor.page).audit(); + }); + } catch (error) { + const errorMessage = String((error as Error).message || error).toLowerCase(); + if (errorMessage.includes('execution context was destroyed') || + errorMessage.includes('navigation')) { + console.warn(`Accessibility audit skipped due to navigation: ${errorMessage}`); + } else { + throw error; + } + } + } + } +} + +function captureDataForCYA(action: string, fieldName?: actionData | actionRecord, value?: actionData | actionRecord): void { + if (action === 'selectClaimantType') { + captureDataForCYAPage = true; + } + + if (captureDataForCYAPage && ['clickRadioButton', 'inputText', 'check', 'select', 'uploadFile'].includes(action)) { + cyaStore.captureAnswer(action, fieldName, value); + } +} + +export async function performAction(action: string, fieldName?: actionData | actionRecord, value?: actionData | actionRecord): Promise { + const executor = getExecutor(); + const actionInstance = ActionCMRegistry.getAction(action); + let displayFieldName = fieldName; + let displayValue = value ?? fieldName; + + if (typeof fieldName === 'string' && fieldName.toLowerCase() === 'password' && typeof value === 'string') { + displayValue = '*'.repeat(value.length); + } else if (typeof fieldName === 'object' && fieldName !== null && 'password' in fieldName) { + const obj = fieldName as Record; + displayValue = { ...obj, password: '*'.repeat(String(obj.password).length) }; + displayFieldName = displayValue; + } + let errorValidationRequired = false; + + if (action.includes('errorValidation') && fieldName === 'NO') { + errorValidationRequired = true; + } + + if (typeof displayFieldName === "object" && displayFieldName !== null) { + errorValidationRequired = ( + readValuesFromInputObjects(displayFieldName as actionRecord) + ).includes("validationReq: NO"); + } + + if (!errorValidationRequired) { + const stepText = `${action}${displayFieldName !== undefined ? ` - ${typeof displayFieldName === 'object' ? readValuesFromInputObjects(displayFieldName) : displayFieldName}` : ''}${displayValue !== undefined ? ` with value '${typeof displayValue === 'object' ? readValuesFromInputObjects(displayValue) : displayValue}'` : ''}`; + await test.step(stepText, async () => { + await actionInstance.execute(executor.page, action, fieldName, value); + await logToBrowser(executor.page, stepText); + }); + await validatePageIfNavigated(action); + } +} + +export async function performValidation(validation: string, inputFieldName?: validationData | validationRecord, inputData?: validationData | validationRecord): Promise { + const executor = getExecutor(); + let fieldName: any; + let data: any; + if (typeof inputFieldName === 'object' && inputFieldName !== null && !Array.isArray(inputFieldName) && inputData !== null && typeof inputData === 'object') { + [fieldName, data] = [inputFieldName, inputData]; + } else if (typeof inputFieldName === 'string') { + [fieldName, data] = [inputFieldName, inputData]; + } else { + [fieldName, data] = ['', inputFieldName]; + } + const validationInstance = ValidationRegistry.getValidation(validation); + await test.step(`Validated ${validation}${fieldName ? ` - '${typeof fieldName === 'object' ? readValuesFromInputObjects(fieldName) : fieldName}'` : ''}${data !== undefined ? ` with value '${typeof data === 'object' ? readValuesFromInputObjects(data) : data}'` : ''}`, async () => { + await validationInstance.validate(executor.page, validation, fieldName, data); + }); +} + +export async function performActions(groupName: string, ...actions: actionTuple[]): Promise { + getExecutor(); + await test.step(`Performed action group: ${groupName}`, async () => { + for (const action of actions) { + const [actionName, fieldName, value] = action; + await performAction(actionName, fieldName, value); + } + }); +} + +export async function performValidations(groupName: string, ...validations: validationTuple[]): Promise { + getExecutor(); + await test.step(`Performed validation group: ${groupName}`, async () => { + for (const validation of validations) { + const [validationType, fieldName, data] = validation; + await performValidation(validationType, fieldName, data); + } + }); +} + +function readValuesFromInputObjects(obj: object): string { + const keys = Object.keys(obj); + const formattedPairs = keys.map(key => { + const value = (obj as actionRecord)[key]; + let valueString: string; + if (Array.isArray(value)) { + valueString = `[${value.map(item => + typeof item === 'object' + ? `{ ${readValuesFromInputObjects(item)} }` + : String(item) + ).join(', ')}]`; + } else if (typeof value === 'object' && value !== null) { + valueString = `{ ${readValuesFromInputObjects(value)} }`; + } else { + valueString = String(value); + } + return `${key}: ${valueString}`; + }); + return `${formattedPairs.join(', ')}`; +} diff --git a/src/e2eTest/utils/registry/action.registry.ts b/src/e2eTest/utils/registry/action.registry.ts index 7dade226ff..109b2c041b 100644 --- a/src/e2eTest/utils/registry/action.registry.ts +++ b/src/e2eTest/utils/registry/action.registry.ts @@ -58,6 +58,7 @@ export class ActionRegistry { ['createCaseAPIDynamicUsers', new CreateCaseAPIAction()], ['submitCaseAPIDynamicUsers', new CreateCaseAPIAction()], ['makeAnApplicationAPI', new CreateCaseAPIAction()], + ['updatePaymentAPI', new CreateCaseAPIAction()], ['selectClaimType', new CreateCaseAction()], ['selectClaimantName', new CreateCaseAction()], ['selectClaimantDetails', new CreateCaseWalesAction()], diff --git a/src/e2eTest/utils/registry/registry-caseManagement/action-caseManagement.registry.ts b/src/e2eTest/utils/registry/registry-caseManagement/action-caseManagement.registry.ts new file mode 100644 index 0000000000..c0ed096d4a --- /dev/null +++ b/src/e2eTest/utils/registry/registry-caseManagement/action-caseManagement.registry.ts @@ -0,0 +1,53 @@ +import { LoginAction, NavigateToUrlAction, CreateCaseAPIAction } from "@utils/actions/custom-actions"; +import { CaseManagementAction } from "@utils/actions/custom-actions/custom-actions-caseManagement"; +import { RecordAnswers } from "@utils/actions/custom-actions/custom-actions-genApps/recordAnsweredFields.action"; +import { LinkSolicitorAPIAction } from "@utils/actions/custom-actions/linkSolicitorAPI.action"; +import { CheckAction, ClickButtonAction, ClickRadioButtonAction, ClickTabAction, InputTextAction, SelectAction, UploadFileAction } from "@utils/actions/element-actions"; +import { ClickLinkAction } from "@utils/actions/element-actions/clickLink.action"; +import { ClickSummaryAction } from "@utils/actions/element-actions/clickSummary.action"; +import { IAction } from "@utils/interfaces"; + + +export class ActionCMRegistry { + private static actions: Map = new Map([ + ['check', new CheckAction()], + ['uncheck', new CheckAction()], + ['clickButton', new ClickButtonAction()], + ['clickSummary', new ClickSummaryAction()], + ['clickLink', new ClickLinkAction()], + ['clickLinkAndVerifyNewTabTitle', new ClickLinkAction()], + ['clickLinkAndVerifySameTabTitle', new ClickLinkAction()], + ['clickRadioButton', new ClickRadioButtonAction()], + ['clickTab', new ClickTabAction()], + ['inputText', new InputTextAction()], + ['select', new SelectAction()], + ['uploadFile', new UploadFileAction()], + ['login', new LoginAction()], + ['createUser', new LoginAction()], + ['navigateToUrl', new NavigateToUrlAction()], + ['createCaseAPI', new CreateCaseAPIAction()], + ['submitCaseAPI', new CreateCaseAPIAction()], + ['deleteCaseRole', new CreateCaseAPIAction()], + ['getCaseAPI', new CreateCaseAPIAction()], + ['updatePaymentAPI', new CreateCaseAPIAction()], + ['linkSolicitorAPI', new LinkSolicitorAPIAction()], + ['makeAnApplicationAPI', new CreateCaseAPIAction()], + ['navigateToSummaryPage', new CaseManagementAction()], + ['selectAnEvent', new CaseManagementAction()], + + ]); + + static getAction(actionName: string): IAction { + const action = this.actions.get(actionName); + if (!action) { + throw new Error( + `Action '${actionName}' is not registered. Available actions: ${Array.from(this.actions.keys()).join(', ')}` + ); + } + return action; + } + + static getAvailableActions(): string[] { + return Array.from(this.actions.keys()); + } +} From 70fcc6ae3dc28a181c9e2cfd9b82b60fd2ff1c57 Mon Sep 17 00:00:00 2001 From: srinijg Date: Mon, 13 Jul 2026 10:36:28 +0100 Subject: [PATCH 46/70] error validations added --- src/e2eTest/data/api-data/payment.api.data.ts | 2 +- .../page-data-caseManagement-figma/index.ts | 1 + .../selectDocument.page.data.ts | 19 +++++++ .../urlToFileMappingCM.ts | 3 ++ .../caseManagement.manageDocuments.spec.ts | 15 ++---- .../custom-actions/createCaseAPI.action.ts | 8 +-- .../caseManagement.action.ts | 50 +++++++++++++++++++ .../caseManagementErrorValidation.action.ts | 29 +++++++++++ .../action-caseManagement.registry.ts | 3 ++ 9 files changed, 114 insertions(+), 16 deletions(-) create mode 100644 src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/index.ts create mode 100644 src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/selectDocument.page.data.ts create mode 100644 src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/urlToFileMappingCM.ts create mode 100644 src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagementErrorValidation.action.ts diff --git a/src/e2eTest/data/api-data/payment.api.data.ts b/src/e2eTest/data/api-data/payment.api.data.ts index c08fdc166a..f15ff99b94 100644 --- a/src/e2eTest/data/api-data/payment.api.data.ts +++ b/src/e2eTest/data/api-data/payment.api.data.ts @@ -2,7 +2,7 @@ import { AxiosRequestConfig } from 'axios'; export const paymentApiData = { paymentApiInstance: (): AxiosRequestConfig => ({ - baseURL: process.env.PCS_API_URL, + baseURL: process.env.CASE_API_URL, headers: { ServiceAuthorization: `Bearer ${process.env.SERVICE_AUTH_TOKEN}`, 'Content-Type': 'application/json', diff --git a/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/index.ts b/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/index.ts new file mode 100644 index 0000000000..489440a729 --- /dev/null +++ b/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/index.ts @@ -0,0 +1 @@ +export * from './selectDocument.page.data'; diff --git a/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/selectDocument.page.data.ts b/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/selectDocument.page.data.ts new file mode 100644 index 0000000000..85b707d556 --- /dev/null +++ b/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/selectDocument.page.data.ts @@ -0,0 +1,19 @@ +export const selectDocument = { + mainHeader: `Select document`, + whichFolderQuestion: `Which folder is the document in?`, + documentToAmendHiddenQuestion: `Which document do you want to amend?`, + docFolder: `Property documents`, + continueButton: `Continue`, + previousButton: `Previous`, + cancelLink: `Cancel`, + errorValidation: `NO`,//set it to `NO` before raising a PR + errorValidationType: { one: `textField`, two: `radioOptions`, three: `checkBox`, four: `dropDown` }, + errorValidationField: { + errorDropDown: [ + { type: 'none', input: '', errMessage: 'Type of document is required' }, + ], + errorRadioOption: [ + { type: 'none', input: '', errMessage: 'Field is required' } + ] + }, +}; diff --git a/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/urlToFileMappingCM.ts b/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/urlToFileMappingCM.ts new file mode 100644 index 0000000000..7032021a9a --- /dev/null +++ b/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/urlToFileMappingCM.ts @@ -0,0 +1,3 @@ +export default { + 'amendDocumentsselectDocument': 'selectDocument', +}; diff --git a/src/e2eTest/tests/test-caseManagement/caseManagement.manageDocuments.spec.ts b/src/e2eTest/tests/test-caseManagement/caseManagement.manageDocuments.spec.ts index 232f9e37ab..d84bc7a025 100644 --- a/src/e2eTest/tests/test-caseManagement/caseManagement.manageDocuments.spec.ts +++ b/src/e2eTest/tests/test-caseManagement/caseManagement.manageDocuments.spec.ts @@ -8,6 +8,7 @@ import { dismissCookieBanner } from '@config/cookie-banner'; import { initializeCMExecutor, performAction } from '@utils/controller-caseManagement'; import { getCaseTypeId } from '@utils/common/caseType.utils'; import { VERY_LONG_TIMEOUT } from 'playwright.config'; +import { selectDocument } from '@data/page-data-figma/page-data-caseManagement-figma'; test.use({ storageState: undefined }) @@ -33,17 +34,6 @@ test.beforeEach(async ({ page, context }) => { await performAction('login', user.staffAdmin); await dismissCookieBanner(page, 'analytics'); await performAction('navigateToSummaryPage'); - // await performAction('navigateToUrl', `${process.env.MANAGE_CASE_BASE_URL}/cases/case-details/PCS/${getCaseTypeId()}/${process.env.CASE_NUMBER}#Summary`); - // await expect(async () => { - // await page.waitForURL(`${process.env.MANAGE_CASE_BASE_URL}/cases/case-details/PCS/${getCaseTypeId()}/${process.env.CASE_NUMBER}#Summary`, { waitUntil: 'domcontentloaded' }); - // }).toPass({ - // timeout: VERY_LONG_TIMEOUT, - // }); - // await page.waitForLoadState(); - // await page.locator('.spinner-container').waitFor({ state: 'detached' }); - // await performValidation('mainHeader', home.caseSummary); - - }); test.afterEach(async () => { @@ -57,5 +47,8 @@ test.afterEach(async () => { test.describe('Case management - Manage documents e2e Journey @nightly', async () => { test('Case management - Manage documents - Amend @CM @regression', async () => { await performAction('selectAnEvent', { eventType: caseSummary.manageDocuments.amend }); + await performValidation('mainHeader', selectDocument.mainHeader); + await performAction('errorValidationSelectDocumentPage', selectDocument.errorValidation); + await performAction('select', selectDocument.whichFolderQuestion, selectDocument.docFolder); }); }); diff --git a/src/e2eTest/utils/actions/custom-actions/createCaseAPI.action.ts b/src/e2eTest/utils/actions/custom-actions/createCaseAPI.action.ts index d4e7435ba5..e9133bc99a 100644 --- a/src/e2eTest/utils/actions/custom-actions/createCaseAPI.action.ts +++ b/src/e2eTest/utils/actions/custom-actions/createCaseAPI.action.ts @@ -47,7 +47,6 @@ export class CreateCaseAPIAction implements IAction { }); process.env.CASE_NUMBER = createResponse.data.id; caseInfo.id = createResponse.data.id; - console.log('id:'+caseInfo.id) caseInfo.fid = createResponse.data.id.replace(/(.{4})(?=.)/g, "$1-"); caseInfo.state = createResponse.data.state; } catch (error: any) { @@ -454,12 +453,12 @@ export class CreateCaseAPIAction implements IAction { private async updatePaymentAPI(): Promise { const paymentApi = Axios.create(paymentApiData.paymentApiInstance()); - const maxRetries = actionRetries; + const maxRetries = actionRetries + actionRetries; const delayMs = VERY_SHORT_TIMEOUT; for (let attempt = 1; attempt <= maxRetries; attempt++) { try { const response = await paymentApi.get(paymentApiData.getFeePaymentInfoApiEndPoint()); - console.log('payment info'+JSON.stringify(response)); + //console.log('payment info'+JSON.stringify(response)); const paymentInfo = response.data; console.log('payment info'+JSON.stringify(paymentInfo)); if (!paymentInfo?.length) { @@ -470,7 +469,7 @@ export class CreateCaseAPIAction implements IAction { paymentApiData.updatePaymentApiEndPoint, paymentApiData.paymentUpdatePayload(requestReference) ); - console.log(JSON.stringify(updateResponse)); + console.log(JSON.stringify(updateResponse.data)); if (updateResponse.status === 200 || updateResponse.status === 204) { return; } @@ -480,6 +479,7 @@ export class CreateCaseAPIAction implements IAction { const responseBody = error?.response?.data; if (attempt === maxRetries) { if (Axios.isAxiosError(error)) { + console.error("Full response body:", responseBody); throw new Error(`Payment API failed after retries: ${error.response?.status}`); } console.error("HTTP Status:", status); diff --git a/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagement.action.ts b/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagement.action.ts index 6084efec5a..6209e59099 100644 --- a/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagement.action.ts +++ b/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagement.action.ts @@ -49,4 +49,54 @@ export class CaseManagementAction implements IAction { await performAction('select', caseSummary.nextStepEventList, event.eventType); await performAction('clickButton', caseSummary.go); } + + private async inputErrorValidation(page: Page, validationArr: actionRecord) { + + + if (Array.isArray(validationArr.inputArray)) { + for (const item of validationArr.inputArray) { + switch (validationArr.validationType) { + + + case 'radioOptions': + await performAction('clickButton', validationArr.button); + await performValidation('inputError', !validationArr?.label ? validationArr.question : validationArr.label, item.errMessage); + await performValidation('errorMessage', !validationArr?.header ? validationArr.header = 'There is a problem' : validationArr.header, item.errMessage); + await performAction('clickRadioButton', { question: validationArr.question, option: validationArr.option }); + break; + + case 'checkBox': + await performAction('clickButton', validationArr.button); + await performValidation('inputError', !validationArr?.label ? validationArr.question : validationArr.label, item.errMessage); + await performValidation('errorMessage', !validationArr?.header ? validationArr.header = 'There is a problem' : validationArr.header, item.errMessage); + await performAction('check', validationArr.checkBox); + break; + + case 'checkBoxPageLevel': + await performAction('clickButton', validationArr.button); + await performValidation('errorMessage', !validationArr?.header ? validationArr.header = 'There is a problem' : validationArr.header, item.errMessage); + await performAction('check', validationArr.checkBox); + break; + + case 'dropDown': + await performAction('clickButton', validationArr.button); + await expect(async () => { + await performAction('clickButton', validationArr.button); + await performValidation('errorMessage', !validationArr?.header ? validationArr.header = 'There is a problem' : validationArr.header, item.errMessage); + }).toPass({ + timeout: VERY_LONG_TIMEOUT, + }); + await performAction('select', validationArr.docType, validationArr.type); + break; + + default: + throw new Error(`Validation type :"${validationArr.validationType}" is not valid`); + }; + } + } + if (validationArr.buttonRemove) { + await performAction('removeFile'); + await page.waitForTimeout(6000); + } + } } diff --git a/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagementErrorValidation.action.ts b/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagementErrorValidation.action.ts new file mode 100644 index 0000000000..082b622a23 --- /dev/null +++ b/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagementErrorValidation.action.ts @@ -0,0 +1,29 @@ +import { Page } from '@playwright/test'; +import { performAction } from '@utils/controller-enforcement'; +import { IAction, actionData, actionRecord } from '@utils/interfaces/action.interface'; +import { enforcementApplication } from '@data/page-data-figma/page-data-enforcement-figma'; + +export class ErrorValidationAction implements IAction { + async execute(page: Page, action: string, errorFlag: string | actionRecord, roles?: actionData): Promise { + const actionsMap = new Map Promise>([ + ['errorValidationSelectDocumentPage', () => this.errorValidationSelectDocumentPage(errorFlag as string)], + + ]); + const actionToPerform = actionsMap.get(action); + if (!actionToPerform) throw new Error(`No action found for '${action}'`); + await actionToPerform(); + } + + private async errorValidationSelectDocumentPage(validationReq: string) { + if (validationReq === 'YES') { + await performAction('inputErrorValidation', { + validationType: enforcementApplication.errorValidationType.three, + inputArray: enforcementApplication.errorValidationField.errorRadioOption, + question: enforcementApplication.typeOfApplicationQuestion, + option: enforcementApplication.warrantOfPossessionRadioOption, + button: enforcementApplication.continueButton + }); + } + } + +} diff --git a/src/e2eTest/utils/registry/registry-caseManagement/action-caseManagement.registry.ts b/src/e2eTest/utils/registry/registry-caseManagement/action-caseManagement.registry.ts index c0ed096d4a..99371a344e 100644 --- a/src/e2eTest/utils/registry/registry-caseManagement/action-caseManagement.registry.ts +++ b/src/e2eTest/utils/registry/registry-caseManagement/action-caseManagement.registry.ts @@ -1,5 +1,6 @@ import { LoginAction, NavigateToUrlAction, CreateCaseAPIAction } from "@utils/actions/custom-actions"; import { CaseManagementAction } from "@utils/actions/custom-actions/custom-actions-caseManagement"; +import { ErrorValidationAction } from "@utils/actions/custom-actions/custom-actions-caseManagement/caseManagementErrorValidation.action"; import { RecordAnswers } from "@utils/actions/custom-actions/custom-actions-genApps/recordAnsweredFields.action"; import { LinkSolicitorAPIAction } from "@utils/actions/custom-actions/linkSolicitorAPI.action"; import { CheckAction, ClickButtonAction, ClickRadioButtonAction, ClickTabAction, InputTextAction, SelectAction, UploadFileAction } from "@utils/actions/element-actions"; @@ -34,6 +35,8 @@ export class ActionCMRegistry { ['makeAnApplicationAPI', new CreateCaseAPIAction()], ['navigateToSummaryPage', new CaseManagementAction()], ['selectAnEvent', new CaseManagementAction()], + ['errorValidationSelectDocumentPage', new ErrorValidationAction()], + ['inputErrorValidation', new CaseManagementAction()], ]); From ab13b58d016d4fbac8916a2e8c8c864cc64986c6 Mon Sep 17 00:00:00 2001 From: sadmanrahman Date: Mon, 13 Jul 2026 11:21:03 +0100 Subject: [PATCH 47/70] HDPI-7308: fix pipeline --- ...gory.sql => V135__default_uncategorised_document_category.sql} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/main/resources/db/migration/{V133__default_uncategorised_document_category.sql => V135__default_uncategorised_document_category.sql} (100%) diff --git a/src/main/resources/db/migration/V133__default_uncategorised_document_category.sql b/src/main/resources/db/migration/V135__default_uncategorised_document_category.sql similarity index 100% rename from src/main/resources/db/migration/V133__default_uncategorised_document_category.sql rename to src/main/resources/db/migration/V135__default_uncategorised_document_category.sql From 5a32d1dd9a46e0bb736a7f85edb3a9a2d0497eec Mon Sep 17 00:00:00 2001 From: sadmanrahman Date: Mon, 13 Jul 2026 11:51:18 +0100 Subject: [PATCH 48/70] HDPI-7308: fix unit test --- .../ClaimFormPersistenceServiceIT.java | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/integrationTest/java/uk/gov/hmcts/reform/pcs/controllers/ClaimFormPersistenceServiceIT.java b/src/integrationTest/java/uk/gov/hmcts/reform/pcs/controllers/ClaimFormPersistenceServiceIT.java index c0490ec54c..bb6af322f6 100644 --- a/src/integrationTest/java/uk/gov/hmcts/reform/pcs/controllers/ClaimFormPersistenceServiceIT.java +++ b/src/integrationTest/java/uk/gov/hmcts/reform/pcs/controllers/ClaimFormPersistenceServiceIT.java @@ -9,6 +9,7 @@ import org.springframework.test.context.bean.override.mockito.MockitoBean; import uk.gov.hmcts.reform.authorisation.generators.AuthTokenGenerator; import uk.gov.hmcts.reform.ccd.client.CaseAssignmentApi; +import uk.gov.hmcts.reform.pcs.ccd.domain.CaseFileCategory; import uk.gov.hmcts.reform.pcs.ccd.entity.DocumentEntity; import uk.gov.hmcts.reform.pcs.ccd.entity.PcsCaseEntity; import uk.gov.hmcts.reform.pcs.ccd.entity.party.PartyRole; @@ -69,7 +70,7 @@ void documentRolledBackWhenActivityLogWriteFails() { final PcsCaseEntity caseEntity = caseCreationHelper.createTestCaseWithParty( caseReference, UUID.randomUUID(), PartyRole.CLAIMANT); when(documentImportService.addDocumentToCase(eq(caseReference), anyString(), any())) - .thenReturn(DocumentEntity.builder().documentId(UUID.randomUUID()).build()); + .thenReturn(importedDocument()); doThrow(new RuntimeException("activity log write failed")) .when(claimActivityLogService).logGenerationSuccess(caseReference); @@ -88,12 +89,22 @@ void attachesDocumentAndRecordsGenerationSuccess() { final PcsCaseEntity caseEntity = caseCreationHelper.createTestCaseWithParty( caseReference, UUID.randomUUID(), PartyRole.CLAIMANT); when(documentImportService.addDocumentToCase(eq(caseReference), anyString(), any())) - .thenReturn(DocumentEntity.builder().documentId(UUID.randomUUID()).build()); + .thenReturn(importedDocument()); claimFormPersistenceService.attach(caseReference, DM_STORE_URL); UUID claimId = caseEntity.getClaims().getFirst().getId(); - assertThat(claimRepository.findById(claimId).orElseThrow().getClaimFormDocument()).isNotNull(); + assertThat(claimRepository.findById(claimId).orElseThrow().getClaimFormDocument()) + .isNotNull() + .extracting(DocumentEntity::getCategoryId) + .isEqualTo(CaseFileCategory.STATEMENTS_OF_CASE.getId()); verify(claimActivityLogService).logGenerationSuccess(caseReference); } + + private static DocumentEntity importedDocument() { + return DocumentEntity.builder() + .documentId(UUID.randomUUID()) + .categoryId(CaseFileCategory.STATEMENTS_OF_CASE.getId()) + .build(); + } } From d612270dd0e9922d64ad3391558e8077c7ad8948 Mon Sep 17 00:00:00 2001 From: srinijg Date: Mon, 13 Jul 2026 18:26:10 +0100 Subject: [PATCH 49/70] new validations added --- .../data/api-data/submitCase.api.data.ts | 20 ++++++++++++--- .../amendDocumentDetails.page.data.ts | 3 +++ .../page-data-caseManagement-figma/index.ts | 1 + .../selectDocument.page.data.ts | 11 ++++---- .../caseManagement.manageDocuments.spec.ts | 14 ++++++----- .../custom-actions/createCaseAPI.action.ts | 8 +----- .../caseManagement.action.ts | 16 +++++++++--- .../caseManagementErrorValidation.action.ts | 25 ++++++++++++------- .../action-caseManagement.registry.ts | 4 ++- .../pageContent.validation.ts | 6 +++++ 10 files changed, 73 insertions(+), 35 deletions(-) create mode 100644 src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/amendDocumentDetails.page.data.ts diff --git a/src/e2eTest/data/api-data/submitCase.api.data.ts b/src/e2eTest/data/api-data/submitCase.api.data.ts index 7b31a240df..c1b1607ad6 100644 --- a/src/e2eTest/data/api-data/submitCase.api.data.ts +++ b/src/e2eTest/data/api-data/submitCase.api.data.ts @@ -1,9 +1,9 @@ export const submitCaseApiData = { submitCaseEventName: 'resumePossessionClaim', submitCasePayload: { - regionId: "1", - caseManagementLocationNumber: "20262", - orgNameFound: "Yes", + regionId: '1', + caseManagementLocationNumber: '20262', + orgNameFound: 'Yes', legislativeCountry: 'England', claimantType: { value: { @@ -97,6 +97,8 @@ export const submitCaseApiData = { completionNextStep: 'SUBMIT_AND_PAY_NOW' }, submitCasePayloadNoDefendants: { + regionId: '1', + caseManagementLocationNumber: '20262', legislativeCountry: 'England', claimantType: { value: { @@ -166,6 +168,8 @@ export const submitCaseApiData = { completionNextStep: 'SUBMIT_AND_PAY_NOW' }, submitCasePayloadOnlyMain: { + regionId: '1', + caseManagementLocationNumber: '20262', legislativeCountry: 'England', claimantType: { value: { @@ -255,6 +259,8 @@ export const submitCaseApiData = { completionNextStep: 'SUBMIT_AND_PAY_NOW' }, submitCasePayloadCaseTab: { + regionId: '1', + caseManagementLocationNumber: '20262', legislativeCountry: 'England', orgNameFound: 'Yes', claimantType: { @@ -364,6 +370,8 @@ export const submitCaseApiData = { completionNextStep: 'SUBMIT_AND_PAY_NOW' }, submitCasePayloadCaseSummary: { + regionId: '1', + caseManagementLocationNumber: '20262', legislativeCountry: 'England', orgNameFound: 'Yes', claimantType: { @@ -492,6 +500,8 @@ export const submitCaseApiData = { }, }, submitCasePayloadCaseDetails: { + regionId: '1', + caseManagementLocationNumber: '20262', legislativeCountry: 'England', orgNameFound: 'Yes', claimantType: { @@ -657,6 +667,8 @@ export const submitCaseApiData = { }, }, submitCasePayloadCaseFileView: { + regionId: '1', + caseManagementLocationNumber: '20262', orgNameFound: 'Yes', claimantName: 'Possession Claims Solicitor Org', isClaimantNameCorrect: 'YES', @@ -908,6 +920,8 @@ export const submitCaseApiData = { }, submitCasePayloadDefault: { + regionId: '1', + caseManagementLocationNumber: '20262', legislativeCountry: 'England', orgNameFound: 'Yes', claimantType: { diff --git a/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/amendDocumentDetails.page.data.ts b/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/amendDocumentDetails.page.data.ts new file mode 100644 index 0000000000..a42d5ac35e --- /dev/null +++ b/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/amendDocumentDetails.page.data.ts @@ -0,0 +1,3 @@ +export const amendDocumentDetails = { + mainHeader: `Amend document details`, +}; diff --git a/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/index.ts b/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/index.ts index 489440a729..2afc27d86e 100644 --- a/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/index.ts +++ b/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/index.ts @@ -1 +1,2 @@ export * from './selectDocument.page.data'; +export * from './amendDocumentDetails.page.data'; diff --git a/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/selectDocument.page.data.ts b/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/selectDocument.page.data.ts index 85b707d556..b7b5d611d7 100644 --- a/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/selectDocument.page.data.ts +++ b/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/selectDocument.page.data.ts @@ -2,18 +2,19 @@ export const selectDocument = { mainHeader: `Select document`, whichFolderQuestion: `Which folder is the document in?`, documentToAmendHiddenQuestion: `Which document do you want to amend?`, - docFolder: `Property documents`, + docFolderHiddenOption: `Property documents`, continueButton: `Continue`, previousButton: `Previous`, cancelLink: `Cancel`, - errorValidation: `NO`,//set it to `NO` before raising a PR + errorValidation: `YES`, + typeOfDocumentHiddenRadioOption: `NoticeDetails - Claimant 1.pdf`, errorValidationType: { one: `textField`, two: `radioOptions`, three: `checkBox`, four: `dropDown` }, errorValidationField: { errorDropDown: [ - { type: 'none', input: '', errMessage: 'Type of document is required' }, + { type: 'none', input: '', errMessage: `Which folder is the document in? is required` }, ], errorRadioOption: [ - { type: 'none', input: '', errMessage: 'Field is required' } - ] + { type: 'none', input: '', errMessage: `Which document do you want to amend? is required`, errInlineMessage: `Field is required` } + ], }, }; diff --git a/src/e2eTest/tests/test-caseManagement/caseManagement.manageDocuments.spec.ts b/src/e2eTest/tests/test-caseManagement/caseManagement.manageDocuments.spec.ts index d84bc7a025..bd8ae4a657 100644 --- a/src/e2eTest/tests/test-caseManagement/caseManagement.manageDocuments.spec.ts +++ b/src/e2eTest/tests/test-caseManagement/caseManagement.manageDocuments.spec.ts @@ -1,14 +1,12 @@ import { createCaseApiData, makeAnApplicationApiData, submitCaseApiData } from '@data/api-data'; import { initializeExecutor, performValidation } from '@utils/controller'; -import test, { expect } from '@playwright/test'; +import test from '@playwright/test'; import { caseInfo, defendantUserDetails } from '@utils/actions/custom-actions'; import { PageContentValidation } from '@utils/validations/element-validations/pageContent.validation'; -import { caseSummary, home, user } from '@data/page-data'; +import { caseSummary, user } from '@data/page-data'; import { dismissCookieBanner } from '@config/cookie-banner'; import { initializeCMExecutor, performAction } from '@utils/controller-caseManagement'; -import { getCaseTypeId } from '@utils/common/caseType.utils'; -import { VERY_LONG_TIMEOUT } from 'playwright.config'; -import { selectDocument } from '@data/page-data-figma/page-data-caseManagement-figma'; +import { amendDocumentDetails, selectDocument } from '@data/page-data-figma/page-data-caseManagement-figma'; test.use({ storageState: undefined }) @@ -49,6 +47,10 @@ test.describe('Case management - Manage documents e2e Journey @nightly', async ( await performAction('selectAnEvent', { eventType: caseSummary.manageDocuments.amend }); await performValidation('mainHeader', selectDocument.mainHeader); await performAction('errorValidationSelectDocumentPage', selectDocument.errorValidation); - await performAction('select', selectDocument.whichFolderQuestion, selectDocument.docFolder); + await performAction('selectDocumentToAmend', { + question: selectDocument.whichFolderQuestion, option: selectDocument.docFolderHiddenOption, + question1: selectDocument.documentToAmendHiddenQuestion, option1: selectDocument.typeOfDocumentHiddenRadioOption, + nextPage: amendDocumentDetails.mainHeader + }); }); }); diff --git a/src/e2eTest/utils/actions/custom-actions/createCaseAPI.action.ts b/src/e2eTest/utils/actions/custom-actions/createCaseAPI.action.ts index e9133bc99a..a462269487 100644 --- a/src/e2eTest/utils/actions/custom-actions/createCaseAPI.action.ts +++ b/src/e2eTest/utils/actions/custom-actions/createCaseAPI.action.ts @@ -458,9 +458,7 @@ export class CreateCaseAPIAction implements IAction { for (let attempt = 1; attempt <= maxRetries; attempt++) { try { const response = await paymentApi.get(paymentApiData.getFeePaymentInfoApiEndPoint()); - //console.log('payment info'+JSON.stringify(response)); const paymentInfo = response.data; - console.log('payment info'+JSON.stringify(paymentInfo)); if (!paymentInfo?.length) { throw new Error('No payment information found.'); } @@ -469,20 +467,16 @@ export class CreateCaseAPIAction implements IAction { paymentApiData.updatePaymentApiEndPoint, paymentApiData.paymentUpdatePayload(requestReference) ); - console.log(JSON.stringify(updateResponse.data)); if (updateResponse.status === 200 || updateResponse.status === 204) { return; } throw new Error(`Payment update failed with status ${updateResponse.status}`); } catch (error: any) { const status = error?.response?.status; - const responseBody = error?.response?.data; if (attempt === maxRetries) { if (Axios.isAxiosError(error)) { - console.error("Full response body:", responseBody); - throw new Error(`Payment API failed after retries: ${error.response?.status}`); + throw new Error(`Payment API failed after retries: ${status}`); } - console.error("HTTP Status:", status); throw new Error(`Payment API failed unexpectedly after retries.${error}`); } await new Promise(res => setTimeout(res, delayMs)); diff --git a/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagement.action.ts b/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagement.action.ts index 6209e59099..6aa019db95 100644 --- a/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagement.action.ts +++ b/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagement.action.ts @@ -6,6 +6,7 @@ import { getCaseTypeId } from '@utils/common/caseType.utils'; import { performAction, performValidation } from '@utils/controller-caseManagement'; import { VERY_LONG_TIMEOUT } from 'playwright.config'; import { caseSummary, home } from '@data/page-data'; +import { selectDocument } from '@data/page-data-figma/page-data-caseManagement-figma'; export const addressInfo = { @@ -22,6 +23,8 @@ export class CaseManagementAction implements IAction { const actionsMap = new Map Promise>([ ['navigateToSummaryPage', () => this.navigateToSummaryPage(page)], ['selectAnEvent', () => this.selectAnEvent(fieldName as actionRecord)], + ['selectDocumentToAmend', () => this.selectDocumentToAmend(fieldName as actionRecord)], + ['inputErrorValidation', () => this.inputErrorValidation(page, fieldName as actionRecord)], ]); const actionToPerform = actionsMap.get(action); @@ -32,8 +35,6 @@ export class CaseManagementAction implements IAction { } private async navigateToSummaryPage(page: Page) { - console.log(process.env.CASE_NUMBER); - console.log(`${process.env.MANAGE_CASE_BASE_URL}/cases/case-details/PCS/${getCaseTypeId()}/${process.env.CASE_NUMBER}#Summary`) await performAction('navigateToUrl', `${process.env.MANAGE_CASE_BASE_URL}/cases/case-details/PCS/${getCaseTypeId()}/${process.env.CASE_NUMBER}#Summary`); await expect(async () => { await page.waitForURL(`${process.env.MANAGE_CASE_BASE_URL}/cases/case-details/PCS/${getCaseTypeId()}/${process.env.CASE_NUMBER}#Summary`, { waitUntil: 'domcontentloaded' }); @@ -50,6 +51,13 @@ export class CaseManagementAction implements IAction { await performAction('clickButton', caseSummary.go); } + private async selectDocumentToAmend(selectDoc: actionRecord){ + await performAction('select', selectDoc.question, selectDoc.option); + await performAction('clickRadioButton', { question: selectDoc.question1, option: selectDoc.option1 }); + await performAction('reTryOnCallBackError', selectDocument.continueButton, selectDoc.nextPage as string); + + } + private async inputErrorValidation(page: Page, validationArr: actionRecord) { @@ -60,7 +68,7 @@ export class CaseManagementAction implements IAction { case 'radioOptions': await performAction('clickButton', validationArr.button); - await performValidation('inputError', !validationArr?.label ? validationArr.question : validationArr.label, item.errMessage); + await performValidation('inputError', !validationArr?.label ? validationArr.question : validationArr.label, item.errInlineMessage); await performValidation('errorMessage', !validationArr?.header ? validationArr.header = 'There is a problem' : validationArr.header, item.errMessage); await performAction('clickRadioButton', { question: validationArr.question, option: validationArr.option }); break; @@ -86,7 +94,7 @@ export class CaseManagementAction implements IAction { }).toPass({ timeout: VERY_LONG_TIMEOUT, }); - await performAction('select', validationArr.docType, validationArr.type); + await performAction('select', validationArr.dropQn, validationArr.option); break; default: diff --git a/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagementErrorValidation.action.ts b/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagementErrorValidation.action.ts index 082b622a23..52c7f6fbc5 100644 --- a/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagementErrorValidation.action.ts +++ b/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagementErrorValidation.action.ts @@ -1,13 +1,13 @@ import { Page } from '@playwright/test'; -import { performAction } from '@utils/controller-enforcement'; +import { performAction } from '@utils/controller-caseManagement'; import { IAction, actionData, actionRecord } from '@utils/interfaces/action.interface'; -import { enforcementApplication } from '@data/page-data-figma/page-data-enforcement-figma'; +import { selectDocument } from '@data/page-data-figma/page-data-caseManagement-figma'; export class ErrorValidationAction implements IAction { async execute(page: Page, action: string, errorFlag: string | actionRecord, roles?: actionData): Promise { const actionsMap = new Map Promise>([ ['errorValidationSelectDocumentPage', () => this.errorValidationSelectDocumentPage(errorFlag as string)], - + ]); const actionToPerform = actionsMap.get(action); if (!actionToPerform) throw new Error(`No action found for '${action}'`); @@ -17,13 +17,20 @@ export class ErrorValidationAction implements IAction { private async errorValidationSelectDocumentPage(validationReq: string) { if (validationReq === 'YES') { await performAction('inputErrorValidation', { - validationType: enforcementApplication.errorValidationType.three, - inputArray: enforcementApplication.errorValidationField.errorRadioOption, - question: enforcementApplication.typeOfApplicationQuestion, - option: enforcementApplication.warrantOfPossessionRadioOption, - button: enforcementApplication.continueButton + validationType: selectDocument.errorValidationType.four, + inputArray: selectDocument.errorValidationField.errorDropDown, + dropQn: selectDocument.whichFolderQuestion, + option: selectDocument.docFolderHiddenOption, + button: selectDocument.continueButton + }); + await performAction('inputErrorValidation', { + validationType: selectDocument.errorValidationType.two, + inputArray: selectDocument.errorValidationField.errorRadioOption, + question: selectDocument.documentToAmendHiddenQuestion, + option: selectDocument.typeOfDocumentHiddenRadioOption, + button: selectDocument.continueButton }); } } - + } diff --git a/src/e2eTest/utils/registry/registry-caseManagement/action-caseManagement.registry.ts b/src/e2eTest/utils/registry/registry-caseManagement/action-caseManagement.registry.ts index 99371a344e..1858b2e686 100644 --- a/src/e2eTest/utils/registry/registry-caseManagement/action-caseManagement.registry.ts +++ b/src/e2eTest/utils/registry/registry-caseManagement/action-caseManagement.registry.ts @@ -1,11 +1,11 @@ import { LoginAction, NavigateToUrlAction, CreateCaseAPIAction } from "@utils/actions/custom-actions"; import { CaseManagementAction } from "@utils/actions/custom-actions/custom-actions-caseManagement"; import { ErrorValidationAction } from "@utils/actions/custom-actions/custom-actions-caseManagement/caseManagementErrorValidation.action"; -import { RecordAnswers } from "@utils/actions/custom-actions/custom-actions-genApps/recordAnsweredFields.action"; import { LinkSolicitorAPIAction } from "@utils/actions/custom-actions/linkSolicitorAPI.action"; import { CheckAction, ClickButtonAction, ClickRadioButtonAction, ClickTabAction, InputTextAction, SelectAction, UploadFileAction } from "@utils/actions/element-actions"; import { ClickLinkAction } from "@utils/actions/element-actions/clickLink.action"; import { ClickSummaryAction } from "@utils/actions/element-actions/clickSummary.action"; +import { RetryOnCallBackError } from "@utils/actions/element-actions/reTryOnCallBackError.action"; import { IAction } from "@utils/interfaces"; @@ -35,8 +35,10 @@ export class ActionCMRegistry { ['makeAnApplicationAPI', new CreateCaseAPIAction()], ['navigateToSummaryPage', new CaseManagementAction()], ['selectAnEvent', new CaseManagementAction()], + ['selectDocumentToAmend', new CaseManagementAction()], ['errorValidationSelectDocumentPage', new ErrorValidationAction()], ['inputErrorValidation', new CaseManagementAction()], + ['reTryOnCallBackError', new RetryOnCallBackError()], ]); diff --git a/src/e2eTest/utils/validations/element-validations/pageContent.validation.ts b/src/e2eTest/utils/validations/element-validations/pageContent.validation.ts index d05f176c68..c9eb07ec97 100644 --- a/src/e2eTest/utils/validations/element-validations/pageContent.validation.ts +++ b/src/e2eTest/utils/validations/element-validations/pageContent.validation.ts @@ -182,6 +182,9 @@ export class PageContentValidation implements IValidation { else if(page.url().includes("makeAnApplication")){ mappingPath = path.join(__dirname, '../../../data/page-data-figma/page-data-genApps-figma/urlToFileMappingGenApps.ts'); } + else if(page.url().includes("amendDocuments")){ + mappingPath = path.join(__dirname, '../../../data/page-data-figma/page-data-caseManagement-figma/urlToFileMappingCM.ts'); + } else{ mappingPath = path.join(__dirname, '../../../data/page-data-figma/urlToFileMapping.ts'); } @@ -241,6 +244,9 @@ export class PageContentValidation implements IValidation { else if (page.url().includes("globalSearch")) { filePath = path.join(__dirname, '../../../data/page-data-figma/page-data-common-component', `${fileName}.page.data.ts`); } + else if (page.url().includes("amendDocuments")) { + filePath = path.join(__dirname, '../../../data/page-data-figma/page-data-caseManagement-figma', `${fileName}.page.data.ts`); + } else { filePath = path.join(__dirname, '../../../data/page-data-figma', `${fileName}.page.data.ts`); } From dc4c803d7188ed55be13b788cf28d5a8ffb58758 Mon Sep 17 00:00:00 2001 From: srinijg Date: Mon, 13 Jul 2026 18:41:03 +0100 Subject: [PATCH 50/70] conflicts fixed --- .../reform/pcs/ccd/view/DocumentsView.java | 6 +--- .../pcs/ccd/view/DocumentsViewTest.java | 29 +------------------ 2 files changed, 2 insertions(+), 33 deletions(-) diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/view/DocumentsView.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/view/DocumentsView.java index fb639dcf16..48e2df69d8 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/view/DocumentsView.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/view/DocumentsView.java @@ -86,10 +86,6 @@ public static boolean isDescriptionEmpty(DocumentEntity documentEntity) { } private boolean isNotInCaseDetailsTab(DocumentEntity documentEntity) { - if (documentEntity.getGeneralApplication() != null) { - return true; - } - List caseDetailsDocuments = List.of( DocumentType.TENANCY_AGREEMENT, DocumentType.POSSESSION_NOTICE, @@ -109,4 +105,4 @@ private boolean isNotInCaseDetailsTab(DocumentEntity documentEntity) { return !isDescriptionEmpty(documentEntity); } -} +} \ No newline at end of file diff --git a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/view/DocumentsViewTest.java b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/view/DocumentsViewTest.java index 1511bf79dc..86007d3d26 100644 --- a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/view/DocumentsViewTest.java +++ b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/view/DocumentsViewTest.java @@ -308,33 +308,6 @@ void shouldNotFilterOutDocumentsThatHaveADescription(DocumentType documentType) assertThat(allDocuments.getFirst().getValue().getFilename()).isEqualTo("filename"); } - @ParameterizedTest - @MethodSource("caseDetailsTabDocuments") - void shouldNotFilterOutGenAppDocumentsThatAppearInCaseDetailsTab(DocumentType documentType) { - // Given - GenAppEntity genAppEntity = mock(GenAppEntity.class); - UUID document1Id = UUID.randomUUID(); - DocumentEntity documentEntity = DocumentEntity.builder() - .id(document1Id) - .fileName("genApps GA1 - Defendant 2.docx") - .type(documentType) - .generalApplication(genAppEntity) - .build(); - - when(securityContextService.getCurrentUserId()).thenReturn(CURRENT_USER_ID); - when(genAppVisibilityService.isGenAppVisibleToUser(genAppEntity, CURRENT_USER_ID)) - .thenReturn(true); - when(pcsCaseEntity.getDocuments()).thenReturn(List.of(documentEntity)); - - // When - underTest.setCaseFields(pcsCase, pcsCaseEntity); - - // Then - List> allDocuments = pcsCase.getAllDocuments(); - assertThat(allDocuments).hasSize(1); - assertThat(allDocuments.getFirst().getValue().getFilename()).isEqualTo("genApps GA1 - Defendant 2.docx"); - } - @ParameterizedTest @MethodSource("nonCaseDetailsTabDocuments") void shouldNotFilterOutDocumentsThatDoNotAppearInCaseDetailsTab(DocumentType documentType) { @@ -396,4 +369,4 @@ private static Stream nonCaseDetailsTabDocuments() { Arguments.of(DocumentType.OTHER) ); } -} +} \ No newline at end of file From ef9feb7288337eb3772366b5bfb7eb2b987ccc1c Mon Sep 17 00:00:00 2001 From: srinijg Date: Mon, 13 Jul 2026 18:50:00 +0100 Subject: [PATCH 51/70] spacing adjusted --- .../java/uk/gov/hmcts/reform/pcs/ccd/view/DocumentsView.java | 2 +- .../uk/gov/hmcts/reform/pcs/ccd/view/DocumentsViewTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/view/DocumentsView.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/view/DocumentsView.java index 48e2df69d8..3a0ffd2307 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/view/DocumentsView.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/view/DocumentsView.java @@ -105,4 +105,4 @@ private boolean isNotInCaseDetailsTab(DocumentEntity documentEntity) { return !isDescriptionEmpty(documentEntity); } -} \ No newline at end of file +} diff --git a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/view/DocumentsViewTest.java b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/view/DocumentsViewTest.java index 86007d3d26..eaf64dcf94 100644 --- a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/view/DocumentsViewTest.java +++ b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/view/DocumentsViewTest.java @@ -369,4 +369,4 @@ private static Stream nonCaseDetailsTabDocuments() { Arguments.of(DocumentType.OTHER) ); } -} \ No newline at end of file +} From 2db68d5a9af8b4b8e3ef02c27147a085c35650b4 Mon Sep 17 00:00:00 2001 From: srinijg Date: Mon, 13 Jul 2026 18:56:30 +0100 Subject: [PATCH 52/70] case file folders name change --- src/e2eTest/data/page-data/home.page.data.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/e2eTest/data/page-data/home.page.data.ts b/src/e2eTest/data/page-data/home.page.data.ts index 74891b516e..6809d8e1bc 100644 --- a/src/e2eTest/data/page-data/home.page.data.ts +++ b/src/e2eTest/data/page-data/home.page.data.ts @@ -13,7 +13,7 @@ export const home = caseSummary: 'Summary', caseDetails: 'Case Details', caseFileView: 'Case File View', - caseFileFolders: ['Appeals','Applications','Orders and notice of hearings','Hearing documents','Property documents','Evidence','Statements of case','Correspondence','Uncategorised documents'], + caseFileFolders: ['Appeals','Applications','Orders and Notice of Hearings','Hearing documents','Property documents','Evidence','Statements of case','Correspondence','Uncategorised documents'], caseListTableHeader: ['Case number','Date issued','Claimant names','Defendant names','Postcode','State'], signOutButton: 'Sign out', }; \ No newline at end of file From 3e3a02478cf1e7f9622e7de53de5090eb9efc257 Mon Sep 17 00:00:00 2001 From: srinijg Date: Tue, 14 Jul 2026 09:49:44 +0100 Subject: [PATCH 53/70] new validation registry added --- .../utils/controller-caseManagement.ts | 2 +- .../registry/registry-caseManagement/index.ts | 2 + .../validation-caseManagement.registry.ts | 44 +++++++++++++++++++ 3 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 src/e2eTest/utils/registry/registry-caseManagement/index.ts create mode 100644 src/e2eTest/utils/registry/registry-caseManagement/validation-caseManagement.registry.ts diff --git a/src/e2eTest/utils/controller-caseManagement.ts b/src/e2eTest/utils/controller-caseManagement.ts index 0a09f377b3..33e6d27ac0 100644 --- a/src/e2eTest/utils/controller-caseManagement.ts +++ b/src/e2eTest/utils/controller-caseManagement.ts @@ -1,11 +1,11 @@ import { Page, test } from '@playwright/test'; import { actionData, actionRecord, actionTuple } from './interfaces/action.interface'; import { validationData, validationRecord, validationTuple } from './interfaces/validation.interface'; -import { ValidationRegistry } from './registry/registry-enforcement/validation-enforcement.registry'; import { AxeUtils } from "@hmcts/playwright-common"; import { cyaStore } from '@utils/validations/custom-validations/CYA/cyaPage.validation'; import { logToBrowser } from './test-logger'; import { ActionCMRegistry } from './registry/registry-caseManagement/action-caseManagement.registry'; +import { ValidationRegistry } from './registry/registry-caseManagement/validation-caseManagement.registry'; let testExecutor: { page: Page }; let previousUrl: string = ''; diff --git a/src/e2eTest/utils/registry/registry-caseManagement/index.ts b/src/e2eTest/utils/registry/registry-caseManagement/index.ts new file mode 100644 index 0000000000..01cf190241 --- /dev/null +++ b/src/e2eTest/utils/registry/registry-caseManagement/index.ts @@ -0,0 +1,2 @@ +export * from "@utils/registry/registry-caseManagement/action-caseManagement.registry"; +export * from "@utils/registry/registry-caseManagement/validation-caseManagement.registry"; diff --git a/src/e2eTest/utils/registry/registry-caseManagement/validation-caseManagement.registry.ts b/src/e2eTest/utils/registry/registry-caseManagement/validation-caseManagement.registry.ts new file mode 100644 index 0000000000..08903e1ed4 --- /dev/null +++ b/src/e2eTest/utils/registry/registry-caseManagement/validation-caseManagement.registry.ts @@ -0,0 +1,44 @@ +import {IValidation} from '@utils/interfaces/validation.interface'; +import {TextValidation} from '@utils/validations/element-validations/text.validation'; +import {BannerAlertValidation} from '@utils/validations/element-validations/bannerAlert.validation'; +import {VisibilityValidation} from '@utils/validations/element-validations/visibility.validation'; +import {FormLabelValueValidation} from '@utils/validations/element-validations/formLabelValue.validation'; +import {OptionListValidation} from '@utils/validations/element-validations/optionList.validation'; +import {MainHeaderValidation} from '@utils/validations/element-validations/pageHeader.validation'; +import {ErrorMessageValidation} from '@utils/validations/element-validations/error-message.validation'; +import {RadioButtonValidation} from '@utils/validations/element-validations/radioButton.validation'; +import {PageContentValidation} from "@utils/validations/element-validations/pageContent.validation"; +import {InputErrorValidation} from "@utils/validations/element-validations/inputError.validation"; +import {ValidatePrePopulatedValues} from '@utils/validations/element-validations/validatePrePopulatedValues.validation'; + +export class ValidationRegistry { + private static validations: Map = new Map([ + ['text', new TextValidation()], + ['bannerAlert', new BannerAlertValidation()], + ['formLabelValue', new FormLabelValueValidation()], + ['optionList', new OptionListValidation()], + ['mainHeader', new MainHeaderValidation()], + ['errorMessage', new ErrorMessageValidation()], + ['radioButtonChecked', new RadioButtonValidation()], + ['elementToBeVisible', new VisibilityValidation()], + ['elementNotToBeVisible', new VisibilityValidation()], + ['waitUntilElementDisappears', new VisibilityValidation()], + ['autoValidatePageContent', new PageContentValidation()], + ['inputError', new InputErrorValidation()], + ['validateRadioButtonValues', new ValidatePrePopulatedValues()], + ['validateInputTextValues', new ValidatePrePopulatedValues()], + ['validateCheckBoxSelection', new ValidatePrePopulatedValues()], + ]); + + static getValidation(validationType: string): IValidation { + const validation = this.validations.get(validationType); + if (!validation) { + throw new Error(`Validation '${validationType}' is not registered. Available validations: ${Array.from(this.validations.keys()).join(', ')}`); + } + return validation; + } + + static getAvailableValidations(): string[] { + return Array.from(this.validations.keys()); + } +} \ No newline at end of file From a0ca8f571b9c01d1dfd4034b16988827693c8490 Mon Sep 17 00:00:00 2001 From: srinijg Date: Tue, 14 Jul 2026 18:34:40 +0100 Subject: [PATCH 54/70] new tests added --- .../changeCaseState.page.data.ts | 37 +++++++++++++ .../checkYourAnswersChangeState.page.data.ts | 7 +++ .../page-data-caseManagement-figma/index.ts | 2 + .../urlToFileMappingCM.ts | 1 + .../data/page-data/caseSummary.page.data.ts | 3 +- ...seManagement.caseWorkerChangeState.spec.ts | 55 +++++++++++++++++++ .../caseManagement.action.ts | 7 ++- .../caseManagementErrorValidation.action.ts | 15 ++++- .../utils/controller-caseManagement.ts | 5 +- .../action-caseManagement.registry.ts | 2 + .../pageContent.validation.ts | 19 +++++-- 11 files changed, 145 insertions(+), 8 deletions(-) create mode 100644 src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/changeCaseState.page.data.ts create mode 100644 src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/checkYourAnswersChangeState.page.data.ts create mode 100644 src/e2eTest/tests/test-caseManagement/caseManagement.caseWorkerChangeState.spec.ts diff --git a/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/changeCaseState.page.data.ts b/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/changeCaseState.page.data.ts new file mode 100644 index 0000000000..e0c4fd09c7 --- /dev/null +++ b/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/changeCaseState.page.data.ts @@ -0,0 +1,37 @@ + +const caseStateHiddenOptionArray = [ + 'Judicial Referral', + 'Hearing Readiness', + 'Prepare For Hearing Conduct Hearing', + 'Decision Outcome', + 'Case Progression', + 'All Final Orders', + 'Case Stayed', + 'Breathing space', +]; + +export const changeCaseState = { + mainHeader: `Case state to change to`, + currentStateParagraph: `Current state: Case Issued`, + whichStateYouMovingCaseToQuestion: `Which state are you moving the case to?`, + caseStateHiddenOption: caseStateHiddenOptionArray[Math.floor(Math.random() * caseStateHiddenOptionArray.length)], + continueButton: `Continue`, + previousButton: `Previous`, + cancelLink: `Cancel`, + errorValidation: `YES`, + typeOfDocumentHiddenRadioOption: `NoticeDetails - Claimant 1.pdf`, + errorValidationType: { one: `textField`, two: `radioOptions`, three: `checkBox`, four: `dropDown` }, + errorValidationField: { + errorDropDown: [ + { type: 'none', input: '', errMessage: `Which state are you moving the case to? is required` }, + ], + errorRadioOption: [ + { type: 'none', input: '', errMessage: `Which document do you want to amend? is required`, errInlineMessage: `Field is required` } + ], + }, +}; + + + + + diff --git a/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/checkYourAnswersChangeState.page.data.ts b/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/checkYourAnswersChangeState.page.data.ts new file mode 100644 index 0000000000..eb93b42493 --- /dev/null +++ b/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/checkYourAnswersChangeState.page.data.ts @@ -0,0 +1,7 @@ +export const checkYourAnswersChangeState = { + mainHeader: `Change case state`, + cyaHeader: `Check your answers`, + submitButton: `Submit`, + previousButton: `Previous`, + cancelLink: `Cancel`, +}; diff --git a/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/index.ts b/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/index.ts index 2afc27d86e..3bce9007b3 100644 --- a/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/index.ts +++ b/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/index.ts @@ -1,2 +1,4 @@ export * from './selectDocument.page.data'; export * from './amendDocumentDetails.page.data'; +export * from './changeCaseState.page.data'; +export * from './checkYourAnswersChangeState.page.data' diff --git a/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/urlToFileMappingCM.ts b/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/urlToFileMappingCM.ts index 7032021a9a..78ab0853b6 100644 --- a/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/urlToFileMappingCM.ts +++ b/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/urlToFileMappingCM.ts @@ -1,3 +1,4 @@ export default { 'amendDocumentsselectDocument': 'selectDocument', + 'changeCaseStatechangeCaseStatePage': 'changeCaseState' }; diff --git a/src/e2eTest/data/page-data/caseSummary.page.data.ts b/src/e2eTest/data/page-data/caseSummary.page.data.ts index 3ebffafb43..0c028d2f63 100644 --- a/src/e2eTest/data/page-data/caseSummary.page.data.ts +++ b/src/e2eTest/data/page-data/caseSummary.page.data.ts @@ -15,5 +15,6 @@ export const caseSummary = { serviceRequestTab: 'Service Request', manageDocuments:{ amend : 'Manage documents: Amend' - } + }, + changeCaseState: 'Change case state' } diff --git a/src/e2eTest/tests/test-caseManagement/caseManagement.caseWorkerChangeState.spec.ts b/src/e2eTest/tests/test-caseManagement/caseManagement.caseWorkerChangeState.spec.ts new file mode 100644 index 0000000000..f3c1d1137e --- /dev/null +++ b/src/e2eTest/tests/test-caseManagement/caseManagement.caseWorkerChangeState.spec.ts @@ -0,0 +1,55 @@ +import { createCaseApiData, makeAnApplicationApiData, submitCaseApiData } from '@data/api-data'; +import { initializeExecutor, performValidation } from '@utils/controller'; +import test from '@playwright/test'; +import { caseInfo, defendantUserDetails } from '@utils/actions/custom-actions'; +import { PageContentValidation } from '@utils/validations/element-validations/pageContent.validation'; +import { caseSummary, user } from '@data/page-data'; +import { dismissCookieBanner } from '@config/cookie-banner'; +import { initializeCMExecutor, performAction } from '@utils/controller-caseManagement'; +import { changeCaseState, checkYourAnswersChangeState } from '@data/page-data-figma/page-data-caseManagement-figma'; + +test.use({ storageState: undefined }) + +test.beforeEach(async ({ page, context }) => { + await context.clearCookies(); + initializeExecutor(page); + initializeCMExecutor(page); + await performAction('createCaseAPI', { data: createCaseApiData.createCasePayload }); + await performAction('submitCaseAPI', { data: submitCaseApiData.submitCasePayloadCaseFileView }); + await performAction('updatePaymentAPI'); + await performAction('getCaseAPI', 'Link Solicitor'); + + for (const defendant of defendantUserDetails) { + await performAction('makeAnApplicationAPI', { + data: makeAnApplicationApiData.makeAnApplicationAdjournPayload( + defendant.id, + defendant.name + ), + }); + }; + await performAction('navigateToUrl', process.env.MANAGE_CASE_BASE_URL); + await dismissCookieBanner(page, 'additional'); + await performAction('login', user.staffAdmin); + await dismissCookieBanner(page, 'analytics'); + await performAction('navigateToSummaryPage'); +}); + +test.afterEach(async () => { + if (caseInfo.id) { + await performAction('deleteCaseRole', '[CLAIMANTSOLICITOR]'); + } + PageContentValidation.finaliseTest(); + +}); + +test.describe('Case management - Case Worker change case state @nightly', async () => { + test('Case management - Case Worker change case state @CM @regression', async () => { + await performAction('selectAnEvent', { eventType: caseSummary.changeCaseState }); + await performValidation('mainHeader', changeCaseState.mainHeader); + await performAction('errorValidationChangeCaseStatePage', changeCaseState.errorValidation); + await performAction('changeCaseState', { + question: changeCaseState.whichStateYouMovingCaseToQuestion, option: changeCaseState.caseStateHiddenOption, + nextPage: checkYourAnswersChangeState.mainHeader + }); + }); +}); diff --git a/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagement.action.ts b/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagement.action.ts index 6aa019db95..c1fb9e1055 100644 --- a/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagement.action.ts +++ b/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagement.action.ts @@ -6,7 +6,7 @@ import { getCaseTypeId } from '@utils/common/caseType.utils'; import { performAction, performValidation } from '@utils/controller-caseManagement'; import { VERY_LONG_TIMEOUT } from 'playwright.config'; import { caseSummary, home } from '@data/page-data'; -import { selectDocument } from '@data/page-data-figma/page-data-caseManagement-figma'; +import { changeCaseState, selectDocument } from '@data/page-data-figma/page-data-caseManagement-figma'; export const addressInfo = { @@ -24,6 +24,7 @@ export class CaseManagementAction implements IAction { ['navigateToSummaryPage', () => this.navigateToSummaryPage(page)], ['selectAnEvent', () => this.selectAnEvent(fieldName as actionRecord)], ['selectDocumentToAmend', () => this.selectDocumentToAmend(fieldName as actionRecord)], + ['changeCaseState', () => this.changeCaseState(fieldName as actionRecord)], ['inputErrorValidation', () => this.inputErrorValidation(page, fieldName as actionRecord)], ]); @@ -55,7 +56,11 @@ export class CaseManagementAction implements IAction { await performAction('select', selectDoc.question, selectDoc.option); await performAction('clickRadioButton', { question: selectDoc.question1, option: selectDoc.option1 }); await performAction('reTryOnCallBackError', selectDocument.continueButton, selectDoc.nextPage as string); + } + private async changeCaseState(caseState: actionRecord){ + await performAction('select', caseState.question, caseState.option); + await performAction('reTryOnCallBackError', changeCaseState.continueButton, caseState.nextPage as string); } private async inputErrorValidation(page: Page, validationArr: actionRecord) { diff --git a/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagementErrorValidation.action.ts b/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagementErrorValidation.action.ts index 52c7f6fbc5..9b71a6c2ac 100644 --- a/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagementErrorValidation.action.ts +++ b/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagementErrorValidation.action.ts @@ -1,12 +1,13 @@ import { Page } from '@playwright/test'; import { performAction } from '@utils/controller-caseManagement'; import { IAction, actionData, actionRecord } from '@utils/interfaces/action.interface'; -import { selectDocument } from '@data/page-data-figma/page-data-caseManagement-figma'; +import { changeCaseState, selectDocument } from '@data/page-data-figma/page-data-caseManagement-figma'; export class ErrorValidationAction implements IAction { async execute(page: Page, action: string, errorFlag: string | actionRecord, roles?: actionData): Promise { const actionsMap = new Map Promise>([ ['errorValidationSelectDocumentPage', () => this.errorValidationSelectDocumentPage(errorFlag as string)], + ['errorValidationChangeCaseStatePage', () => this.errorValidationChangeCaseStatePage(errorFlag as string)], ]); const actionToPerform = actionsMap.get(action); @@ -33,4 +34,16 @@ export class ErrorValidationAction implements IAction { } } + private async errorValidationChangeCaseStatePage(validationReq: string) { + if (validationReq === 'YES') { + await performAction('inputErrorValidation', { + validationType: changeCaseState.errorValidationType.four, + inputArray: changeCaseState.errorValidationField.errorDropDown, + dropQn: changeCaseState.whichStateYouMovingCaseToQuestion, + option: changeCaseState.caseStateHiddenOption, + button: changeCaseState.continueButton + }); + } + } + } diff --git a/src/e2eTest/utils/controller-caseManagement.ts b/src/e2eTest/utils/controller-caseManagement.ts index 33e6d27ac0..b2ce79aa06 100644 --- a/src/e2eTest/utils/controller-caseManagement.ts +++ b/src/e2eTest/utils/controller-caseManagement.ts @@ -70,7 +70,7 @@ async function validatePageIfNavigated(action: string): Promise { } function captureDataForCYA(action: string, fieldName?: actionData | actionRecord, value?: actionData | actionRecord): void { - if (action === 'selectClaimantType') { + if (action === 'changeCaseState') { captureDataForCYAPage = true; } @@ -82,6 +82,9 @@ function captureDataForCYA(action: string, fieldName?: actionData | actionRecord export async function performAction(action: string, fieldName?: actionData | actionRecord, value?: actionData | actionRecord): Promise { const executor = getExecutor(); const actionInstance = ActionCMRegistry.getAction(action); + + captureDataForCYA(action, fieldName, value); + let displayFieldName = fieldName; let displayValue = value ?? fieldName; diff --git a/src/e2eTest/utils/registry/registry-caseManagement/action-caseManagement.registry.ts b/src/e2eTest/utils/registry/registry-caseManagement/action-caseManagement.registry.ts index 1858b2e686..965532c77a 100644 --- a/src/e2eTest/utils/registry/registry-caseManagement/action-caseManagement.registry.ts +++ b/src/e2eTest/utils/registry/registry-caseManagement/action-caseManagement.registry.ts @@ -36,7 +36,9 @@ export class ActionCMRegistry { ['navigateToSummaryPage', new CaseManagementAction()], ['selectAnEvent', new CaseManagementAction()], ['selectDocumentToAmend', new CaseManagementAction()], + ['changeCaseState', new CaseManagementAction()], ['errorValidationSelectDocumentPage', new ErrorValidationAction()], + ['errorValidationChangeCaseStatePage', new ErrorValidationAction()], ['inputErrorValidation', new CaseManagementAction()], ['reTryOnCallBackError', new RetryOnCallBackError()], diff --git a/src/e2eTest/utils/validations/element-validations/pageContent.validation.ts b/src/e2eTest/utils/validations/element-validations/pageContent.validation.ts index c9eb07ec97..7594c6e49e 100644 --- a/src/e2eTest/utils/validations/element-validations/pageContent.validation.ts +++ b/src/e2eTest/utils/validations/element-validations/pageContent.validation.ts @@ -182,7 +182,10 @@ export class PageContentValidation implements IValidation { else if(page.url().includes("makeAnApplication")){ mappingPath = path.join(__dirname, '../../../data/page-data-figma/page-data-genApps-figma/urlToFileMappingGenApps.ts'); } - else if(page.url().includes("amendDocuments")){ + else if( + ["amendDocuments", "changeCaseState"].some(str => + page.url().includes(str) + )) { mappingPath = path.join(__dirname, '../../../data/page-data-figma/page-data-caseManagement-figma/urlToFileMappingCM.ts'); } else{ @@ -244,7 +247,10 @@ export class PageContentValidation implements IValidation { else if (page.url().includes("globalSearch")) { filePath = path.join(__dirname, '../../../data/page-data-figma/page-data-common-component', `${fileName}.page.data.ts`); } - else if (page.url().includes("amendDocuments")) { + else if ( + ["amendDocuments", "changeCaseState"].some(str => + page.url().includes(str) + )) { filePath = path.join(__dirname, '../../../data/page-data-figma/page-data-caseManagement-figma', `${fileName}.page.data.ts`); } else { @@ -383,9 +389,14 @@ export class PageContentValidation implements IValidation { mappingPath = path.join(__dirname, '../../../data/page-data-figma/page-data-enforcement-figma/urlToFileMappingEnforcement.ts'); } else if(url.includes("makeAnApplication")){ mappingPath = path.join(__dirname, '../../../data/page-data-figma/page-data-genApps-figma/urlToFileMappingGenApps.ts'); + } else if ( + ["amendDocuments", "changeCaseState"].some(str => + url.includes(str) + )) { + mappingPath = path.join(__dirname, '../../../data/page-data-figma/page-data-caseManagement-figma/urlToFileMappingCM.ts'); } - else{ - mappingPath = path.join(__dirname, '../../../data/page-data-figma/urlToFileMapping.ts'); + else { + mappingPath = path.join(__dirname, '../../../data/page-data-figma/urlToFileMapping.ts'); } if (!fs.existsSync(mappingPath)) return segment; const mappingContent = fs.readFileSync(mappingPath, 'utf8'); From 0781224ce331a8aa8cef6f172df25632052d83ee Mon Sep 17 00:00:00 2001 From: srinijg Date: Wed, 15 Jul 2026 13:25:19 +0100 Subject: [PATCH 55/70] confirm page update --- .../confirmCaseStateChange.page.data.ts | 7 +++++ .../page-data-caseManagement-figma/index.ts | 3 ++- .../urlToFileMappingCM.ts | 5 ++-- ...seManagement.caseWorkerChangeState.spec.ts | 5 +++- .../caseManagement.action.ts | 27 ++++++++++++++++--- .../action-caseManagement.registry.ts | 1 + 6 files changed, 41 insertions(+), 7 deletions(-) create mode 100644 src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/confirmCaseStateChange.page.data.ts diff --git a/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/confirmCaseStateChange.page.data.ts b/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/confirmCaseStateChange.page.data.ts new file mode 100644 index 0000000000..fbadec7f50 --- /dev/null +++ b/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/confirmCaseStateChange.page.data.ts @@ -0,0 +1,7 @@ +export const confirmCaseStateChange = { + mainHeader: `Change case state`, + changeCaseState: `Change case state`, + whatHappensNextHeader: `What happens next`, + theCaseWillParagraph: `The case will progress according to the state it has been changed to.`, + closeAndReturnToCaseOverviewButton: `Close and Return to case details`, +}; diff --git a/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/index.ts b/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/index.ts index 3bce9007b3..ab33b0a451 100644 --- a/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/index.ts +++ b/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/index.ts @@ -1,4 +1,5 @@ export * from './selectDocument.page.data'; export * from './amendDocumentDetails.page.data'; export * from './changeCaseState.page.data'; -export * from './checkYourAnswersChangeState.page.data' +export * from './checkYourAnswersChangeState.page.data'; +export * from './confirmCaseStateChange.page.data'; diff --git a/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/urlToFileMappingCM.ts b/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/urlToFileMappingCM.ts index 78ab0853b6..5ddbccf2cc 100644 --- a/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/urlToFileMappingCM.ts +++ b/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/urlToFileMappingCM.ts @@ -1,4 +1,5 @@ export default { 'amendDocumentsselectDocument': 'selectDocument', - 'changeCaseStatechangeCaseStatePage': 'changeCaseState' -}; + 'changeCaseStatechangeCaseStatePage': 'changeCaseState', + 'changeCaseState/confirm': 'confirmCaseStateChange' +}; \ No newline at end of file diff --git a/src/e2eTest/tests/test-caseManagement/caseManagement.caseWorkerChangeState.spec.ts b/src/e2eTest/tests/test-caseManagement/caseManagement.caseWorkerChangeState.spec.ts index f3c1d1137e..79d601ca28 100644 --- a/src/e2eTest/tests/test-caseManagement/caseManagement.caseWorkerChangeState.spec.ts +++ b/src/e2eTest/tests/test-caseManagement/caseManagement.caseWorkerChangeState.spec.ts @@ -50,6 +50,9 @@ test.describe('Case management - Case Worker change case state @nightly', async await performAction('changeCaseState', { question: changeCaseState.whichStateYouMovingCaseToQuestion, option: changeCaseState.caseStateHiddenOption, nextPage: checkYourAnswersChangeState.mainHeader - }); + }); + await performAction('clickButton', checkYourAnswersChangeState.submitButton); + await performAction('confirmCaseStateChange'); + await performValidation('bannerAlert', 'Case #.* has been updated with event: Change case state'); }); }); diff --git a/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagement.action.ts b/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagement.action.ts index c1fb9e1055..575091ed09 100644 --- a/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagement.action.ts +++ b/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagement.action.ts @@ -6,7 +6,8 @@ import { getCaseTypeId } from '@utils/common/caseType.utils'; import { performAction, performValidation } from '@utils/controller-caseManagement'; import { VERY_LONG_TIMEOUT } from 'playwright.config'; import { caseSummary, home } from '@data/page-data'; -import { changeCaseState, selectDocument } from '@data/page-data-figma/page-data-caseManagement-figma'; +import { changeCaseState, confirmCaseStateChange, selectDocument } from '@data/page-data-figma/page-data-caseManagement-figma'; +import { caseInfo } from '../createCaseAPI.action'; export const addressInfo = { @@ -25,6 +26,7 @@ export class CaseManagementAction implements IAction { ['selectAnEvent', () => this.selectAnEvent(fieldName as actionRecord)], ['selectDocumentToAmend', () => this.selectDocumentToAmend(fieldName as actionRecord)], ['changeCaseState', () => this.changeCaseState(fieldName as actionRecord)], + ['confirmCaseStateChange', () => this.confirmCaseStateChange()], ['inputErrorValidation', () => this.inputErrorValidation(page, fieldName as actionRecord)], ]); @@ -59,18 +61,37 @@ export class CaseManagementAction implements IAction { } private async changeCaseState(caseState: actionRecord){ + await performValidation('text', { elementType: 'paragraph', text: 'Case number: ' + caseInfo.fid }); + await performValidation('text', { + elementType: 'paragraph', + text: `Property address: ${addressInfo.buildingStreet}, ${addressInfo.townCity}, ${addressInfo.engOrWalPostcode}` + }); await performAction('select', caseState.question, caseState.option); await performAction('reTryOnCallBackError', changeCaseState.continueButton, caseState.nextPage as string); } + private async confirmCaseStateChange(): Promise { + await performValidation('text', { elementType: 'paragraph', text: 'Case number: ' + caseInfo.fid }); + await performValidation('text', { + elementType: 'paragraph', + text: `Property address: ${addressInfo.buildingStreet}, ${addressInfo.townCity}, ${addressInfo.engOrWalPostcode}` + }); + await performValidation('text', { elementType: 'inlineText', text: 'Case number: ' + caseInfo.fid }); + await performValidation('text', { + elementType: 'inlineText', + text: `Property address: ${addressInfo.buildingStreet}, ${addressInfo.townCity}, ${addressInfo.engOrWalPostcode}` + }); + await performValidation('mainHeader', confirmCaseStateChange.mainHeader); + await performAction('clickButton', confirmCaseStateChange.closeAndReturnToCaseOverviewButton); + } + private async inputErrorValidation(page: Page, validationArr: actionRecord) { if (Array.isArray(validationArr.inputArray)) { for (const item of validationArr.inputArray) { switch (validationArr.validationType) { - - + case 'radioOptions': await performAction('clickButton', validationArr.button); await performValidation('inputError', !validationArr?.label ? validationArr.question : validationArr.label, item.errInlineMessage); diff --git a/src/e2eTest/utils/registry/registry-caseManagement/action-caseManagement.registry.ts b/src/e2eTest/utils/registry/registry-caseManagement/action-caseManagement.registry.ts index 965532c77a..50cd3cacb7 100644 --- a/src/e2eTest/utils/registry/registry-caseManagement/action-caseManagement.registry.ts +++ b/src/e2eTest/utils/registry/registry-caseManagement/action-caseManagement.registry.ts @@ -37,6 +37,7 @@ export class ActionCMRegistry { ['selectAnEvent', new CaseManagementAction()], ['selectDocumentToAmend', new CaseManagementAction()], ['changeCaseState', new CaseManagementAction()], + ['confirmCaseStateChange', new CaseManagementAction()], ['errorValidationSelectDocumentPage', new ErrorValidationAction()], ['errorValidationChangeCaseStatePage', new ErrorValidationAction()], ['inputErrorValidation', new CaseManagementAction()], From 65e7651dc575341531913f48f4d70e00e8c8d6e2 Mon Sep 17 00:00:00 2001 From: srinijg Date: Thu, 16 Jul 2026 12:16:12 +0100 Subject: [PATCH 56/70] conflicts resolved --- .../caseManagement.manageDocuments.spec.ts | 56 --- .../ClaimFormPersistenceServiceIT.java | 19 +- .../pcs/ccd/domain/CaseFileCategory.java | 10 +- .../hmcts/reform/pcs/ccd/domain/PCSCase.java | 5 +- .../documentamend/DocumentAmendDetails.java | 139 ------- .../reform/pcs/ccd/event/AmendDocuments.java | 59 --- .../hmcts/reform/pcs/ccd/event/EventId.java | 1 - .../AmendDocumentDetailsPlaceholderPage.java | 20 - .../documentamend/DocumentCategoryField.java | 79 ---- .../documentamend/SelectDocumentPage.java | 114 ------ .../service/DefendantAccessCodeService.java | 4 +- .../DocumentAmendSelectionService.java | 178 --------- .../ccd/service/document/DocumentService.java | 22 +- ...efault_uncategorised_document_category.sql | 9 - .../ccd/accesscontrol/AccessProfileTest.java | 14 +- .../DefendantAccessCodeServiceTest.java | 5 +- .../ccd/service/DraftCaseJsonMergerTest.java | 1 - .../DocumentAmendSelectionServiceTest.java | 349 ------------------ .../service/document/DocumentServiceTest.java | 11 +- 19 files changed, 25 insertions(+), 1070 deletions(-) delete mode 100644 src/e2eTest/tests/test-caseManagement/caseManagement.manageDocuments.spec.ts delete mode 100644 src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendDetails.java delete mode 100644 src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/AmendDocuments.java delete mode 100644 src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/AmendDocumentDetailsPlaceholderPage.java delete mode 100644 src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/DocumentCategoryField.java delete mode 100644 src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java delete mode 100644 src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionService.java delete mode 100644 src/main/resources/db/migration/V135__default_uncategorised_document_category.sql delete mode 100644 src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java diff --git a/src/e2eTest/tests/test-caseManagement/caseManagement.manageDocuments.spec.ts b/src/e2eTest/tests/test-caseManagement/caseManagement.manageDocuments.spec.ts deleted file mode 100644 index bd8ae4a657..0000000000 --- a/src/e2eTest/tests/test-caseManagement/caseManagement.manageDocuments.spec.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { createCaseApiData, makeAnApplicationApiData, submitCaseApiData } from '@data/api-data'; -import { initializeExecutor, performValidation } from '@utils/controller'; -import test from '@playwright/test'; -import { caseInfo, defendantUserDetails } from '@utils/actions/custom-actions'; -import { PageContentValidation } from '@utils/validations/element-validations/pageContent.validation'; -import { caseSummary, user } from '@data/page-data'; -import { dismissCookieBanner } from '@config/cookie-banner'; -import { initializeCMExecutor, performAction } from '@utils/controller-caseManagement'; -import { amendDocumentDetails, selectDocument } from '@data/page-data-figma/page-data-caseManagement-figma'; - -test.use({ storageState: undefined }) - -test.beforeEach(async ({ page, context }) => { - await context.clearCookies(); - initializeExecutor(page); - initializeCMExecutor(page); - await performAction('createCaseAPI', { data: createCaseApiData.createCasePayload }); - await performAction('submitCaseAPI', { data: submitCaseApiData.submitCasePayloadCaseFileView }); - await performAction('updatePaymentAPI'); - await performAction('getCaseAPI', 'Link Solicitor'); - - for (const defendant of defendantUserDetails) { - await performAction('makeAnApplicationAPI', { - data: makeAnApplicationApiData.makeAnApplicationAdjournPayload( - defendant.id, - defendant.name - ), - }); - }; - await performAction('navigateToUrl', process.env.MANAGE_CASE_BASE_URL); - await dismissCookieBanner(page, 'additional'); - await performAction('login', user.staffAdmin); - await dismissCookieBanner(page, 'analytics'); - await performAction('navigateToSummaryPage'); -}); - -test.afterEach(async () => { - if (caseInfo.id) { - await performAction('deleteCaseRole', '[CLAIMANTSOLICITOR]'); - } - PageContentValidation.finaliseTest(); - -}); - -test.describe('Case management - Manage documents e2e Journey @nightly', async () => { - test('Case management - Manage documents - Amend @CM @regression', async () => { - await performAction('selectAnEvent', { eventType: caseSummary.manageDocuments.amend }); - await performValidation('mainHeader', selectDocument.mainHeader); - await performAction('errorValidationSelectDocumentPage', selectDocument.errorValidation); - await performAction('selectDocumentToAmend', { - question: selectDocument.whichFolderQuestion, option: selectDocument.docFolderHiddenOption, - question1: selectDocument.documentToAmendHiddenQuestion, option1: selectDocument.typeOfDocumentHiddenRadioOption, - nextPage: amendDocumentDetails.mainHeader - }); - }); -}); diff --git a/src/integrationTest/java/uk/gov/hmcts/reform/pcs/controllers/ClaimFormPersistenceServiceIT.java b/src/integrationTest/java/uk/gov/hmcts/reform/pcs/controllers/ClaimFormPersistenceServiceIT.java index bb6af322f6..d11d0522bc 100644 --- a/src/integrationTest/java/uk/gov/hmcts/reform/pcs/controllers/ClaimFormPersistenceServiceIT.java +++ b/src/integrationTest/java/uk/gov/hmcts/reform/pcs/controllers/ClaimFormPersistenceServiceIT.java @@ -9,7 +9,6 @@ import org.springframework.test.context.bean.override.mockito.MockitoBean; import uk.gov.hmcts.reform.authorisation.generators.AuthTokenGenerator; import uk.gov.hmcts.reform.ccd.client.CaseAssignmentApi; -import uk.gov.hmcts.reform.pcs.ccd.domain.CaseFileCategory; import uk.gov.hmcts.reform.pcs.ccd.entity.DocumentEntity; import uk.gov.hmcts.reform.pcs.ccd.entity.PcsCaseEntity; import uk.gov.hmcts.reform.pcs.ccd.entity.party.PartyRole; @@ -70,7 +69,7 @@ void documentRolledBackWhenActivityLogWriteFails() { final PcsCaseEntity caseEntity = caseCreationHelper.createTestCaseWithParty( caseReference, UUID.randomUUID(), PartyRole.CLAIMANT); when(documentImportService.addDocumentToCase(eq(caseReference), anyString(), any())) - .thenReturn(importedDocument()); + .thenReturn(DocumentEntity.builder().documentId(UUID.randomUUID()).build()); doThrow(new RuntimeException("activity log write failed")) .when(claimActivityLogService).logGenerationSuccess(caseReference); @@ -89,22 +88,12 @@ void attachesDocumentAndRecordsGenerationSuccess() { final PcsCaseEntity caseEntity = caseCreationHelper.createTestCaseWithParty( caseReference, UUID.randomUUID(), PartyRole.CLAIMANT); when(documentImportService.addDocumentToCase(eq(caseReference), anyString(), any())) - .thenReturn(importedDocument()); + .thenReturn(DocumentEntity.builder().documentId(UUID.randomUUID()).build()); claimFormPersistenceService.attach(caseReference, DM_STORE_URL); UUID claimId = caseEntity.getClaims().getFirst().getId(); - assertThat(claimRepository.findById(claimId).orElseThrow().getClaimFormDocument()) - .isNotNull() - .extracting(DocumentEntity::getCategoryId) - .isEqualTo(CaseFileCategory.STATEMENTS_OF_CASE.getId()); + assertThat(claimRepository.findById(claimId).orElseThrow().getClaimFormDocument()).isNotNull(); verify(claimActivityLogService).logGenerationSuccess(caseReference); } - - private static DocumentEntity importedDocument() { - return DocumentEntity.builder() - .documentId(UUID.randomUUID()) - .categoryId(CaseFileCategory.STATEMENTS_OF_CASE.getId()) - .build(); - } -} +} \ No newline at end of file diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/CaseFileCategory.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/CaseFileCategory.java index 037290f7fc..7ac092e7df 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/CaseFileCategory.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/CaseFileCategory.java @@ -2,23 +2,21 @@ import lombok.AllArgsConstructor; import lombok.Getter; -import uk.gov.hmcts.ccd.sdk.api.HasLabel; @AllArgsConstructor @Getter -public enum CaseFileCategory implements HasLabel { +public enum CaseFileCategory { STATEMENTS_OF_CASE("statementsOfCase", "Statements of case", 1), PROPERTY_DOCUMENTS("propertyDocuments", "Property documents", 2), EVIDENCE("evidence", "Evidence", 3), HEARING_DOCUMENTS("hearingDocuments", "Hearing documents", 4), - ORDERS_AND_NOTICE_OF_HEARINGS("ordersAndNoticeOfHearings", "Orders and Notice of Hearings", 5), + ORDERS_AND_NOTICE_OF_HEARINGS("ordersAndNoticeOfHearings", "Orders and notice of hearings", 5), APPLICATIONS("applications", "Applications", 6), APPEALS("appeals", "Appeals", 7), - CORRESPONDENCE("correspondence", "Correspondence", 8), - UNCATEGORISED_DOCUMENTS("uncategorisedDocuments", "Uncategorised documents", 9); + CORRESPONDENCE("correspondence", "Correspondence", 8); private final String id; private final String label; private final int displayOrder; -} +} \ No newline at end of file diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/PCSCase.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/PCSCase.java index 3d43c1b560..e9f8dc7e7a 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/PCSCase.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/PCSCase.java @@ -482,9 +482,6 @@ public class PCSCase { @JsonUnwrapped private DocumentUploadDetails documentUploadDetails; - @JsonUnwrapped(prefix = "documentAmend_") - private DocumentAmendDetails documentAmendDetails; - @CCD( label = "Are you planning to make an application at the same time as your claim?", hint = "After you’ve submitted your claim, there will be instructions on how to make an application" @@ -732,4 +729,4 @@ public class PCSCase { typeParameterOverride = "CaseStateOption" ) private CaseStateOption targetState; -} +} \ No newline at end of file diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendDetails.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendDetails.java deleted file mode 100644 index bd0f751490..0000000000 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendDetails.java +++ /dev/null @@ -1,139 +0,0 @@ -package uk.gov.hmcts.reform.pcs.ccd.domain.documentamend; - -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonInclude.Include; -import com.fasterxml.jackson.databind.PropertyNamingStrategies; -import com.fasterxml.jackson.databind.annotation.JsonNaming; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; -import uk.gov.hmcts.ccd.sdk.api.CCD; -import uk.gov.hmcts.reform.pcs.ccd.domain.CaseFileCategory; -import uk.gov.hmcts.ccd.sdk.type.DynamicList; -import uk.gov.hmcts.ccd.sdk.type.YesOrNo; - -import static uk.gov.hmcts.ccd.sdk.type.FieldType.DynamicRadioList; -import static uk.gov.hmcts.ccd.sdk.type.FieldType.FixedList; - -@Builder -@Data -@NoArgsConstructor -@AllArgsConstructor -@JsonInclude(Include.NON_NULL) -@JsonNaming(PropertyNamingStrategies.UpperCamelCaseStrategy.class) -public class DocumentAmendDetails { - - @CCD( - label = "Which folder is the document in?", - searchable = false, - typeOverride = FixedList, - typeParameterOverride = "CaseFileCategory" - ) - private CaseFileCategory selectedFolder; - - @CCD(searchable = false) - private String propertyAddressSummary; - - @CCD( - label = "Which document do you want to amend?", - searchable = false, - typeOverride = DynamicRadioList - ) - private DynamicList statementsOfCaseDocuments; - - @CCD( - label = "Which document do you want to amend?", - searchable = false, - typeOverride = DynamicRadioList - ) - private DynamicList propertyDocuments; - - @CCD( - label = "Which document do you want to amend?", - searchable = false, - typeOverride = DynamicRadioList - ) - private DynamicList evidenceDocuments; - - @CCD( - label = "Which document do you want to amend?", - searchable = false, - typeOverride = DynamicRadioList - ) - private DynamicList hearingDocuments; - - @CCD( - label = "Which document do you want to amend?", - searchable = false, - typeOverride = DynamicRadioList - ) - private DynamicList ordersAndNoticeOfHearingsDocuments; - - @CCD( - label = "Which document do you want to amend?", - searchable = false, - typeOverride = DynamicRadioList - ) - private DynamicList applicationsDocuments; - - @CCD( - label = "Which document do you want to amend?", - searchable = false, - typeOverride = DynamicRadioList - ) - private DynamicList appealsDocuments; - - @CCD( - label = "Which document do you want to amend?", - searchable = false, - typeOverride = DynamicRadioList - ) - private DynamicList correspondenceDocuments; - - @CCD( - label = "Which document do you want to amend?", - searchable = false, - typeOverride = DynamicRadioList - ) - private DynamicList uncategorisedDocuments; - - @CCD(searchable = false) - private YesOrNo statementsOfCaseEmpty; - - @CCD(searchable = false) - private YesOrNo propertyDocumentsEmpty; - - @CCD(searchable = false) - private YesOrNo evidenceEmpty; - - @CCD(searchable = false) - private YesOrNo hearingDocumentsEmpty; - - @CCD(searchable = false) - private YesOrNo ordersAndNoticeOfHearingsEmpty; - - @CCD(searchable = false) - private YesOrNo applicationsEmpty; - - @CCD(searchable = false) - private YesOrNo appealsEmpty; - - @CCD(searchable = false) - private YesOrNo correspondenceEmpty; - - @CCD(searchable = false) - private YesOrNo uncategorisedDocumentsEmpty; - - @CCD(searchable = false) - private String selectedFolderId; - - @CCD(searchable = false) - private String selectedFolderLabel; - - @CCD(searchable = false) - private String selectedDocumentId; - - @CCD(searchable = false) - private String selectedDocumentFileName; -} diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/AmendDocuments.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/AmendDocuments.java deleted file mode 100644 index 2893ae7a00..0000000000 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/AmendDocuments.java +++ /dev/null @@ -1,59 +0,0 @@ -package uk.gov.hmcts.reform.pcs.ccd.event; - -import lombok.AllArgsConstructor; -import org.springframework.stereotype.Component; -import uk.gov.hmcts.ccd.sdk.api.CCDConfig; -import uk.gov.hmcts.ccd.sdk.api.DecentralisedConfigBuilder; -import uk.gov.hmcts.ccd.sdk.api.Event; -import uk.gov.hmcts.ccd.sdk.api.EventPayload; -import uk.gov.hmcts.ccd.sdk.api.Permission; -import uk.gov.hmcts.ccd.sdk.api.callback.SubmitResponse; -import uk.gov.hmcts.reform.pcs.ccd.accesscontrol.UserRole; -import uk.gov.hmcts.reform.pcs.ccd.common.PageBuilder; -import uk.gov.hmcts.reform.pcs.ccd.domain.PCSCase; -import uk.gov.hmcts.reform.pcs.ccd.domain.State; -import uk.gov.hmcts.reform.pcs.ccd.page.documentamend.AmendDocumentDetailsPlaceholderPage; -import uk.gov.hmcts.reform.pcs.ccd.page.documentamend.SelectDocumentPage; -import uk.gov.hmcts.reform.pcs.ccd.service.document.DocumentAmendSelectionService; - -import static uk.gov.hmcts.reform.pcs.ccd.event.EventId.amendDocuments; - -@Component -@AllArgsConstructor -public class AmendDocuments implements CCDConfig { - - private final DocumentAmendSelectionService documentAmendSelectionService; - private final SelectDocumentPage selectDocumentPage; - private final AmendDocumentDetailsPlaceholderPage amendDocumentDetailsPlaceholderPage; - - @Override - public void configureDecentralised(DecentralisedConfigBuilder configBuilder) { - Event.EventBuilder eventBuilder = - configBuilder - .decentralisedEvent(amendDocuments.name(), this::submit, this::start) - .forStates(State.CASE_ISSUED) - .name("Manage documents: Amend") - .grant(Permission.CRU, UserRole.CTSC_ADMIN) - .grant(Permission.CRU, UserRole.WLU_ADMIN) - .grant(Permission.CRU, UserRole.HEARING_CENTRE_ADMIN) - .grant(Permission.CRU, UserRole.JUDGE) - .grant(Permission.CRU, UserRole.CIRCUIT_JUDGE) - .grant(Permission.CRU, UserRole.FEE_PAID_JUDGE) - .grant(Permission.CRU, UserRole.LEADERSHIP_JUDGE) - .endButtonLabel("Submit"); - - PageBuilder pageBuilder = new PageBuilder(eventBuilder); - selectDocumentPage.addTo(pageBuilder); - amendDocumentDetailsPlaceholderPage.addTo(pageBuilder); - } - - private PCSCase start(EventPayload eventPayload) { - PCSCase caseData = eventPayload.caseData(); - documentAmendSelectionService.initialise(eventPayload.caseReference(), caseData); - return caseData; - } - - private SubmitResponse submit(EventPayload eventPayload) { - return SubmitResponse.defaultResponse(); - } -} diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/EventId.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/EventId.java index fae47b205b..109456c49b 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/EventId.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/EventId.java @@ -15,7 +15,6 @@ public enum EventId { dashboardView, confirmEviction, uploadDocuments, - amendDocuments, addCaseNote, createFlags, amendFlags, diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/AmendDocumentDetailsPlaceholderPage.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/AmendDocumentDetailsPlaceholderPage.java deleted file mode 100644 index 4414252a4d..0000000000 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/AmendDocumentDetailsPlaceholderPage.java +++ /dev/null @@ -1,20 +0,0 @@ -package uk.gov.hmcts.reform.pcs.ccd.page.documentamend; - -import org.springframework.stereotype.Component; -import uk.gov.hmcts.reform.pcs.ccd.common.CcdPageConfiguration; -import uk.gov.hmcts.reform.pcs.ccd.common.PageBuilder; - -@Component -public class AmendDocumentDetailsPlaceholderPage implements CcdPageConfiguration { - - @Override - public void addTo(PageBuilder pageBuilder) { - pageBuilder - .page("amendDocumentDetails") - .pageLabel("Amend document details") - .label("amendDocumentDetails-selectedDocument", """ - --- - Selected document: ${documentAmend_SelectedDocumentFileName} - """); - } -} diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/DocumentCategoryField.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/DocumentCategoryField.java deleted file mode 100644 index f00bd1792c..0000000000 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/DocumentCategoryField.java +++ /dev/null @@ -1,79 +0,0 @@ -package uk.gov.hmcts.reform.pcs.ccd.page.documentamend; - -import uk.gov.hmcts.ccd.sdk.api.TypedPropertyGetter; -import uk.gov.hmcts.ccd.sdk.type.DynamicList; -import uk.gov.hmcts.ccd.sdk.type.YesOrNo; -import uk.gov.hmcts.reform.pcs.ccd.domain.CaseFileCategory; -import uk.gov.hmcts.reform.pcs.ccd.domain.documentamend.DocumentAmendDetails; - -enum DocumentCategoryField { - STATEMENTS_OF_CASE( - CaseFileCategory.STATEMENTS_OF_CASE, - "statementsOfCase", - DocumentAmendDetails::getStatementsOfCaseDocuments, - DocumentAmendDetails::getStatementsOfCaseEmpty - ), - PROPERTY_DOCUMENTS( - CaseFileCategory.PROPERTY_DOCUMENTS, - "propertyDocuments", - DocumentAmendDetails::getPropertyDocuments, - DocumentAmendDetails::getPropertyDocumentsEmpty - ), - EVIDENCE( - CaseFileCategory.EVIDENCE, - "evidence", - DocumentAmendDetails::getEvidenceDocuments, - DocumentAmendDetails::getEvidenceEmpty - ), - HEARING_DOCUMENTS( - CaseFileCategory.HEARING_DOCUMENTS, - "hearingDocuments", - DocumentAmendDetails::getHearingDocuments, - DocumentAmendDetails::getHearingDocumentsEmpty - ), - ORDERS_AND_NOTICE_OF_HEARINGS( - CaseFileCategory.ORDERS_AND_NOTICE_OF_HEARINGS, - "ordersAndNoticeOfHearings", - DocumentAmendDetails::getOrdersAndNoticeOfHearingsDocuments, - DocumentAmendDetails::getOrdersAndNoticeOfHearingsEmpty - ), - APPLICATIONS( - CaseFileCategory.APPLICATIONS, - "applications", - DocumentAmendDetails::getApplicationsDocuments, - DocumentAmendDetails::getApplicationsEmpty - ), - APPEALS( - CaseFileCategory.APPEALS, - "appeals", - DocumentAmendDetails::getAppealsDocuments, - DocumentAmendDetails::getAppealsEmpty - ), - CORRESPONDENCE( - CaseFileCategory.CORRESPONDENCE, - "correspondence", - DocumentAmendDetails::getCorrespondenceDocuments, - DocumentAmendDetails::getCorrespondenceEmpty - ), - UNCATEGORISED_DOCUMENTS( - CaseFileCategory.UNCATEGORISED_DOCUMENTS, - "uncategorisedDocuments", - DocumentAmendDetails::getUncategorisedDocuments, - DocumentAmendDetails::getUncategorisedDocumentsEmpty - ); - - final CaseFileCategory category; - final String idPrefix; - final TypedPropertyGetter documentsGetter; - final TypedPropertyGetter emptyGetter; - - DocumentCategoryField(CaseFileCategory category, - String idPrefix, - TypedPropertyGetter documentsGetter, - TypedPropertyGetter emptyGetter) { - this.category = category; - this.idPrefix = idPrefix; - this.documentsGetter = documentsGetter; - this.emptyGetter = emptyGetter; - } -} diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java deleted file mode 100644 index c15e9da9aa..0000000000 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/SelectDocumentPage.java +++ /dev/null @@ -1,114 +0,0 @@ -package uk.gov.hmcts.reform.pcs.ccd.page.documentamend; - -import lombok.AllArgsConstructor; -import org.springframework.stereotype.Component; -import uk.gov.hmcts.ccd.sdk.api.CaseDetails; -import uk.gov.hmcts.ccd.sdk.api.FieldCollection.FieldCollectionBuilder; -import uk.gov.hmcts.ccd.sdk.api.callback.AboutToStartOrSubmitResponse; -import uk.gov.hmcts.reform.pcs.ccd.common.CcdPageConfiguration; -import uk.gov.hmcts.reform.pcs.ccd.common.PageBuilder; -import uk.gov.hmcts.reform.pcs.ccd.domain.CaseFileCategory; -import uk.gov.hmcts.reform.pcs.ccd.domain.PCSCase; -import uk.gov.hmcts.reform.pcs.ccd.domain.State; -import uk.gov.hmcts.reform.pcs.ccd.domain.documentamend.DocumentAmendDetails; -import uk.gov.hmcts.reform.pcs.ccd.service.document.DocumentAmendSelectionService; -import uk.gov.hmcts.reform.pcs.ccd.util.StringUtils; - -import java.util.List; - -import static uk.gov.hmcts.reform.pcs.ccd.ShowConditions.NEVER_SHOW; - -@AllArgsConstructor -@Component -public class SelectDocumentPage implements CcdPageConfiguration { - - private static final String PAGE_ID = "selectDocument"; - private static final String FIELD_PREFIX = "documentAmend_"; - private static final String YES = "=\"Yes\""; - private static final String NO = "=\"No\""; - private final DocumentAmendSelectionService documentAmendSelectionService; - - @Override - public void addTo(PageBuilder pageBuilder) { - FieldCollectionBuilder documentAmendPage = pageBuilder - .page(PAGE_ID, this::midEvent) - .pageLabel("Select document") - .label(PAGE_ID + "-separator", "---") - .complex(PCSCase::getDocumentAmendDetails) - .readonly(DocumentAmendDetails::getPropertyAddressSummary, NEVER_SHOW, true) - .mandatory(DocumentAmendDetails::getSelectedFolder) - .label("emptyFolderDocumentError", "", NEVER_SHOW) - .label("selectedFolderEmptyErrorMessage", "", NEVER_SHOW) - .label("emptyFolderDocumentQuestion", "", NEVER_SHOW); - - for (DocumentCategoryField categoryField : DocumentCategoryField.values()) { - addCategoryFields(documentAmendPage, categoryField); - } - - for (DocumentCategoryField categoryField : DocumentCategoryField.values()) { - documentAmendPage.readonly(categoryField.emptyGetter, NEVER_SHOW, true); - } - - documentAmendPage - .readonly(DocumentAmendDetails::getSelectedFolderId, NEVER_SHOW, true) - .readonly(DocumentAmendDetails::getSelectedFolderLabel, NEVER_SHOW, true) - .readonly(DocumentAmendDetails::getSelectedDocumentId, NEVER_SHOW, true) - .readonly(DocumentAmendDetails::getSelectedDocumentFileName, NEVER_SHOW, true) - .done(); - } - - private void addCategoryFields(FieldCollectionBuilder page, - DocumentCategoryField categoryField) { - CaseFileCategory category = categoryField.category; - page - .label(categoryField.idPrefix + "EmptyFolderMessage", emptyFolderMessage(category), - noDocumentsShowCondition(category)) - .mandatory(categoryField.documentsGetter, documentsShowCondition(category), true); - } - - private AboutToStartOrSubmitResponse midEvent(CaseDetails details, - CaseDetails detailsBefore) { - PCSCase caseData = details.getData(); - - documentAmendSelectionService.initialise(details.getId(), caseData); - List errors = documentAmendSelectionService.validateAndStoreSelection(caseData); - - return AboutToStartOrSubmitResponse.builder() - .data(caseData) - .errorMessageOverride(StringUtils.joinIfNotEmpty("\n", errors)) - .build(); - } - - private String documentsShowCondition(CaseFileCategory category) { - return selectedFolderCondition(category) + " AND " + emptyFieldId(category) + NO; - } - - private String noDocumentsShowCondition(CaseFileCategory category) { - return selectedFolderCondition(category) + " AND " + emptyFieldId(category) + YES; - } - - private String selectedFolderCondition(CaseFileCategory category) { - return FIELD_PREFIX + "SelectedFolder=\"" + category.name() + "\""; - } - - private String emptyFieldId(CaseFileCategory category) { - return switch (category) { - case STATEMENTS_OF_CASE -> FIELD_PREFIX + "StatementsOfCaseEmpty"; - case PROPERTY_DOCUMENTS -> FIELD_PREFIX + "PropertyDocumentsEmpty"; - case EVIDENCE -> FIELD_PREFIX + "EvidenceEmpty"; - case HEARING_DOCUMENTS -> FIELD_PREFIX + "HearingDocumentsEmpty"; - case ORDERS_AND_NOTICE_OF_HEARINGS -> FIELD_PREFIX + "OrdersAndNoticeOfHearingsEmpty"; - case APPLICATIONS -> FIELD_PREFIX + "ApplicationsEmpty"; - case APPEALS -> FIELD_PREFIX + "AppealsEmpty"; - case CORRESPONDENCE -> FIELD_PREFIX + "CorrespondenceEmpty"; - case UNCATEGORISED_DOCUMENTS -> FIELD_PREFIX + "UncategorisedDocumentsEmpty"; - }; - } - - private String emptyFolderMessage(CaseFileCategory category) { - return "Which document do you want to amend?" - + "
" - + "No documents in '" + category.getLabel() + "'"; - } - -} diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/DefendantAccessCodeService.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/DefendantAccessCodeService.java index a4c7a21435..ac9b9c3621 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/DefendantAccessCodeService.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/DefendantAccessCodeService.java @@ -4,7 +4,6 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import uk.gov.hmcts.reform.pcs.ccd.domain.CaseFileCategory; import uk.gov.hmcts.reform.pcs.ccd.domain.DocumentType; import uk.gov.hmcts.reform.pcs.ccd.domain.claimactivitylog.ClaimActivityType; import uk.gov.hmcts.reform.pcs.ccd.domain.claimactivitylog.GenerationDetails; @@ -90,7 +89,6 @@ public void generateForDefendant(long caseReference, UUID defendantPartyId, .url(documentUrl) .documentId(documentIdExtractor.extractDocumentId(documentUrl)) .type(DocumentType.DEFENDANT_ACCESS_CODE) - .categoryId(CaseFileCategory.UNCATEGORISED_DOCUMENTS.getId()) .build() ); @@ -153,4 +151,4 @@ private static ClaimEntity getMainClaim(PcsCaseEntity pcsCaseEntity) { .findFirst() .orElseThrow(() -> new ClaimNotFoundException(pcsCaseEntity.getCaseReference())); } -} +} \ No newline at end of file diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionService.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionService.java deleted file mode 100644 index 3cfbd8e8cc..0000000000 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionService.java +++ /dev/null @@ -1,178 +0,0 @@ -package uk.gov.hmcts.reform.pcs.ccd.service.document; - -import org.springframework.stereotype.Service; -import org.springframework.util.CollectionUtils; -import uk.gov.hmcts.ccd.sdk.type.DynamicList; -import uk.gov.hmcts.ccd.sdk.type.DynamicListElement; -import uk.gov.hmcts.ccd.sdk.type.YesOrNo; -import uk.gov.hmcts.reform.pcs.ccd.domain.CaseFileCategory; -import uk.gov.hmcts.reform.pcs.ccd.domain.DocumentType; -import uk.gov.hmcts.reform.pcs.ccd.domain.PCSCase; -import uk.gov.hmcts.reform.pcs.ccd.domain.documentamend.DocumentAmendDetails; -import uk.gov.hmcts.reform.pcs.ccd.entity.DocumentEntity; -import uk.gov.hmcts.reform.pcs.ccd.entity.PcsCaseEntity; -import uk.gov.hmcts.reform.pcs.ccd.service.PcsCaseService; -import uk.gov.hmcts.reform.pcs.ccd.util.AddressFormatter; - -import java.util.Comparator; -import java.util.List; -import java.util.Objects; - -import static uk.gov.hmcts.reform.pcs.ccd.util.AddressFormatter.COMMA_DELIMITER; - -@Service -public class DocumentAmendSelectionService { - - public static final String SELECT_DIFFERENT_FOLDER_ERROR = "Select a different folder to continue"; - private static final Comparator DOCUMENT_ORDER = Comparator - .comparing(DocumentEntity::getSubmittedDate, Comparator.nullsLast(Comparator.reverseOrder())) - .thenComparing(DocumentEntity::getFileName, Comparator.nullsLast(String::compareToIgnoreCase)); - - private final PcsCaseService pcsCaseService; - private final AddressFormatter addressFormatter; - - public DocumentAmendSelectionService(PcsCaseService pcsCaseService, AddressFormatter addressFormatter) { - this.pcsCaseService = pcsCaseService; - this.addressFormatter = addressFormatter; - } - - public void initialise(long caseReference, PCSCase caseData) { - DocumentAmendDetails details = getOrCreateDetails(caseData); - PcsCaseEntity pcsCase = pcsCaseService.loadCase(caseReference); - - details.setPropertyAddressSummary(addressFormatter.formatShortAddress(caseData.getPropertyAddress(), - COMMA_DELIMITER)); - for (CaseFileCategory category : CaseFileCategory.values()) { - setDocumentsForCategory(details, pcsCase, category); - } - } - - public List validateAndStoreSelection(PCSCase caseData) { - DocumentAmendDetails details = caseData.getDocumentAmendDetails(); - if (details == null || details.getSelectedFolder() == null) { - return List.of(); - } - - CaseFileCategory selectedFolder = details.getSelectedFolder(); - DynamicList selectedDocuments = documentsForCategory(details, selectedFolder); - details.setSelectedFolderId(selectedFolder.getId()); - details.setSelectedFolderLabel(selectedFolder.getLabel()); - - if (isEmpty(selectedDocuments)) { - details.setSelectedDocumentId(null); - details.setSelectedDocumentFileName(null); - return List.of(SELECT_DIFFERENT_FOLDER_ERROR); - } - - DynamicListElement selectedDocument = selectedDocuments.getValue(); - if (selectedDocument == null || selectedDocument.getCode() == null) { - details.setSelectedDocumentId(null); - details.setSelectedDocumentFileName(null); - return List.of(); - } - - details.setSelectedDocumentId(selectedDocument.getCode().toString()); - details.setSelectedDocumentFileName(selectedDocument.getLabel()); - return List.of(); - } - - private void setDocumentsForCategory(DocumentAmendDetails details, PcsCaseEntity pcsCase, - CaseFileCategory category) { - DynamicList documents = documentList(pcsCase, category, documentsForCategory(details, category)); - applyDocumentsForCategory(details, category, documents); - setEmptyForCategory(details, category, YesOrNo.from(isEmpty(documents))); - } - - private DynamicList documentList(PcsCaseEntity pcsCase, CaseFileCategory category, - DynamicList existingList) { - DynamicListElement selected = existingList == null ? null : existingList.getValue(); - - List documents = CollectionUtils.isEmpty(pcsCase.getDocuments()) - ? List.of() - : pcsCase.getDocuments().stream() - .filter(Objects::nonNull) - .filter(document -> isInCategory(document, category)) - .filter(document -> document.getType() != DocumentType.DEFENDANT_ACCESS_CODE) - .sorted(DOCUMENT_ORDER) - .map(document -> DynamicListElement.builder() - .code(document.getId()) - .label(document.getFileName()) - .build()) - .toList(); - - return DynamicList.builder() - .value(retainSelectedValue(selected, documents)) - .listItems(documents) - .build(); - } - - private boolean isInCategory(DocumentEntity document, CaseFileCategory category) { - return category.getId().equals(document.getCategoryId()); - } - - private DynamicListElement retainSelectedValue(DynamicListElement selected, - List options) { - if (selected == null || selected.getCode() == null) { - return null; - } - - return options.stream() - .filter(option -> selected.getCode().toString().equals(option.getCode().toString())) - .findFirst() - .orElse(null); - } - - private boolean isEmpty(DynamicList documents) { - return documents == null || CollectionUtils.isEmpty(documents.getListItems()); - } - - private DocumentAmendDetails getOrCreateDetails(PCSCase caseData) { - if (caseData.getDocumentAmendDetails() == null) { - caseData.setDocumentAmendDetails(new DocumentAmendDetails()); - } - return caseData.getDocumentAmendDetails(); - } - - private DynamicList documentsForCategory(DocumentAmendDetails details, CaseFileCategory category) { - return switch (category) { - case STATEMENTS_OF_CASE -> details.getStatementsOfCaseDocuments(); - case PROPERTY_DOCUMENTS -> details.getPropertyDocuments(); - case EVIDENCE -> details.getEvidenceDocuments(); - case HEARING_DOCUMENTS -> details.getHearingDocuments(); - case ORDERS_AND_NOTICE_OF_HEARINGS -> details.getOrdersAndNoticeOfHearingsDocuments(); - case APPLICATIONS -> details.getApplicationsDocuments(); - case APPEALS -> details.getAppealsDocuments(); - case CORRESPONDENCE -> details.getCorrespondenceDocuments(); - case UNCATEGORISED_DOCUMENTS -> details.getUncategorisedDocuments(); - }; - } - - private void applyDocumentsForCategory(DocumentAmendDetails details, CaseFileCategory category, - DynamicList documents) { - switch (category) { - case STATEMENTS_OF_CASE -> details.setStatementsOfCaseDocuments(documents); - case PROPERTY_DOCUMENTS -> details.setPropertyDocuments(documents); - case EVIDENCE -> details.setEvidenceDocuments(documents); - case HEARING_DOCUMENTS -> details.setHearingDocuments(documents); - case ORDERS_AND_NOTICE_OF_HEARINGS -> details.setOrdersAndNoticeOfHearingsDocuments(documents); - case APPLICATIONS -> details.setApplicationsDocuments(documents); - case APPEALS -> details.setAppealsDocuments(documents); - case CORRESPONDENCE -> details.setCorrespondenceDocuments(documents); - case UNCATEGORISED_DOCUMENTS -> details.setUncategorisedDocuments(documents); - } - } - - private void setEmptyForCategory(DocumentAmendDetails details, CaseFileCategory category, YesOrNo empty) { - switch (category) { - case STATEMENTS_OF_CASE -> details.setStatementsOfCaseEmpty(empty); - case PROPERTY_DOCUMENTS -> details.setPropertyDocumentsEmpty(empty); - case EVIDENCE -> details.setEvidenceEmpty(empty); - case HEARING_DOCUMENTS -> details.setHearingDocumentsEmpty(empty); - case ORDERS_AND_NOTICE_OF_HEARINGS -> details.setOrdersAndNoticeOfHearingsEmpty(empty); - case APPLICATIONS -> details.setApplicationsEmpty(empty); - case APPEALS -> details.setAppealsEmpty(empty); - case CORRESPONDENCE -> details.setCorrespondenceEmpty(empty); - case UNCATEGORISED_DOCUMENTS -> details.setUncategorisedDocumentsEmpty(empty); - } - } -} diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentService.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentService.java index f388779e6b..ca12664dad 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentService.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentService.java @@ -53,7 +53,6 @@ public class DocumentService { private final DocumentNameService documentNameService; private static final String CLAIMANT_1 = "Claimant 1"; - private static final String DEFAULT_CATEGORY_ID = CaseFileCategory.UNCATEGORISED_DOCUMENTS.getId(); public List createAllDocuments(PCSCase pcsCase) { @@ -188,7 +187,9 @@ private List createDocumentEntities( .documentId(documentIdExtractor.extractDocumentId(holder.getDocument().getUrl())) .fileName(holder.getDocument().getFilename()) .binaryUrl(holder.getDocument().getBinaryUrl()) - .categoryId(categoryIdFor(holder.getType())) + .categoryId(mapDocumentTypeToCategory(holder.getType()) + .map(CaseFileCategory::getId) + .orElse(null)) .type(holder.getType()) .description(StringUtils.isEmpty(holder.getDescription()) ? null : holder.getDescription()) .build()) @@ -247,6 +248,8 @@ public List linkAdditionalDocumentsToCase( .collect(Collectors.toSet()); ClaimEntity mainClaim = getMainClaim(pcsCase); + String applicationsCategoryId = CaseFileCategory.APPLICATIONS.getId(); + List documentEntities = uploadedDocuments.stream() .map(ListValue::getValue) .filter(Objects::nonNull) @@ -268,7 +271,7 @@ public List linkAdditionalDocumentsToCase( .contentType(uploaded.getContentType()) .size(uploaded.getSizeInBytes()) .type(DocumentType.OTHER) - .categoryId(selectedGenApp != null ? CaseFileCategory.APPLICATIONS.getId() : DEFAULT_CATEGORY_ID) + .categoryId(selectedGenApp != null ? applicationsCategoryId : null) .build(); }) .toList(); @@ -325,7 +328,6 @@ public List createDefendantUploadedDocuments( .binaryUrl(defDoc.getDocument().getBinaryUrl()) .contentType(defDoc.getContentType()) .size(defDoc.getSizeInBytes()) - .categoryId(DEFAULT_CATEGORY_ID) .build(); }) .toList(); @@ -415,16 +417,6 @@ private Optional mapDocumentTypeToCategory(DocumentType docume }; } - private String categoryIdFor(DocumentType documentType) { - if (documentType == null) { - return DEFAULT_CATEGORY_ID; - } - - return mapDocumentTypeToCategory(documentType) - .map(CaseFileCategory::getId) - .orElse(DEFAULT_CATEGORY_ID); - } - private DocumentType mapEvidenceDocumentTypeToDocumentType(EvidenceDocumentType evidenceDocumentType) { return switch (evidenceDocumentType) { case PHOTOGRAPHIC_EVIDENCE -> DocumentType.PHOTOGRAPHIC_EVIDENCE; @@ -441,4 +433,4 @@ private static class DocumentHolder { private DocumentType type; private String description; } -} +} \ No newline at end of file diff --git a/src/main/resources/db/migration/V135__default_uncategorised_document_category.sql b/src/main/resources/db/migration/V135__default_uncategorised_document_category.sql deleted file mode 100644 index 496ee14494..0000000000 --- a/src/main/resources/db/migration/V135__default_uncategorised_document_category.sql +++ /dev/null @@ -1,9 +0,0 @@ -UPDATE document -SET category_id = 'uncategorisedDocuments' -WHERE category_id IS NULL; - -ALTER TABLE document -ALTER COLUMN category_id SET DEFAULT 'uncategorisedDocuments'; - -ALTER TABLE document -ALTER COLUMN category_id SET NOT NULL; diff --git a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/AccessProfileTest.java b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/AccessProfileTest.java index fd42e060ea..f0d30a9ccd 100644 --- a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/AccessProfileTest.java +++ b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/AccessProfileTest.java @@ -1,7 +1,6 @@ package uk.gov.hmcts.reform.pcs.ccd.accesscontrol; import org.junit.jupiter.api.Test; -import uk.gov.hmcts.ccd.sdk.api.Permission; import static org.assertj.core.api.Assertions.assertThat; @@ -20,15 +19,4 @@ void shouldReturnEmptyArrayWhenNoProfilesGiven() { assertThat(roles).isEmpty(); } - - @Test - void shouldGrantCreateReadUpdateCaseTypeAccessToJudicialProfiles() { - assertThat(AccessProfile.JUDGE.getCaseTypePermissions()).isEqualTo(Permission.toString(Permission.CRU)); - assertThat(AccessProfile.FEE_PAID_JUDGE.getCaseTypePermissions()) - .isEqualTo(Permission.toString(Permission.CRU)); - assertThat(AccessProfile.CIRCUIT_JUDGE.getCaseTypePermissions()) - .isEqualTo(Permission.toString(Permission.CRU)); - assertThat(AccessProfile.LEADERSHIP_JUDGE.getCaseTypePermissions()) - .isEqualTo(Permission.toString(Permission.CRU)); - } -} +} \ No newline at end of file diff --git a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/DefendantAccessCodeServiceTest.java b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/DefendantAccessCodeServiceTest.java index 5438a16456..fa55970f3a 100644 --- a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/DefendantAccessCodeServiceTest.java +++ b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/DefendantAccessCodeServiceTest.java @@ -7,7 +7,6 @@ import org.mockito.Captor; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import uk.gov.hmcts.reform.pcs.ccd.domain.CaseFileCategory; import uk.gov.hmcts.reform.pcs.ccd.domain.DocumentType; import uk.gov.hmcts.reform.pcs.ccd.domain.claimactivitylog.ClaimActivityType; import uk.gov.hmcts.reform.pcs.ccd.domain.claimactivitylog.GenerationDetails; @@ -105,7 +104,7 @@ void generateForDefendant_savesDocumentEncryptedCodePinAndLogsSuccess() { verify(documentRepository).save(documentCaptor.capture()); DocumentEntity savedDoc = documentCaptor.getValue(); assertThat(savedDoc.getType()).isEqualTo(DocumentType.DEFENDANT_ACCESS_CODE); - assertThat(savedDoc.getCategoryId()).isEqualTo(CaseFileCategory.UNCATEGORISED_DOCUMENTS.getId()); + assertThat(savedDoc.getCategoryId()).isNull(); assertThat(savedDoc.getUrl()).isEqualTo(DOC_URL); assertThat(savedDoc.getParty().getId()).isEqualTo(partyId); assertThat(savedDoc.getPcsCase()).isEqualTo(caseEntity); @@ -216,4 +215,4 @@ private static PcsCaseEntity createCaseWithDefendants(UUID... partyIds) { .claims(List.of(mainClaim)) .build(); } -} +} \ No newline at end of file diff --git a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/DraftCaseJsonMergerTest.java b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/DraftCaseJsonMergerTest.java index 5ac8c175b1..c7e5d17730 100644 --- a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/DraftCaseJsonMergerTest.java +++ b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/DraftCaseJsonMergerTest.java @@ -88,7 +88,6 @@ void shouldKeepExistingFieldsWhenMerging() throws JsonProcessingException { "possessionClaimResponse", "enforcementOrder.rawWarrantDetails.vulnerableAdultsChildren", "xuiGenAppRequest", - "documentAmendDetails", "casePartiesTab", "caseDetailsTab", "summaryTab") diff --git a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java deleted file mode 100644 index bd89aa8488..0000000000 --- a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java +++ /dev/null @@ -1,349 +0,0 @@ -package uk.gov.hmcts.reform.pcs.ccd.service.document; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; -import uk.gov.hmcts.ccd.sdk.type.DynamicList; -import uk.gov.hmcts.ccd.sdk.type.DynamicListElement; -import uk.gov.hmcts.ccd.sdk.type.YesOrNo; -import uk.gov.hmcts.reform.pcs.ccd.domain.CaseFileCategory; -import uk.gov.hmcts.reform.pcs.ccd.domain.DocumentType; -import uk.gov.hmcts.reform.pcs.ccd.domain.PCSCase; -import uk.gov.hmcts.reform.pcs.ccd.domain.VerticalYesNo; -import uk.gov.hmcts.reform.pcs.ccd.domain.documentamend.DocumentAmendDetails; -import uk.gov.hmcts.reform.pcs.ccd.entity.DocumentEntity; -import uk.gov.hmcts.reform.pcs.ccd.entity.GenAppEntity; -import uk.gov.hmcts.reform.pcs.ccd.entity.PcsCaseEntity; -import uk.gov.hmcts.reform.pcs.ccd.service.PcsCaseService; -import uk.gov.hmcts.reform.pcs.ccd.util.AddressFormatter; - -import java.time.Instant; -import java.util.List; -import java.util.UUID; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.when; -import static uk.gov.hmcts.reform.pcs.ccd.domain.CaseFileCategory.APPLICATIONS; -import static uk.gov.hmcts.reform.pcs.ccd.domain.CaseFileCategory.EVIDENCE; -import static uk.gov.hmcts.reform.pcs.ccd.domain.CaseFileCategory.UNCATEGORISED_DOCUMENTS; - -@ExtendWith(MockitoExtension.class) -class DocumentAmendSelectionServiceTest { - - private static final long CASE_REFERENCE = 1234567890123456L; - - @Mock - private PcsCaseService pcsCaseService; - - private DocumentAmendSelectionService underTest; - - @BeforeEach - void setUp() { - underTest = new DocumentAmendSelectionService(pcsCaseService, new AddressFormatter()); - } - - @Test - void shouldDefineFolderDropdownWithCaseFileViewFolders() { - assertThat(CaseFileCategory.values()) - .extracting(CaseFileCategory::getLabel) - .containsExactly( - "Statements of case", - "Property documents", - "Evidence", - "Hearing documents", - "Orders and Notice of Hearings", - "Applications", - "Appeals", - "Correspondence", - "Uncategorised documents" - ); - } - - @Test - void shouldPopulatePropertyAddressSummary() { - when(pcsCaseService.loadCase(CASE_REFERENCE)).thenReturn(PcsCaseEntity.builder().build()); - PCSCase caseData = PCSCase.builder() - .propertyAddress(uk.gov.hmcts.ccd.sdk.type.AddressUK.builder() - .addressLine1("15 Garden Drive") - .postTown("Luton") - .postCode("LU1 1AB") - .build()) - .build(); - - underTest.initialise(CASE_REFERENCE, caseData); - - assertThat(caseData.getDocumentAmendDetails().getPropertyAddressSummary()) - .isEqualTo("15 Garden Drive, Luton, LU1 1AB"); - } - - @Test - void shouldSerialiseDocumentAmendFieldsWithGeneratedCcdFieldIds() throws JsonProcessingException { - DynamicList applicationsDocuments = DynamicList.builder() - .value(DynamicListElement.EMPTY) - .listItems(List.of(DynamicListElement.builder() - .code(UUID.randomUUID()) - .label("application.pdf") - .build())) - .build(); - PCSCase caseData = PCSCase.builder() - .documentAmendDetails(DocumentAmendDetails.builder() - .applicationsDocuments(applicationsDocuments) - .applicationsEmpty(YesOrNo.NO) - .build()) - .build(); - - String serialisedCaseData = new ObjectMapper().writeValueAsString(caseData); - - assertThat(serialisedCaseData).contains("\"documentAmend_ApplicationsDocuments\""); - assertThat(serialisedCaseData).contains("\"documentAmend_ApplicationsEmpty\""); - assertThat(serialisedCaseData).doesNotContain("documentAmend_applicationsDocuments"); - } - - @Test - void shouldPopulateDocumentsForSelectedCategoryAndIncludeWithoutNoticeApplicationDocuments() { - DocumentEntity visibleEvidence = document("visible evidence.pdf", EVIDENCE.getId(), null); - DocumentEntity withoutNoticeApplicationDocument = document( - "without notice application.pdf", - APPLICATIONS.getId(), - GenAppEntity.builder().withoutNotice(VerticalYesNo.YES).build() - ); - DocumentEntity visibleApplicationDocument = document( - "visible application.pdf", - APPLICATIONS.getId(), - GenAppEntity.builder().withoutNotice(VerticalYesNo.NO).build() - ); - PcsCaseEntity pcsCase = PcsCaseEntity.builder() - .documents(List.of(visibleEvidence, withoutNoticeApplicationDocument, visibleApplicationDocument)) - .build(); - when(pcsCaseService.loadCase(CASE_REFERENCE)).thenReturn(pcsCase); - PCSCase caseData = PCSCase.builder().build(); - - underTest.initialise(CASE_REFERENCE, caseData); - - DocumentAmendDetails details = caseData.getDocumentAmendDetails(); - assertThat(details.getEvidenceDocuments().getListItems()) - .extracting(DynamicListElement::getLabel) - .containsExactly("visible evidence.pdf"); - assertThat(details.getApplicationsDocuments().getListItems()) - .extracting(DynamicListElement::getLabel) - .containsExactly("visible application.pdf", "without notice application.pdf"); - assertThat(details.getApplicationsDocuments().getValue()).isNull(); - } - - @Test - void shouldExcludeDocumentsWithNullCategoryIdFromUncategorisedDocuments() { - DocumentEntity nullCategoryDocument = document("loose document.pdf", null, null); - DocumentEntity categorisedDocument = document( - "uncategorised document.pdf", - UNCATEGORISED_DOCUMENTS.getId(), - null - ); - when(pcsCaseService.loadCase(CASE_REFERENCE)).thenReturn(PcsCaseEntity.builder() - .documents(List.of(nullCategoryDocument, categorisedDocument)) - .build()); - PCSCase caseData = PCSCase.builder().build(); - - underTest.initialise(CASE_REFERENCE, caseData); - - assertThat(caseData.getDocumentAmendDetails().getUncategorisedDocuments().getListItems()) - .extracting(DynamicListElement::getLabel) - .containsExactly("uncategorised document.pdf"); - assertThat(caseData.getDocumentAmendDetails().getUncategorisedDocumentsEmpty()).isEqualTo(YesOrNo.NO); - } - - @Test - void shouldExcludeDefendantAccessCodeDocumentsFromUncategorisedDocuments() { - DocumentEntity accessCodeDocument = documentWithType( - null, - UNCATEGORISED_DOCUMENTS.getId(), - DocumentType.DEFENDANT_ACCESS_CODE - ); - DocumentEntity visibleDocument = documentWithType( - "uncategorised document.pdf", - UNCATEGORISED_DOCUMENTS.getId(), - DocumentType.OTHER - ); - when(pcsCaseService.loadCase(CASE_REFERENCE)).thenReturn(PcsCaseEntity.builder() - .documents(List.of(accessCodeDocument, visibleDocument)) - .build()); - PCSCase caseData = PCSCase.builder().build(); - - underTest.initialise(CASE_REFERENCE, caseData); - - assertThat(caseData.getDocumentAmendDetails().getUncategorisedDocuments().getListItems()) - .extracting(DynamicListElement::getLabel) - .containsExactly("uncategorised document.pdf"); - assertThat(caseData.getDocumentAmendDetails().getUncategorisedDocumentsEmpty()).isEqualTo(YesOrNo.NO); - } - - @Test - void shouldOrderDocumentsBySubmittedDateDescendingThenFileNameWithNullDatesLast() { - DocumentEntity older = document( - "b older evidence.pdf", - EVIDENCE.getId(), - null, - Instant.parse("2026-01-01T10:00:00Z") - ); - DocumentEntity newerA = document( - "a newer evidence.pdf", - EVIDENCE.getId(), - null, - Instant.parse("2026-01-02T10:00:00Z") - ); - DocumentEntity newerB = document( - "b newer evidence.pdf", - EVIDENCE.getId(), - null, - Instant.parse("2026-01-02T10:00:00Z") - ); - DocumentEntity nullDate = document("null date evidence.pdf", EVIDENCE.getId(), null, null); - when(pcsCaseService.loadCase(CASE_REFERENCE)).thenReturn(PcsCaseEntity.builder() - .documents(List.of(older, nullDate, newerB, newerA)) - .build()); - PCSCase caseData = PCSCase.builder().build(); - - underTest.initialise(CASE_REFERENCE, caseData); - - assertThat(caseData.getDocumentAmendDetails().getEvidenceDocuments().getListItems()) - .extracting(DynamicListElement::getLabel) - .containsExactly( - "a newer evidence.pdf", - "b newer evidence.pdf", - "b older evidence.pdf", - "null date evidence.pdf" - ); - } - - @Test - void shouldReturnNoErrorsWhenDocumentAmendDetailsIsNull() { - List errors = underTest.validateAndStoreSelection(PCSCase.builder().build()); - - assertThat(errors).isEmpty(); - } - - @Test - void shouldReturnDifferentFolderErrorWhenSelectedFolderHasNoDocuments() { - when(pcsCaseService.loadCase(CASE_REFERENCE)).thenReturn(PcsCaseEntity.builder().build()); - PCSCase caseData = PCSCase.builder() - .documentAmendDetails(DocumentAmendDetails.builder() - .selectedFolder(UNCATEGORISED_DOCUMENTS) - .build()) - .build(); - underTest.initialise(CASE_REFERENCE, caseData); - - List errors = underTest.validateAndStoreSelection(caseData); - - assertThat(errors).containsExactly("Select a different folder to continue"); - assertThat(caseData.getDocumentAmendDetails().getSelectedFolderId()) - .isEqualTo(UNCATEGORISED_DOCUMENTS.getId()); - assertThat(caseData.getDocumentAmendDetails().getSelectedFolderLabel()) - .isEqualTo(UNCATEGORISED_DOCUMENTS.getLabel()); - assertThat(caseData.getDocumentAmendDetails().getSelectedDocumentId()).isNull(); - assertThat(caseData.getDocumentAmendDetails().getSelectedDocumentFileName()).isNull(); - } - - @Test - void shouldTreatEmptyDocumentSelectionAsNoSelection() { - DocumentEntity document = document("photo.pdf", EVIDENCE.getId(), null); - when(pcsCaseService.loadCase(CASE_REFERENCE)).thenReturn(PcsCaseEntity.builder() - .documents(List.of(document)) - .build()); - PCSCase caseData = PCSCase.builder() - .documentAmendDetails(DocumentAmendDetails.builder() - .selectedFolder(EVIDENCE) - .evidenceDocuments(DynamicList.builder() - .build()) - .build()) - .build(); - underTest.initialise(CASE_REFERENCE, caseData); - - List errors = underTest.validateAndStoreSelection(caseData); - - assertThat(errors).isEmpty(); - assertThat(caseData.getDocumentAmendDetails().getSelectedDocumentId()).isNull(); - assertThat(caseData.getDocumentAmendDetails().getSelectedDocumentFileName()).isNull(); - } - - @Test - void shouldPersistSelectedFolderAndDocumentDetails() { - DocumentEntity document = document("photo.pdf", EVIDENCE.getId(), null); - when(pcsCaseService.loadCase(CASE_REFERENCE)).thenReturn(PcsCaseEntity.builder() - .documents(List.of(document)) - .build()); - PCSCase caseData = PCSCase.builder() - .documentAmendDetails(DocumentAmendDetails.builder() - .selectedFolder(EVIDENCE) - .evidenceDocuments(selectedDocument(document)) - .build()) - .build(); - underTest.initialise(CASE_REFERENCE, caseData); - - List errors = underTest.validateAndStoreSelection(caseData); - - assertThat(errors).isEmpty(); - assertThat(caseData.getDocumentAmendDetails().getSelectedFolderId()).isEqualTo(EVIDENCE.getId()); - assertThat(caseData.getDocumentAmendDetails().getSelectedFolderLabel()).isEqualTo(EVIDENCE.getLabel()); - assertThat(caseData.getDocumentAmendDetails().getSelectedDocumentId()).isEqualTo(document.getId().toString()); - assertThat(caseData.getDocumentAmendDetails().getSelectedDocumentFileName()).isEqualTo("photo.pdf"); - } - - @Test - void shouldLeaveMissingDocumentSelectionToExuiMandatoryValidation() { - DocumentEntity document = document("photo.pdf", EVIDENCE.getId(), null); - when(pcsCaseService.loadCase(CASE_REFERENCE)).thenReturn(PcsCaseEntity.builder() - .documents(List.of(document)) - .build()); - PCSCase caseData = PCSCase.builder() - .documentAmendDetails(DocumentAmendDetails.builder() - .selectedFolder(EVIDENCE) - .build()) - .build(); - underTest.initialise(CASE_REFERENCE, caseData); - - List errors = underTest.validateAndStoreSelection(caseData); - - assertThat(errors).isEmpty(); - assertThat(caseData.getDocumentAmendDetails().getSelectedDocumentId()).isNull(); - } - - private static DynamicList selectedDocument(DocumentEntity document) { - DynamicListElement selectedDocument = DynamicListElement.builder() - .code(document.getId()) - .label(document.getFileName()) - .build(); - - return DynamicList.builder() - .value(selectedDocument) - .listItems(List.of(selectedDocument)) - .build(); - } - - private static DocumentEntity document(String fileName, String categoryId, GenAppEntity generalApplication) { - return document(fileName, categoryId, generalApplication, Instant.now()); - } - - private static DocumentEntity document(String fileName, String categoryId, GenAppEntity generalApplication, - Instant submittedDate) { - return DocumentEntity.builder() - .id(UUID.randomUUID()) - .fileName(fileName) - .categoryId(categoryId) - .generalApplication(generalApplication) - .submittedDate(submittedDate) - .build(); - } - - private static DocumentEntity documentWithType(String fileName, String categoryId, DocumentType type) { - return DocumentEntity.builder() - .id(UUID.randomUUID()) - .fileName(fileName) - .categoryId(categoryId) - .type(type) - .submittedDate(Instant.now()) - .build(); - } -} diff --git a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentServiceTest.java b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentServiceTest.java index 91314aa40e..cf8d4829d1 100644 --- a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentServiceTest.java +++ b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentServiceTest.java @@ -485,8 +485,7 @@ void shouldPersistNullCategoryForPoliceReportEvidenceDocuments() { List capturedEntities = documentEntityListCaptor.getValue(); assertThat(capturedEntities).hasSize(1); - assertThat(capturedEntities.getFirst().getCategoryId()) - .isEqualTo(CaseFileCategory.UNCATEGORISED_DOCUMENTS.getId()); + assertThat(capturedEntities.getFirst().getCategoryId()).isNull(); } @Test @@ -770,7 +769,7 @@ void shouldSaveDefendantEvidenceDocuments() { assertThat(entities).allSatisfy(entity -> { assertThat(entity.getType()).isNull(); - assertThat(entity.getCategoryId()).isEqualTo(CaseFileCategory.UNCATEGORISED_DOCUMENTS.getId()); + assertThat(entity.getCategoryId()).isNull(); assertThat(entity.getDefendantResponse()).isEqualTo(response); assertThat(entity.getPcsCase()).isEqualTo(pcsCase); assertThat(entity.getParty()).isEqualTo(party); @@ -968,7 +967,7 @@ void shouldSaveAdditionalDocumentsForPartyAsOtherTypeWithPartyPostfixWhenNoGenAp assertThat(entities).hasSize(1); DocumentEntity entity = entities.getFirst(); assertThat(entity.getType()).isEqualTo(DocumentType.OTHER); - assertThat(entity.getCategoryId()).isEqualTo(CaseFileCategory.UNCATEGORISED_DOCUMENTS.getId()); + assertThat(entity.getCategoryId()).isNull(); assertThat(entity.getGeneralApplication()).isNull(); assertThat(entity.getUrl()).isEqualTo("url-new"); assertThat(entity.getFileName()).isEqualTo("file-new - Defendant 1.pdf"); @@ -1170,7 +1169,7 @@ private static Stream additionalDocumentCategoryScenarios() { Arguments.of(AdditionalDocumentType.CERTIFICATE_OF_SUITABILITY_AS_LF, CaseFileCategory.CORRESPONDENCE.getId()), Arguments.of(AdditionalDocumentType.LEGAL_AID_CERTIFICATE, CaseFileCategory.CORRESPONDENCE.getId()), - Arguments.of(AdditionalDocumentType.OTHER, CaseFileCategory.UNCATEGORISED_DOCUMENTS.getId()) + Arguments.of(AdditionalDocumentType.OTHER, null) ); } @@ -1387,4 +1386,4 @@ private static Stream additionalDocumentTypeScenarios() { ) ); } -} +} \ No newline at end of file From 78dece31fc2f8994346bc2de1429f2374aace5ce Mon Sep 17 00:00:00 2001 From: srinijg Date: Thu, 16 Jul 2026 12:17:54 +0100 Subject: [PATCH 57/70] spacing update --- .../reform/pcs/controllers/ClaimFormPersistenceServiceIT.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/integrationTest/java/uk/gov/hmcts/reform/pcs/controllers/ClaimFormPersistenceServiceIT.java b/src/integrationTest/java/uk/gov/hmcts/reform/pcs/controllers/ClaimFormPersistenceServiceIT.java index d11d0522bc..c0490ec54c 100644 --- a/src/integrationTest/java/uk/gov/hmcts/reform/pcs/controllers/ClaimFormPersistenceServiceIT.java +++ b/src/integrationTest/java/uk/gov/hmcts/reform/pcs/controllers/ClaimFormPersistenceServiceIT.java @@ -96,4 +96,4 @@ void attachesDocumentAndRecordsGenerationSuccess() { assertThat(claimRepository.findById(claimId).orElseThrow().getClaimFormDocument()).isNotNull(); verify(claimActivityLogService).logGenerationSuccess(caseReference); } -} \ No newline at end of file +} From 312102e697245b4cb77d3f20190ddd704f8d5510 Mon Sep 17 00:00:00 2001 From: srinijg Date: Thu, 16 Jul 2026 12:21:36 +0100 Subject: [PATCH 58/70] spacing adjusted --- .../uk/gov/hmcts/reform/pcs/ccd/domain/CaseFileCategory.java | 2 +- src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/PCSCase.java | 2 +- .../reform/pcs/ccd/service/DefendantAccessCodeService.java | 2 +- .../hmcts/reform/pcs/ccd/service/document/DocumentService.java | 2 +- .../hmcts/reform/pcs/ccd/accesscontrol/AccessProfileTest.java | 2 +- .../reform/pcs/ccd/service/DefendantAccessCodeServiceTest.java | 2 +- .../reform/pcs/ccd/service/document/DocumentServiceTest.java | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/CaseFileCategory.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/CaseFileCategory.java index 7ac092e7df..0d8a87716f 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/CaseFileCategory.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/CaseFileCategory.java @@ -19,4 +19,4 @@ public enum CaseFileCategory { private final String id; private final String label; private final int displayOrder; -} \ No newline at end of file +} diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/PCSCase.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/PCSCase.java index e9f8dc7e7a..a4e2f8eeec 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/PCSCase.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/PCSCase.java @@ -729,4 +729,4 @@ public class PCSCase { typeParameterOverride = "CaseStateOption" ) private CaseStateOption targetState; -} \ No newline at end of file +} diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/DefendantAccessCodeService.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/DefendantAccessCodeService.java index ac9b9c3621..465ae60de1 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/DefendantAccessCodeService.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/DefendantAccessCodeService.java @@ -151,4 +151,4 @@ private static ClaimEntity getMainClaim(PcsCaseEntity pcsCaseEntity) { .findFirst() .orElseThrow(() -> new ClaimNotFoundException(pcsCaseEntity.getCaseReference())); } -} \ No newline at end of file +} diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentService.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentService.java index ca12664dad..a0a274e389 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentService.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentService.java @@ -433,4 +433,4 @@ private static class DocumentHolder { private DocumentType type; private String description; } -} \ No newline at end of file +} diff --git a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/AccessProfileTest.java b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/AccessProfileTest.java index f0d30a9ccd..aa04539f75 100644 --- a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/AccessProfileTest.java +++ b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/AccessProfileTest.java @@ -19,4 +19,4 @@ void shouldReturnEmptyArrayWhenNoProfilesGiven() { assertThat(roles).isEmpty(); } -} \ No newline at end of file +} diff --git a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/DefendantAccessCodeServiceTest.java b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/DefendantAccessCodeServiceTest.java index fa55970f3a..d15e4b79a2 100644 --- a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/DefendantAccessCodeServiceTest.java +++ b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/DefendantAccessCodeServiceTest.java @@ -215,4 +215,4 @@ private static PcsCaseEntity createCaseWithDefendants(UUID... partyIds) { .claims(List.of(mainClaim)) .build(); } -} \ No newline at end of file +} diff --git a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentServiceTest.java b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentServiceTest.java index cf8d4829d1..8292cc9224 100644 --- a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentServiceTest.java +++ b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentServiceTest.java @@ -1386,4 +1386,4 @@ private static Stream additionalDocumentTypeScenarios() { ) ); } -} \ No newline at end of file +} From e8b412bd41137014b3da01d3192ea927c68f7c84 Mon Sep 17 00:00:00 2001 From: srinijg Date: Thu, 16 Jul 2026 12:59:45 +0100 Subject: [PATCH 59/70] update tab action --- src/e2eTest/data/page-data/home.page.data.ts | 2 +- src/e2eTest/utils/actions/element-actions/clickTab.action.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/e2eTest/data/page-data/home.page.data.ts b/src/e2eTest/data/page-data/home.page.data.ts index 6809d8e1bc..74891b516e 100644 --- a/src/e2eTest/data/page-data/home.page.data.ts +++ b/src/e2eTest/data/page-data/home.page.data.ts @@ -13,7 +13,7 @@ export const home = caseSummary: 'Summary', caseDetails: 'Case Details', caseFileView: 'Case File View', - caseFileFolders: ['Appeals','Applications','Orders and Notice of Hearings','Hearing documents','Property documents','Evidence','Statements of case','Correspondence','Uncategorised documents'], + caseFileFolders: ['Appeals','Applications','Orders and notice of hearings','Hearing documents','Property documents','Evidence','Statements of case','Correspondence','Uncategorised documents'], caseListTableHeader: ['Case number','Date issued','Claimant names','Defendant names','Postcode','State'], signOutButton: 'Sign out', }; \ No newline at end of file diff --git a/src/e2eTest/utils/actions/element-actions/clickTab.action.ts b/src/e2eTest/utils/actions/element-actions/clickTab.action.ts index 6d2d2b6e83..4dfe1b853f 100644 --- a/src/e2eTest/utils/actions/element-actions/clickTab.action.ts +++ b/src/e2eTest/utils/actions/element-actions/clickTab.action.ts @@ -7,7 +7,7 @@ export class ClickTabAction implements IAction { const locator = page.getByRole('tab', { name: tabName }) .or(page.getByRole('link', { name: tabName })); - await locator.waitFor({ state: 'visible' }); - await locator.click(); + await locator.first().waitFor({ state: 'visible' }); + await locator.first().click(); } } From e199c5e5a3b642fdf77fe4eea3f055a647996f23 Mon Sep 17 00:00:00 2001 From: hmcts-jenkins-j-to-z <61242337+hmcts-jenkins-j-to-z[bot]@users.noreply.github.com> Date: Thu, 16 Jul 2026 12:29:09 +0000 Subject: [PATCH 60/70] Bumping chart version/ fixing aliases --- charts/pcs-api/Chart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/charts/pcs-api/Chart.yaml b/charts/pcs-api/Chart.yaml index 9c995131ee..33d8187acf 100644 --- a/charts/pcs-api/Chart.yaml +++ b/charts/pcs-api/Chart.yaml @@ -3,7 +3,7 @@ appVersion: "1.0" description: A Helm chart for pcs-api App name: pcs-api home: https://github.com/hmcts/pcs-api -version: 0.0.74 +version: 0.0.75 maintainers: - name: HMCTS pcs team dependencies: From 104a0004517dcdcb3394d75d71d0a4778510c378 Mon Sep 17 00:00:00 2001 From: srinijg Date: Fri, 17 Jul 2026 14:26:13 +0100 Subject: [PATCH 61/70] new tests added --- ...enterGenAppapplicationDetails.page.data.ts | 37 ++++ .../page-data-caseManagement-figma/index.ts | 1 + .../urlToFileMappingCM.ts | 3 +- .../data/page-data/caseSummary.page.data.ts | 3 +- .../data/user-data/permanent.user.data.ts | 4 + .../caseManagement.caseWorkerGenApps.spec.ts | 56 ++++++ .../caseManagement.action.ts | 167 +++++++++++++----- .../caseManagementErrorValidation.action.ts | 33 +++- .../caseManagementUtils.action.ts | 125 +++++++++++++ .../utils/controller-caseManagement.ts | 2 +- .../action-caseManagement.registry.ts | 2 + .../pageContent.validation.ts | 6 +- 12 files changed, 383 insertions(+), 56 deletions(-) create mode 100644 src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/enterGenAppapplicationDetails.page.data.ts create mode 100644 src/e2eTest/tests/test-caseManagement/caseManagement.caseWorkerGenApps.spec.ts create mode 100644 src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagementUtils.action.ts diff --git a/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/enterGenAppapplicationDetails.page.data.ts b/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/enterGenAppapplicationDetails.page.data.ts new file mode 100644 index 0000000000..0ab6644611 --- /dev/null +++ b/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/enterGenAppapplicationDetails.page.data.ts @@ -0,0 +1,37 @@ +export const enterGenappApplication = { + mainHeader: `Application details`, + whichPartyMadeAppQuestion: `Which party made the application?`, + whatDateAppReceivedQuestion: `What date was the application received?`, + typeOfAppQuestion: `Which type of application has the applicant made?`, + adjournRadioOption: `Adjourn`, + setAsideRadioOption: `Set aside`, + somethingElseRadioOption: `Something else`, + dayTextLabel: `Day`, + monthTextLabel: `Month`, + yearTextLabel: `Year`, + errorValidation: `YES`, + eventCouldNotBeCreatedErrorMessageHeader: `The event could not be created`, + errorValidationType: { one: `textField`, two: `radioOptions`, three: `checkBox`, four: `dropDown`, five: `dateField` }, + errorValidationField: { + errorRadioOption1: [ + { type: `none`, input: ``, errMessage: `Which party made the application? is required`, errInlineMessage: `Field is required` }, + ], + errorRadioOption2: [ + { type: `none`, input: ``, errMessage: `Which type of application has the applicant made? is required`, errInlineMessage: `Which type of application has the applicant made? is required` }, + ], + errorDateField: [ + { type: `empty`, input: `EMPTY`, errMessage: `What date was the application received? is required `,errInlineMessage: `Which type of application has the applicant made? is required`}, + { type: `invalid`, input: `invalid`, errMessage: `What date was the application received? is not valid `,errInlineMessage: `The data entered is not valid for What date was the application received?`}, + { type: `future`, input: 'future', errMessage: `Date the application was received must be in the past` }, + { type: `present`, input: 'present', errMessage: `Date the application was received must be in the past` }, + + ], + errorTextField: [ + { type: `moreThanMax`, input: 505, errMessage: `In ‘How are they vulnerable?’, you have entered more than the maximum number of characters (6,800)` }, + { type: `empty`, input: `EMPTY`, errMessage: `Which categories apply? is required `}, + ] + }, + continueButton: `Continue`, + previousButton: `Previous`, + cancelLink: `Cancel`, +}; diff --git a/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/index.ts b/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/index.ts index ab33b0a451..dd626c629f 100644 --- a/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/index.ts +++ b/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/index.ts @@ -3,3 +3,4 @@ export * from './amendDocumentDetails.page.data'; export * from './changeCaseState.page.data'; export * from './checkYourAnswersChangeState.page.data'; export * from './confirmCaseStateChange.page.data'; +export * from './enterGenAppapplicationDetails.page.data'; diff --git a/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/urlToFileMappingCM.ts b/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/urlToFileMappingCM.ts index 5ddbccf2cc..bc9ee544ba 100644 --- a/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/urlToFileMappingCM.ts +++ b/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/urlToFileMappingCM.ts @@ -1,5 +1,6 @@ export default { 'amendDocumentsselectDocument': 'selectDocument', 'changeCaseStatechangeCaseStatePage': 'changeCaseState', - 'changeCaseState/confirm': 'confirmCaseStateChange' + 'changeCaseState/confirm': 'confirmCaseStateChange', + 'enterGenAppapplicationDetails': 'enterGenAppapplicationDetails' }; \ No newline at end of file diff --git a/src/e2eTest/data/page-data/caseSummary.page.data.ts b/src/e2eTest/data/page-data/caseSummary.page.data.ts index 0c028d2f63..b2a7be001d 100644 --- a/src/e2eTest/data/page-data/caseSummary.page.data.ts +++ b/src/e2eTest/data/page-data/caseSummary.page.data.ts @@ -16,5 +16,6 @@ export const caseSummary = { manageDocuments:{ amend : 'Manage documents: Amend' }, - changeCaseState: 'Change case state' + changeCaseState: 'Change case state', + enterAGenApp: 'Enter a general application' } diff --git a/src/e2eTest/data/user-data/permanent.user.data.ts b/src/e2eTest/data/user-data/permanent.user.data.ts index 0cca4aafec..92a6aebca4 100644 --- a/src/e2eTest/data/user-data/permanent.user.data.ts +++ b/src/e2eTest/data/user-data/permanent.user.data.ts @@ -15,5 +15,9 @@ export const user = { staffAdmin: { email: 'pcs-ctsc-admin-01@justice.gov.uk', password: process.env.IDAM_PCS_USER_PASSWORD + }, + hearingCenterAdmin: { + email: 'pcs-hearing-centre-administrator-01@justice.gov.uk', + password: process.env.IDAM_PCS_USER_PASSWORD } }; diff --git a/src/e2eTest/tests/test-caseManagement/caseManagement.caseWorkerGenApps.spec.ts b/src/e2eTest/tests/test-caseManagement/caseManagement.caseWorkerGenApps.spec.ts new file mode 100644 index 0000000000..03ebf7e967 --- /dev/null +++ b/src/e2eTest/tests/test-caseManagement/caseManagement.caseWorkerGenApps.spec.ts @@ -0,0 +1,56 @@ +import { createCaseApiData, submitCaseApiData } from '@data/api-data'; +import { initializeExecutor } from '@utils/controller'; +import test from '@playwright/test'; +import { caseInfo } from '@utils/actions/custom-actions'; +import { PageContentValidation } from '@utils/validations/element-validations/pageContent.validation'; +import { caseSummary, user } from '@data/page-data'; +import { dismissCookieBanner } from '@config/cookie-banner'; +import { initializeCMExecutor, performAction, performValidation } from '@utils/controller-caseManagement'; +import { allPartyDetails } from '@utils/actions/custom-actions/custom-actions-caseManagement'; +import { enterGenappApplication } from '@data/page-data-figma/page-data-caseManagement-figma'; + +test.use({ storageState: undefined }) + +test.beforeEach(async ({ page, context }) => { + await context.clearCookies(); + initializeExecutor(page); + initializeCMExecutor(page); + allPartyDetails.length = 0; + await performAction('createCaseAPI', { data: createCaseApiData.createCasePayload }); + await performAction('submitCaseAPI', { data: submitCaseApiData.submitCasePayloadCaseFileView }); + await performAction('updatePaymentAPI'); + await performAction('getCaseAPI', 'Link Solicitor'); + await performAction('getAllPartyDetails', { + defendant1NameKnown: submitCaseApiData.submitCasePayloadCaseFileView.defendant1.nameKnown, + additionalDefendants: submitCaseApiData.submitCasePayloadCaseFileView.addAnotherDefendant, + payLoad: submitCaseApiData.submitCasePayloadCaseFileView + }); + await performAction('navigateToUrl', process.env.MANAGE_CASE_BASE_URL); + await dismissCookieBanner(page, 'additional'); + await performAction('login', user.hearingCenterAdmin); + await dismissCookieBanner(page, 'analytics'); + await performAction('navigateToSummaryPage'); +}); + +test.afterEach(async () => { + if (caseInfo.id) { + await performAction('deleteCaseRole', '[CLAIMANTSOLICITOR]'); + } + PageContentValidation.finaliseTest(); + +}); + +test.describe('Case management - Case Worker Enter a General application @nightly', async () => { + test('Case management - Case Worker Enter a General application ADJOURN Journey @CM @regression', async () => { + await performAction('selectAnEvent', { eventType: caseSummary.enterAGenApp }); + await performValidation('mainHeader', enterGenappApplication.mainHeader); + await performAction('errorValidationEnterGeneralAppPage', enterGenappApplication.errorValidation); + // await performAction('changeCaseState', { + // question: changeCaseState.whichStateYouMovingCaseToQuestion, option: changeCaseState.caseStateHiddenOption, + // nextPage: checkYourAnswersChangeState.mainHeader + // }); + // await performAction('clickButton', checkYourAnswersChangeState.submitButton); + // await performAction('confirmCaseStateChange'); + // await performValidation('bannerAlert', 'Case #.* has been updated with event: Change case state'); + }); +}); diff --git a/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagement.action.ts b/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagement.action.ts index 575091ed09..e96f6bd817 100644 --- a/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagement.action.ts +++ b/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagement.action.ts @@ -3,11 +3,12 @@ import { expect, Page } from '@playwright/test'; import { IAction, actionData, actionRecord } from '@utils/interfaces'; import { createCaseApiData } from '@data/api-data'; import { getCaseTypeId } from '@utils/common/caseType.utils'; -import { performAction, performValidation } from '@utils/controller-caseManagement'; +import { performAction, performActions, performValidation } from '@utils/controller-caseManagement'; import { VERY_LONG_TIMEOUT } from 'playwright.config'; import { caseSummary, home } from '@data/page-data'; import { changeCaseState, confirmCaseStateChange, selectDocument } from '@data/page-data-figma/page-data-caseManagement-figma'; import { caseInfo } from '../createCaseAPI.action'; +import { CaseManagementCommonUtils } from './caseManagementUtils.action'; export const addressInfo = { @@ -17,7 +18,7 @@ export const addressInfo = { engOrWalPostcode: createCaseApiData.createCasePayload.propertyAddress.PostCode }; const cyaMap = new Map(); -export let defendantDetails: string[] = []; +export let allPartyDetails: string[] = []; export class CaseManagementAction implements IAction { async execute(page: Page, action: string, fieldName: actionData | actionRecord): Promise { @@ -27,6 +28,7 @@ export class CaseManagementAction implements IAction { ['selectDocumentToAmend', () => this.selectDocumentToAmend(fieldName as actionRecord)], ['changeCaseState', () => this.changeCaseState(fieldName as actionRecord)], ['confirmCaseStateChange', () => this.confirmCaseStateChange()], + ['getAllPartyDetails', () => this.getAllPartyDetails(fieldName as actionRecord)], ['inputErrorValidation', () => this.inputErrorValidation(page, fieldName as actionRecord)], ]); @@ -54,13 +56,13 @@ export class CaseManagementAction implements IAction { await performAction('clickButton', caseSummary.go); } - private async selectDocumentToAmend(selectDoc: actionRecord){ + private async selectDocumentToAmend(selectDoc: actionRecord) { await performAction('select', selectDoc.question, selectDoc.option); await performAction('clickRadioButton', { question: selectDoc.question1, option: selectDoc.option1 }); await performAction('reTryOnCallBackError', selectDocument.continueButton, selectDoc.nextPage as string); } - private async changeCaseState(caseState: actionRecord){ + private async changeCaseState(caseState: actionRecord) { await performValidation('text', { elementType: 'paragraph', text: 'Case number: ' + caseInfo.fid }); await performValidation('text', { elementType: 'paragraph', @@ -85,52 +87,119 @@ export class CaseManagementAction implements IAction { await performAction('clickButton', confirmCaseStateChange.closeAndReturnToCaseOverviewButton); } - private async inputErrorValidation(page: Page, validationArr: actionRecord) { - - - if (Array.isArray(validationArr.inputArray)) { - for (const item of validationArr.inputArray) { - switch (validationArr.validationType) { - - case 'radioOptions': - await performAction('clickButton', validationArr.button); - await performValidation('inputError', !validationArr?.label ? validationArr.question : validationArr.label, item.errInlineMessage); - await performValidation('errorMessage', !validationArr?.header ? validationArr.header = 'There is a problem' : validationArr.header, item.errMessage); - await performAction('clickRadioButton', { question: validationArr.question, option: validationArr.option }); - break; - - case 'checkBox': - await performAction('clickButton', validationArr.button); - await performValidation('inputError', !validationArr?.label ? validationArr.question : validationArr.label, item.errMessage); - await performValidation('errorMessage', !validationArr?.header ? validationArr.header = 'There is a problem' : validationArr.header, item.errMessage); - await performAction('check', validationArr.checkBox); - break; - - case 'checkBoxPageLevel': - await performAction('clickButton', validationArr.button); - await performValidation('errorMessage', !validationArr?.header ? validationArr.header = 'There is a problem' : validationArr.header, item.errMessage); - await performAction('check', validationArr.checkBox); - break; - - case 'dropDown': - await performAction('clickButton', validationArr.button); - await expect(async () => { - await performAction('clickButton', validationArr.button); - await performValidation('errorMessage', !validationArr?.header ? validationArr.header = 'There is a problem' : validationArr.header, item.errMessage); - }).toPass({ - timeout: VERY_LONG_TIMEOUT, - }); - await performAction('select', validationArr.dropQn, validationArr.option); - break; - - default: - throw new Error(`Validation type :"${validationArr.validationType}" is not valid`); - }; - } + private async getAllPartyDetails(allPartiesDetails: actionRecord) { + + let originalDefendantDetails: string[] = []; + const payLoad = allPartiesDetails.payLoad as Record; + if (allPartiesDetails.defendant1NameKnown === 'YES') { + originalDefendantDetails.push( + `${payLoad.defendant1.firstName} ${payLoad.defendant1.lastName} - Defendant 1` + ); + } else { + originalDefendantDetails.push( + `null null` + ); + } + + if (allPartiesDetails.additionalDefendants === 'YES') { + + for (const [index, defendant] of payLoad.additionalDefendants.entries()) { + if (defendant.value.nameKnown === 'YES') { + originalDefendantDetails.push(`${defendant.value.firstName} ${defendant.value.lastName} - Defendant ${index + 2}`); + } else { + originalDefendantDetails.push( + `null null` + ); } - if (validationArr.buttonRemove) { - await performAction('removeFile'); - await page.waitForTimeout(6000); } } + + allPartyDetails = [...new Set(originalDefendantDetails.filter(n => n.trim().toLowerCase() !== "null null")), + ...originalDefendantDetails.filter(n => n.trim().toLowerCase() === "null null") + ]; + allPartyDetails.push(`${payLoad.claimantName} - Claimant 1`); + console.log(allPartyDetails); + } + + private async inputErrorValidation(page: Page, validationArr: actionRecord) { + + + if (Array.isArray(validationArr.inputArray)) { + for (const item of validationArr.inputArray) { + switch (validationArr.validationType) { + + case 'radioOptions': + await performAction('clickButton', validationArr.button); + await performValidation('inputError', !validationArr?.label ? validationArr.question : validationArr.label, item.errInlineMessage); + await performValidation('errorMessage', !validationArr?.header ? validationArr.header = 'There is a problem' : validationArr.header, item.errMessage); + await performAction('clickRadioButton', { question: validationArr.question, option: validationArr.option }); + break; + + case 'checkBox': + await performAction('clickButton', validationArr.button); + await performValidation('inputError', !validationArr?.label ? validationArr.question : validationArr.label, item.errMessage); + await performValidation('errorMessage', !validationArr?.header ? validationArr.header = 'There is a problem' : validationArr.header, item.errMessage); + await performAction('check', validationArr.checkBox); + break; + + case 'checkBoxPageLevel': + await performAction('clickButton', validationArr.button); + await performValidation('errorMessage', !validationArr?.header ? validationArr.header = 'There is a problem' : validationArr.header, item.errMessage); + await performAction('check', validationArr.checkBox); + break; + + case 'dropDown': + await performAction('clickButton', validationArr.button); + await expect(async () => { + await performAction('clickButton', validationArr.button); + await performValidation('errorMessage', !validationArr?.header ? validationArr.header = 'There is a problem' : validationArr.header, item.errMessage); + }).toPass({ + timeout: VERY_LONG_TIMEOUT, + }); + await performAction('select', validationArr.dropQn, validationArr.option); + break; + + case 'textField': + await performAction('inputText', validationArr.label, CaseManagementCommonUtils.generateRandomString(item.input)); + await expect(async () => { + await performAction('clickButton', validationArr.button); + if (item.type === 'moreThanMax') { + await performValidation('errorMessage', { header: validationArr.header, message: item.errMessage }); + } else { + await performValidation('inputError', validationArr.label, item.errMessage); + await performValidation('errorMessage', validationArr.label, item.errMessage); + } + }).toPass({ + timeout: VERY_LONG_TIMEOUT, + }); + break; + + case 'dateField': + let date: string = ''; + if (item.input === 'empty') { + await performAction('clickButton', validationArr.button); + await performValidation('errorMessage', { header: validationArr.header, message: item.errMessage }); + } + else { + date = CaseManagementCommonUtils.getRandomDate(item.input); + } + + await performActions('Enter Date', + ['inputText', validationArr.label, date.split('/')[0]], + ['inputText', validationArr.label, date.split('/')[1]], + ['inputText', validationArr.label, date.split('/')[2]]); + await performValidation('inputError', validationArr.label, item.errMessage); + await performValidation('errorMessage', validationArr.label, item.errMessage); + break; + + default: + throw new Error(`Validation type :"${validationArr.validationType}" is not valid`); + }; + } + } + if (validationArr.buttonRemove) { + await performAction('removeFile'); + await page.waitForTimeout(6000); + } + } } diff --git a/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagementErrorValidation.action.ts b/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagementErrorValidation.action.ts index 9b71a6c2ac..2afafc8561 100644 --- a/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagementErrorValidation.action.ts +++ b/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagementErrorValidation.action.ts @@ -1,13 +1,15 @@ import { Page } from '@playwright/test'; import { performAction } from '@utils/controller-caseManagement'; import { IAction, actionData, actionRecord } from '@utils/interfaces/action.interface'; -import { changeCaseState, selectDocument } from '@data/page-data-figma/page-data-caseManagement-figma'; +import { changeCaseState, enterGenappApplication, selectDocument } from '@data/page-data-figma/page-data-caseManagement-figma'; +import { allPartyDetails } from './caseManagement.action'; export class ErrorValidationAction implements IAction { async execute(page: Page, action: string, errorFlag: string | actionRecord, roles?: actionData): Promise { const actionsMap = new Map Promise>([ ['errorValidationSelectDocumentPage', () => this.errorValidationSelectDocumentPage(errorFlag as string)], ['errorValidationChangeCaseStatePage', () => this.errorValidationChangeCaseStatePage(errorFlag as string)], + ['errorValidationEnterGeneralAppPage', () => this.errorValidationEnterGeneralAppPage(errorFlag as string)], ]); const actionToPerform = actionsMap.get(action); @@ -46,4 +48,33 @@ export class ErrorValidationAction implements IAction { } } + private async errorValidationEnterGeneralAppPage(validationReq: string) { + if (validationReq === 'YES') { + await performAction('inputErrorValidation', { + validationType: enterGenappApplication.errorValidationType.two, + inputArray: enterGenappApplication.errorValidationField.errorRadioOption1, + question: enterGenappApplication.whichPartyMadeAppQuestion, + option: allPartyDetails[0], + button: enterGenappApplication.continueButton + }); + await performAction('inputErrorValidation', { + validationType: enterGenappApplication.errorValidationType.two, + inputArray: enterGenappApplication.errorValidationField.errorRadioOption2, + question: enterGenappApplication.typeOfAppQuestion, + option: enterGenappApplication.somethingElseRadioOption, + button: enterGenappApplication.continueButton + }); + await performAction('inputErrorValidation', { + validationType: enterGenappApplication.errorValidationType.five, + inputArray: enterGenappApplication.errorValidationField.errorTextField, + header: enterGenappApplication.eventCouldNotBeCreatedErrorMessageHeader, + label1: enterGenappApplication.dayTextLabel, + label2: enterGenappApplication.monthTextLabel, + label3: enterGenappApplication.yearTextLabel, + button: enterGenappApplication.continueButton + }); + + } + } + } diff --git a/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagementUtils.action.ts b/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagementUtils.action.ts new file mode 100644 index 0000000000..a067a8d6bb --- /dev/null +++ b/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagementUtils.action.ts @@ -0,0 +1,125 @@ +import { Page } from '@playwright/test'; +export type actionData = string | number | boolean | object | string[] | object[]; +export type actionRecord = Record; +export type actionTuple = [string, actionData | actionRecord] | [string, actionData | actionRecord, actionData | actionRecord]; + +export class CaseManagementCommonUtils { + + public static async generateMoreThanMaxString(page: Page, label: string, input: string | number): Promise { + + let length: number; + + if (input === 'MAXPLUS') { + const hintText = await page + .locator(`//span[text()="${label}"]/ancestor::div[contains(@class,'form-group')]//span[contains(@class,'form-hint')]`) + .innerText(); + + const limit = CaseManagementCommonUtils.retrieveLengthFromString(hintText); + if (limit === 0) return ''; + + length = limit + 1; + + } else if (typeof input === 'number') { + length = input + 1; + + } else { + return ''; + } + + const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + let finalString = ''; + for (let i = 0; i < length; i++) { + finalString += chars.charAt(Math.floor(Math.random() * chars.length)); + } + return finalString; + } + + public static retrieveLengthFromString(input: string): number { + const getCharCount = input.split('You can enter').map(str => str.trim()).filter(str => str.length > 0); + const charLimitInfo = getCharCount[getCharCount.length - 1].match(/[-+]?(?:\d{1,3}(?:,\d{3})+|\d+)(?:\.\d+)?/); + const amount = charLimitInfo ? Number(charLimitInfo[0].replace(/,/g, "")) : 0; + return Number(amount.toFixed(2)); + } + + + // public static inputDOB(inputArray: string[]): string { + // return inputArray.map((item) => item + " - " + CaseManagementCommonUtils.getRandomDate(18, 30)).join('\n'); + // } + + + public static getRandomDate(type: string): string { + + if (type === 'invalid') { + return '32/13/9999'; + } + + const today = new Date(); + + if (type === 'present') { + const day = String(today.getDate()).padStart(2, '0'); + const month = String(today.getMonth() + 1).padStart(2, '0'); + const year = today.getFullYear(); + + return `${day}/${month}/${year}`; + } + + let minDate: Date; + let maxDate: Date; + + if (type === 'future') { + minDate = today; + maxDate = new Date( + today.getFullYear() + 10, + today.getMonth(), + today.getDate() + ); + } else { + minDate = new Date( + today.getFullYear() - 100, + today.getMonth(), + today.getDate() + ); + maxDate = today; + } + + const randomTime = + minDate.getTime() + + Math.random() * (maxDate.getTime() - minDate.getTime()); + + const randomDate = new Date(randomTime); + + const day = String(randomDate.getDate()).padStart(2, '0'); + const month = String(randomDate.getMonth() + 1).padStart(2, '0'); + const year = randomDate.getFullYear(); + + return `${day}/${month}/${year}`; + } + + public static getRandomElementForAnArray(arr: T[]): T | undefined { + + if (arr.length === 0) return undefined; + const index = Math.floor(Math.random() * arr.length); + return arr[index]; + + } + + public static formatPayLoadData(input: string): string { + + let formattedOutput = ""; + const splitInput = input.toLowerCase().split("_"); + formattedOutput = splitInput + .map((str, i) => (i === 0 ? str.charAt(0).toUpperCase() + str.slice(1) : str)) + .join(" "); + return formattedOutput; + + } + + public static generateRandomString(length: string | number): string { + if (typeof length !== 'number' || !Number.isInteger(length) || length <= 0) { + return ''; + } + const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + return Array.from({ length }, () => chars[Math.floor(Math.random() * chars.length)]).join(''); + } + +} diff --git a/src/e2eTest/utils/controller-caseManagement.ts b/src/e2eTest/utils/controller-caseManagement.ts index b2ce79aa06..f4a340833a 100644 --- a/src/e2eTest/utils/controller-caseManagement.ts +++ b/src/e2eTest/utils/controller-caseManagement.ts @@ -70,7 +70,7 @@ async function validatePageIfNavigated(action: string): Promise { } function captureDataForCYA(action: string, fieldName?: actionData | actionRecord, value?: actionData | actionRecord): void { - if (action === 'changeCaseState') { + if (action === 'changeCaseState' || action === 'enterAppDetails') { captureDataForCYAPage = true; } diff --git a/src/e2eTest/utils/registry/registry-caseManagement/action-caseManagement.registry.ts b/src/e2eTest/utils/registry/registry-caseManagement/action-caseManagement.registry.ts index 50cd3cacb7..eb99b97eb4 100644 --- a/src/e2eTest/utils/registry/registry-caseManagement/action-caseManagement.registry.ts +++ b/src/e2eTest/utils/registry/registry-caseManagement/action-caseManagement.registry.ts @@ -38,8 +38,10 @@ export class ActionCMRegistry { ['selectDocumentToAmend', new CaseManagementAction()], ['changeCaseState', new CaseManagementAction()], ['confirmCaseStateChange', new CaseManagementAction()], + ['getAllPartyDetails', new CaseManagementAction()], ['errorValidationSelectDocumentPage', new ErrorValidationAction()], ['errorValidationChangeCaseStatePage', new ErrorValidationAction()], + ['errorValidationEnterGeneralAppPage', new ErrorValidationAction()], ['inputErrorValidation', new CaseManagementAction()], ['reTryOnCallBackError', new RetryOnCallBackError()], diff --git a/src/e2eTest/utils/validations/element-validations/pageContent.validation.ts b/src/e2eTest/utils/validations/element-validations/pageContent.validation.ts index 7594c6e49e..098fe7ebe6 100644 --- a/src/e2eTest/utils/validations/element-validations/pageContent.validation.ts +++ b/src/e2eTest/utils/validations/element-validations/pageContent.validation.ts @@ -183,7 +183,7 @@ export class PageContentValidation implements IValidation { mappingPath = path.join(__dirname, '../../../data/page-data-figma/page-data-genApps-figma/urlToFileMappingGenApps.ts'); } else if( - ["amendDocuments", "changeCaseState"].some(str => + ["amendDocuments", "changeCaseState", "enterGenApp"].some(str => page.url().includes(str) )) { mappingPath = path.join(__dirname, '../../../data/page-data-figma/page-data-caseManagement-figma/urlToFileMappingCM.ts'); @@ -248,7 +248,7 @@ export class PageContentValidation implements IValidation { filePath = path.join(__dirname, '../../../data/page-data-figma/page-data-common-component', `${fileName}.page.data.ts`); } else if ( - ["amendDocuments", "changeCaseState"].some(str => + ["amendDocuments", "changeCaseState", "enterGenApp"].some(str => page.url().includes(str) )) { filePath = path.join(__dirname, '../../../data/page-data-figma/page-data-caseManagement-figma', `${fileName}.page.data.ts`); @@ -390,7 +390,7 @@ export class PageContentValidation implements IValidation { } else if(url.includes("makeAnApplication")){ mappingPath = path.join(__dirname, '../../../data/page-data-figma/page-data-genApps-figma/urlToFileMappingGenApps.ts'); } else if ( - ["amendDocuments", "changeCaseState"].some(str => + ["amendDocuments", "changeCaseState", "enterGenApp"].some(str => url.includes(str) )) { mappingPath = path.join(__dirname, '../../../data/page-data-figma/page-data-caseManagement-figma/urlToFileMappingCM.ts'); From 78d3a9c6b98481109d92a48264f25b5ae5c5d3d5 Mon Sep 17 00:00:00 2001 From: srinijg Date: Mon, 20 Jul 2026 11:35:44 +0100 Subject: [PATCH 62/70] error validations added --- ...enterGenAppapplicationDetails.page.data.ts | 11 +-- .../enterGenAppapplicationFee.page.data.ts | 6 ++ .../enterGenApphearingDate.page.data.ts | 16 +++++ .../page-data-caseManagement-figma/index.ts | 2 + .../urlToFileMappingCM.ts | 4 +- src/e2eTest/data/user-data/users.data.ts | 2 +- src/e2eTest/tests/caseTabs.spec.ts | 2 +- .../caseManagement.caseWorkerGenApps.spec.ts | 25 ++++--- .../caseManagement.action.ts | 67 +++++++++++++++---- .../caseManagementErrorValidation.action.ts | 33 ++++++++- .../caseManagementUtils.action.ts | 2 +- .../action-caseManagement.registry.ts | 3 + 12 files changed, 140 insertions(+), 33 deletions(-) create mode 100644 src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/enterGenAppapplicationFee.page.data.ts create mode 100644 src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/enterGenApphearingDate.page.data.ts diff --git a/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/enterGenAppapplicationDetails.page.data.ts b/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/enterGenAppapplicationDetails.page.data.ts index 0ab6644611..eed321baca 100644 --- a/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/enterGenAppapplicationDetails.page.data.ts +++ b/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/enterGenAppapplicationDetails.page.data.ts @@ -9,8 +9,10 @@ export const enterGenappApplication = { dayTextLabel: `Day`, monthTextLabel: `Month`, yearTextLabel: `Year`, + whichCategoriesHiddenLabel: `Which categories apply?`, errorValidation: `YES`, eventCouldNotBeCreatedErrorMessageHeader: `The event could not be created`, + thereIsProbErrorMessageHeader: `There is a problem`, errorValidationType: { one: `textField`, two: `radioOptions`, three: `checkBox`, four: `dropDown`, five: `dateField` }, errorValidationField: { errorRadioOption1: [ @@ -20,14 +22,15 @@ export const enterGenappApplication = { { type: `none`, input: ``, errMessage: `Which type of application has the applicant made? is required`, errInlineMessage: `Which type of application has the applicant made? is required` }, ], errorDateField: [ - { type: `empty`, input: `EMPTY`, errMessage: `What date was the application received? is required `,errInlineMessage: `Which type of application has the applicant made? is required`}, + { type: `empty`, input: `empty`, errMessage: `What date was the application received? is required`,errInlineMessage: `What date was the application received? is required`}, { type: `invalid`, input: `invalid`, errMessage: `What date was the application received? is not valid `,errInlineMessage: `The data entered is not valid for What date was the application received?`}, - { type: `future`, input: 'future', errMessage: `Date the application was received must be in the past` }, - { type: `present`, input: 'present', errMessage: `Date the application was received must be in the past` }, + { type: `future`, input: 'future', errMessage: `Date the application was received must be in the past`, errInlineMessage: `The data entered is not valid for What date was the application received?` }, + { type: `present`, input: 'present', errMessage: `Date the application was received must be in the past`, errInlineMessage: `The data entered is not valid for What date was the application received?` }, + { type: `past`, input: 'past', errMessage: ``, errInlineMessage: `` }, ], errorTextField: [ - { type: `moreThanMax`, input: 505, errMessage: `In ‘How are they vulnerable?’, you have entered more than the maximum number of characters (6,800)` }, + { type: `moreThanMax`, input: 505, errMessage: `In ‘Which categories apply’, you have entered more than the maximum number of characters (500)` }, { type: `empty`, input: `EMPTY`, errMessage: `Which categories apply? is required `}, ] }, diff --git a/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/enterGenAppapplicationFee.page.data.ts b/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/enterGenAppapplicationFee.page.data.ts new file mode 100644 index 0000000000..d08bc9e6b0 --- /dev/null +++ b/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/enterGenAppapplicationFee.page.data.ts @@ -0,0 +1,6 @@ +export const enterGenAppapplicationFee = { + mainHeader: `Application fee`, + continueButton: `Save and continue`, + previousButton: `Previous`, + cancelLink: `Cancel`, +}; diff --git a/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/enterGenApphearingDate.page.data.ts b/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/enterGenApphearingDate.page.data.ts new file mode 100644 index 0000000000..baef91057e --- /dev/null +++ b/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/enterGenApphearingDate.page.data.ts @@ -0,0 +1,16 @@ +export const enterGenAppHearingDate = { + mainHeader: `Hearing date`, + hearingInNext14DaysQuestion: `Is there a hearing for this case in the next 14 days?`, + yesRadioOption: `Yes`, + noRadioOption: `No`, + errorValidation: `YES`, + errorValidationType: { one: `textField`, two: `radioOptions`, three: `checkBox`, four: `dropDown`, five: `dateField` }, + errorValidationField: { + errorRadioOption: [ + { type: `none`, input: ``, errMessage: `Is there a hearing for this case in the next 14 days? is required`, errInlineMessage: `Is there a hearing for this case in the next 14 days? is required` }, + ], + }, + continueButton: `Continue`, + previousButton: `Previous`, + cancelLink: `Cancel`, +}; diff --git a/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/index.ts b/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/index.ts index dd626c629f..61c900e31d 100644 --- a/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/index.ts +++ b/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/index.ts @@ -4,3 +4,5 @@ export * from './changeCaseState.page.data'; export * from './checkYourAnswersChangeState.page.data'; export * from './confirmCaseStateChange.page.data'; export * from './enterGenAppapplicationDetails.page.data'; +export * from './enterGenApphearingDate.page.data'; +export * from './enterGenAppapplicationFee.page.data'; diff --git a/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/urlToFileMappingCM.ts b/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/urlToFileMappingCM.ts index bc9ee544ba..df26755877 100644 --- a/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/urlToFileMappingCM.ts +++ b/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/urlToFileMappingCM.ts @@ -2,5 +2,7 @@ export default { 'amendDocumentsselectDocument': 'selectDocument', 'changeCaseStatechangeCaseStatePage': 'changeCaseState', 'changeCaseState/confirm': 'confirmCaseStateChange', - 'enterGenAppapplicationDetails': 'enterGenAppapplicationDetails' + 'enterGenAppapplicationDetails': 'enterGenAppapplicationDetails', + 'enterGenApphearingDate': 'enterGenApphearingDate', + 'enterGenAppapplicationFee': 'enterGenAppapplicationFee', }; \ No newline at end of file diff --git a/src/e2eTest/data/user-data/users.data.ts b/src/e2eTest/data/user-data/users.data.ts index 4650652c56..fecbdb7e4d 100644 --- a/src/e2eTest/data/user-data/users.data.ts +++ b/src/e2eTest/data/user-data/users.data.ts @@ -18,7 +18,7 @@ export const users = [{ }, { user: 'County Court Judge', - email: 'DDJ.Randell.Lesch@ejudiciary.net', + email: 'HHJ.Test.McGinn@judicialofficeelinkssw.onmicrosoft.com', password: process.env.IDAM_PCS_USER_PASSWORD, tabAccess: ['Case Parties', 'Case Details', 'Case File View', 'Summary', 'History', 'Service Request', 'Notes', 'Linked Cases', 'Case flags'] }, diff --git a/src/e2eTest/tests/caseTabs.spec.ts b/src/e2eTest/tests/caseTabs.spec.ts index e41cc8a9b4..39bfbe3017 100644 --- a/src/e2eTest/tests/caseTabs.spec.ts +++ b/src/e2eTest/tests/caseTabs.spec.ts @@ -116,7 +116,7 @@ test.describe('[Case tabs - England Journey] @nightly', async () => { const firstTab = pages[0]; await firstTab.bringToFront(); await dismissCookieBanner(page, 'additional'); - await performAction('login', { email: 'DDJ.Randell.Lesch@ejudiciary.net', password: process.env.IDAM_PCS_USER_PASSWORD, }); + await performAction('login', { email: 'HHJ.Test.McGinn@judicialofficeelinkssw.onmicrosoft.com', password: process.env.IDAM_PCS_USER_PASSWORD, }); await dismissCookieBanner(page, 'analytics'); await performAction('navigateToUrl', `${process.env.MANAGE_CASE_BASE_URL}/cases/case-details/PCS/${getCaseTypeId()}/${process.env.CASE_NUMBER}#Summary`); await performValidation('mainHeader', home.caseSummary); diff --git a/src/e2eTest/tests/test-caseManagement/caseManagement.caseWorkerGenApps.spec.ts b/src/e2eTest/tests/test-caseManagement/caseManagement.caseWorkerGenApps.spec.ts index 03ebf7e967..7af74ee2c1 100644 --- a/src/e2eTest/tests/test-caseManagement/caseManagement.caseWorkerGenApps.spec.ts +++ b/src/e2eTest/tests/test-caseManagement/caseManagement.caseWorkerGenApps.spec.ts @@ -7,7 +7,8 @@ import { caseSummary, user } from '@data/page-data'; import { dismissCookieBanner } from '@config/cookie-banner'; import { initializeCMExecutor, performAction, performValidation } from '@utils/controller-caseManagement'; import { allPartyDetails } from '@utils/actions/custom-actions/custom-actions-caseManagement'; -import { enterGenappApplication } from '@data/page-data-figma/page-data-caseManagement-figma'; +import { enterGenappApplication, enterGenAppapplicationFee, enterGenAppHearingDate } from '@data/page-data-figma/page-data-caseManagement-figma'; +import { label } from 'allure-js-commons'; test.use({ storageState: undefined }) @@ -45,12 +46,20 @@ test.describe('Case management - Case Worker Enter a General application @nightl await performAction('selectAnEvent', { eventType: caseSummary.enterAGenApp }); await performValidation('mainHeader', enterGenappApplication.mainHeader); await performAction('errorValidationEnterGeneralAppPage', enterGenappApplication.errorValidation); - // await performAction('changeCaseState', { - // question: changeCaseState.whichStateYouMovingCaseToQuestion, option: changeCaseState.caseStateHiddenOption, - // nextPage: checkYourAnswersChangeState.mainHeader - // }); - // await performAction('clickButton', checkYourAnswersChangeState.submitButton); - // await performAction('confirmCaseStateChange'); - // await performValidation('bannerAlert', 'Case #.* has been updated with event: Change case state'); + await performAction('enterApplicationDetails', { + question1: enterGenappApplication.whichPartyMadeAppQuestion, option1: allPartyDetails[0], + question2: enterGenappApplication.typeOfAppQuestion, option2: enterGenappApplication.adjournRadioOption, + label1: enterGenappApplication.dayTextLabel, + label2: enterGenappApplication.monthTextLabel, + label3: enterGenappApplication.yearTextLabel, + dateType: 'past', + nextPage: enterGenAppHearingDate.mainHeader + }) + await performAction('errorValidationHearingDatePage', enterGenAppHearingDate.errorValidation); + await performAction('confirmIfCourtHearingInNext14Days', { + question: enterGenAppHearingDate.hearingInNext14DaysQuestion, + option: enterGenAppHearingDate.yesRadioOption, + nextPage: enterGenAppapplicationFee.mainHeader + }); }); }); diff --git a/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagement.action.ts b/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagement.action.ts index e96f6bd817..e34a61d4c7 100644 --- a/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagement.action.ts +++ b/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagement.action.ts @@ -6,7 +6,7 @@ import { getCaseTypeId } from '@utils/common/caseType.utils'; import { performAction, performActions, performValidation } from '@utils/controller-caseManagement'; import { VERY_LONG_TIMEOUT } from 'playwright.config'; import { caseSummary, home } from '@data/page-data'; -import { changeCaseState, confirmCaseStateChange, selectDocument } from '@data/page-data-figma/page-data-caseManagement-figma'; +import { changeCaseState, confirmCaseStateChange, enterGenappApplication, enterGenAppHearingDate, selectDocument } from '@data/page-data-figma/page-data-caseManagement-figma'; import { caseInfo } from '../createCaseAPI.action'; import { CaseManagementCommonUtils } from './caseManagementUtils.action'; @@ -29,6 +29,8 @@ export class CaseManagementAction implements IAction { ['changeCaseState', () => this.changeCaseState(fieldName as actionRecord)], ['confirmCaseStateChange', () => this.confirmCaseStateChange()], ['getAllPartyDetails', () => this.getAllPartyDetails(fieldName as actionRecord)], + ['enterApplicationDetails', () => this.enterApplicationDetails(fieldName as actionRecord)], + ['confirmIfCourtHearingInNext14Days', () => this.confirmIfCourtHearingInNext14Days(fieldName as actionRecord)], ['inputErrorValidation', () => this.inputErrorValidation(page, fieldName as actionRecord)], ]); @@ -118,7 +120,29 @@ export class CaseManagementAction implements IAction { ...originalDefendantDetails.filter(n => n.trim().toLowerCase() === "null null") ]; allPartyDetails.push(`${payLoad.claimantName} - Claimant 1`); - console.log(allPartyDetails); + } + + private async enterApplicationDetails(appDetails: actionRecord) { + let date = CaseManagementCommonUtils.getRandomDate(appDetails.dateType as string); + await performAction('clickRadioButton', { question: appDetails.question1, option: appDetails.option1 }); + + await performActions('Enter Date', + ['inputText', appDetails.label1, date.split('/')[0]], + ['inputText', appDetails.label2, date.split('/')[1]], + ['inputText', appDetails.label3, date.split('/')[2]]); + await performAction('clickRadioButton', { question: appDetails.question2, option: appDetails.option2 }); + await performAction('reTryOnCallBackError', enterGenappApplication.continueButton, appDetails.nextPage as string); + + } + + private async confirmIfCourtHearingInNext14Days(courtHearing: actionRecord) { + await performValidation('text', { elementType: 'paragraph', text: 'Case number: ' + caseInfo.fid }); + await performValidation('text', { elementType: 'paragraph', text: `Property address: ${addressInfo.buildingStreet}, ${addressInfo.townCity}, ${addressInfo.engOrWalPostcode}` }); + await performAction('clickRadioButton', { + question: courtHearing.question, + option: courtHearing.option, + }); + await performAction('reTryOnCallBackError', enterGenAppHearingDate.continueButton, courtHearing.nextPage as string); } private async inputErrorValidation(page: Page, validationArr: actionRecord) { @@ -175,21 +199,36 @@ export class CaseManagementAction implements IAction { break; case 'dateField': - let date: string = ''; - if (item.input === 'empty') { + let date: string = CaseManagementCommonUtils.getRandomDate(item.type as string); + if (item.type === 'empty') { await performAction('clickButton', validationArr.button); - await performValidation('errorMessage', { header: validationArr.header, message: item.errMessage }); - } - else { - date = CaseManagementCommonUtils.getRandomDate(item.input); + await performValidation('inputError', !validationArr?.label ? validationArr.question : validationArr.label, item.errInlineMessage); + await performValidation('errorMessage', validationArr.header1, item.errMessage); + } else if (item.type === 'past') { + await performActions('Enter Date', + ['inputText', validationArr.label1, date.split('/')[0]], + ['inputText', validationArr.label2, date.split('/')[1]], + ['inputText', validationArr.label3, date.split('/')[2]]); + }else if(item.type === 'invalid'){ + await performActions('Enter Date', + ['inputText', validationArr.label1, date.split('/')[0]], + ['inputText', validationArr.label2, date.split('/')[1]], + ['inputText', validationArr.label3, date.split('/')[2]]); + await performAction('clickButton', validationArr.button); + await performValidation('errorMessage', validationArr.header1, item.errMessage ); + } + else { - await performActions('Enter Date', - ['inputText', validationArr.label, date.split('/')[0]], - ['inputText', validationArr.label, date.split('/')[1]], - ['inputText', validationArr.label, date.split('/')[2]]); - await performValidation('inputError', validationArr.label, item.errMessage); - await performValidation('errorMessage', validationArr.label, item.errMessage); + await performActions('Enter Date', + ['inputText', validationArr.label1, date.split('/')[0]], + ['inputText', validationArr.label2, date.split('/')[1]], + ['inputText', validationArr.label3, date.split('/')[2]]); + await performAction('clickButton', validationArr.button); + //await performValidation('inputError', !validationArr?.label ? validationArr.question : validationArr.label, item.errInlineMessage); + //await performValidation('errorMessage', !validationArr?.header ? validationArr.header = 'There is a problem' : validationArr.header, item.errMessage); + await performValidation('errorMessage', { header: validationArr.header, message: item.errMessage }); + } break; default: diff --git a/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagementErrorValidation.action.ts b/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagementErrorValidation.action.ts index 2afafc8561..4e96b2c94d 100644 --- a/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagementErrorValidation.action.ts +++ b/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagementErrorValidation.action.ts @@ -1,7 +1,7 @@ import { Page } from '@playwright/test'; import { performAction } from '@utils/controller-caseManagement'; import { IAction, actionData, actionRecord } from '@utils/interfaces/action.interface'; -import { changeCaseState, enterGenappApplication, selectDocument } from '@data/page-data-figma/page-data-caseManagement-figma'; +import { changeCaseState, enterGenappApplication, enterGenAppHearingDate, selectDocument } from '@data/page-data-figma/page-data-caseManagement-figma'; import { allPartyDetails } from './caseManagement.action'; export class ErrorValidationAction implements IAction { @@ -10,6 +10,7 @@ export class ErrorValidationAction implements IAction { ['errorValidationSelectDocumentPage', () => this.errorValidationSelectDocumentPage(errorFlag as string)], ['errorValidationChangeCaseStatePage', () => this.errorValidationChangeCaseStatePage(errorFlag as string)], ['errorValidationEnterGeneralAppPage', () => this.errorValidationEnterGeneralAppPage(errorFlag as string)], + ['errorValidationHearingDatePage', () => this.errorValidationHearingDatePage(errorFlag as string)], ]); const actionToPerform = actionsMap.get(action); @@ -57,23 +58,49 @@ export class ErrorValidationAction implements IAction { option: allPartyDetails[0], button: enterGenappApplication.continueButton }); + await performAction('inputErrorValidation', { validationType: enterGenappApplication.errorValidationType.two, inputArray: enterGenappApplication.errorValidationField.errorRadioOption2, question: enterGenappApplication.typeOfAppQuestion, - option: enterGenappApplication.somethingElseRadioOption, + option: enterGenappApplication.adjournRadioOption, button: enterGenappApplication.continueButton }); await performAction('inputErrorValidation', { validationType: enterGenappApplication.errorValidationType.five, - inputArray: enterGenappApplication.errorValidationField.errorTextField, + inputArray: enterGenappApplication.errorValidationField.errorDateField, header: enterGenappApplication.eventCouldNotBeCreatedErrorMessageHeader, + header1: enterGenappApplication.thereIsProbErrorMessageHeader, + question: enterGenappApplication.whatDateAppReceivedQuestion, label1: enterGenappApplication.dayTextLabel, label2: enterGenappApplication.monthTextLabel, label3: enterGenappApplication.yearTextLabel, button: enterGenappApplication.continueButton }); + await performAction('clickRadioButton', { + question: enterGenappApplication.typeOfAppQuestion, + option: enterGenappApplication.somethingElseRadioOption, + }); + await performAction('inputErrorValidation', { + validationType: enterGenappApplication.errorValidationType.one, + inputArray: enterGenappApplication.errorValidationField.errorTextField, + header: enterGenappApplication.eventCouldNotBeCreatedErrorMessageHeader, + label: enterGenappApplication.whichCategoriesHiddenLabel, + button: enterGenappApplication.continueButton + }); + + } + } + private async errorValidationHearingDatePage(validationReq: string) { + if (validationReq === 'YES') { + await performAction('inputErrorValidation', { + validationType: enterGenAppHearingDate.errorValidationType.two, + inputArray: enterGenAppHearingDate.errorValidationField.errorRadioOption, + question: enterGenAppHearingDate.hearingInNext14DaysQuestion, + option: enterGenAppHearingDate.yesRadioOption, + button: enterGenAppHearingDate.continueButton + }); } } diff --git a/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagementUtils.action.ts b/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagementUtils.action.ts index a067a8d6bb..475dae546d 100644 --- a/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagementUtils.action.ts +++ b/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagementUtils.action.ts @@ -75,7 +75,7 @@ export class CaseManagementCommonUtils { ); } else { minDate = new Date( - today.getFullYear() - 100, + today.getFullYear() - 10, today.getMonth(), today.getDate() ); diff --git a/src/e2eTest/utils/registry/registry-caseManagement/action-caseManagement.registry.ts b/src/e2eTest/utils/registry/registry-caseManagement/action-caseManagement.registry.ts index eb99b97eb4..84ee1ddf79 100644 --- a/src/e2eTest/utils/registry/registry-caseManagement/action-caseManagement.registry.ts +++ b/src/e2eTest/utils/registry/registry-caseManagement/action-caseManagement.registry.ts @@ -39,9 +39,12 @@ export class ActionCMRegistry { ['changeCaseState', new CaseManagementAction()], ['confirmCaseStateChange', new CaseManagementAction()], ['getAllPartyDetails', new CaseManagementAction()], + ['enterApplicationDetails', new CaseManagementAction()], + ['confirmIfCourtHearingInNext14Days', new CaseManagementAction()], ['errorValidationSelectDocumentPage', new ErrorValidationAction()], ['errorValidationChangeCaseStatePage', new ErrorValidationAction()], ['errorValidationEnterGeneralAppPage', new ErrorValidationAction()], + ['errorValidationHearingDatePage', new ErrorValidationAction()], ['inputErrorValidation', new CaseManagementAction()], ['reTryOnCallBackError', new RetryOnCallBackError()], From 29f5475c733a57f4e706c6af533c57991dd44bc1 Mon Sep 17 00:00:00 2001 From: srinijg Date: Mon, 20 Jul 2026 12:48:40 +0100 Subject: [PATCH 63/70] validations added --- ...enterGenAppapplicationDetails.page.data.ts | 6 ++- .../caseManagement.caseWorkerGenApps.spec.ts | 36 +++++++++++++++- .../caseManagement.action.ts | 42 +++++++++---------- .../caseManagementErrorValidation.action.ts | 2 +- 4 files changed, 59 insertions(+), 27 deletions(-) diff --git a/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/enterGenAppapplicationDetails.page.data.ts b/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/enterGenAppapplicationDetails.page.data.ts index eed321baca..e10cc005f7 100644 --- a/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/enterGenAppapplicationDetails.page.data.ts +++ b/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/enterGenAppapplicationDetails.page.data.ts @@ -9,11 +9,13 @@ export const enterGenappApplication = { dayTextLabel: `Day`, monthTextLabel: `Month`, yearTextLabel: `Year`, - whichCategoriesHiddenLabel: `Which categories apply?`, + dateTypeHiddenUserInput: 'past', + whichCategoriesHiddenTextLabel: `Which categories apply?`, + whichCategoriesHiddenTextInput: 400, errorValidation: `YES`, eventCouldNotBeCreatedErrorMessageHeader: `The event could not be created`, thereIsProbErrorMessageHeader: `There is a problem`, - errorValidationType: { one: `textField`, two: `radioOptions`, three: `checkBox`, four: `dropDown`, five: `dateField` }, + errorValidationType: { one: `textField`, two: `radioOptions`, three: `checkBox`, four: `dropDown`, five: `appReceivedDateField` }, errorValidationField: { errorRadioOption1: [ { type: `none`, input: ``, errMessage: `Which party made the application? is required`, errInlineMessage: `Field is required` }, diff --git a/src/e2eTest/tests/test-caseManagement/caseManagement.caseWorkerGenApps.spec.ts b/src/e2eTest/tests/test-caseManagement/caseManagement.caseWorkerGenApps.spec.ts index 7af74ee2c1..c59d621bce 100644 --- a/src/e2eTest/tests/test-caseManagement/caseManagement.caseWorkerGenApps.spec.ts +++ b/src/e2eTest/tests/test-caseManagement/caseManagement.caseWorkerGenApps.spec.ts @@ -49,10 +49,12 @@ test.describe('Case management - Case Worker Enter a General application @nightl await performAction('enterApplicationDetails', { question1: enterGenappApplication.whichPartyMadeAppQuestion, option1: allPartyDetails[0], question2: enterGenappApplication.typeOfAppQuestion, option2: enterGenappApplication.adjournRadioOption, + label: enterGenappApplication.whichCategoriesHiddenTextLabel, + input: enterGenappApplication.whichCategoriesHiddenTextInput, label1: enterGenappApplication.dayTextLabel, label2: enterGenappApplication.monthTextLabel, label3: enterGenappApplication.yearTextLabel, - dateType: 'past', + dateType: enterGenappApplication.dateTypeHiddenUserInput, nextPage: enterGenAppHearingDate.mainHeader }) await performAction('errorValidationHearingDatePage', enterGenAppHearingDate.errorValidation); @@ -62,4 +64,36 @@ test.describe('Case management - Case Worker Enter a General application @nightl nextPage: enterGenAppapplicationFee.mainHeader }); }); + + test('Case management - Case Worker Enter a General application SET ASIDE Journey @CM', async () => { + await performAction('selectAnEvent', { eventType: caseSummary.enterAGenApp }); + await performValidation('mainHeader', enterGenappApplication.mainHeader); + await performAction('enterApplicationDetails', { + question1: enterGenappApplication.whichPartyMadeAppQuestion, option1: allPartyDetails[1], + question2: enterGenappApplication.typeOfAppQuestion, option2: enterGenappApplication.setAsideRadioOption, + label: enterGenappApplication.whichCategoriesHiddenTextLabel, + input: enterGenappApplication.whichCategoriesHiddenTextInput, + label1: enterGenappApplication.dayTextLabel, + label2: enterGenappApplication.monthTextLabel, + label3: enterGenappApplication.yearTextLabel, + dateType: enterGenappApplication.dateTypeHiddenUserInput, + nextPage: enterGenAppapplicationFee.mainHeader + }) + }); + + test('Case management - Case Worker Enter a General application SOMETHING ELSE Journey @CM', async () => { + await performAction('selectAnEvent', { eventType: caseSummary.enterAGenApp }); + await performValidation('mainHeader', enterGenappApplication.mainHeader); + await performAction('enterApplicationDetails', { + question1: enterGenappApplication.whichPartyMadeAppQuestion, option1: allPartyDetails[2], + question2: enterGenappApplication.typeOfAppQuestion, option2: enterGenappApplication.somethingElseRadioOption, + label: enterGenappApplication.whichCategoriesHiddenTextLabel, + input: enterGenappApplication.whichCategoriesHiddenTextInput, + label1: enterGenappApplication.dayTextLabel, + label2: enterGenappApplication.monthTextLabel, + label3: enterGenappApplication.yearTextLabel, + dateType: enterGenappApplication.dateTypeHiddenUserInput, + nextPage: enterGenAppapplicationFee.mainHeader + }) + }); }); diff --git a/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagement.action.ts b/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagement.action.ts index e34a61d4c7..90d399f9d2 100644 --- a/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagement.action.ts +++ b/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagement.action.ts @@ -131,6 +131,9 @@ export class CaseManagementAction implements IAction { ['inputText', appDetails.label2, date.split('/')[1]], ['inputText', appDetails.label3, date.split('/')[2]]); await performAction('clickRadioButton', { question: appDetails.question2, option: appDetails.option2 }); + if (appDetails.option2 === 'Something else') { + performAction('inputText', appDetails.label, CaseManagementCommonUtils.generateRandomString(appDetails.input as number)) + } await performAction('reTryOnCallBackError', enterGenappApplication.continueButton, appDetails.nextPage as string); } @@ -147,11 +150,9 @@ export class CaseManagementAction implements IAction { private async inputErrorValidation(page: Page, validationArr: actionRecord) { - if (Array.isArray(validationArr.inputArray)) { for (const item of validationArr.inputArray) { switch (validationArr.validationType) { - case 'radioOptions': await performAction('clickButton', validationArr.button); await performValidation('inputError', !validationArr?.label ? validationArr.question : validationArr.label, item.errInlineMessage); @@ -198,35 +199,30 @@ export class CaseManagementAction implements IAction { }); break; - case 'dateField': + case 'appReceivedDateField': let date: string = CaseManagementCommonUtils.getRandomDate(item.type as string); + const enterDate = () => + performActions( + 'Enter Date', + ['inputText', validationArr.label1, date.split('/')[0]], + ['inputText', validationArr.label2, date.split('/')[1]], + ['inputText', validationArr.label3, date.split('/')[2]] + ); + if (item.type === 'empty') { await performAction('clickButton', validationArr.button); await performValidation('inputError', !validationArr?.label ? validationArr.question : validationArr.label, item.errInlineMessage); await performValidation('errorMessage', validationArr.header1, item.errMessage); } else if (item.type === 'past') { - await performActions('Enter Date', - ['inputText', validationArr.label1, date.split('/')[0]], - ['inputText', validationArr.label2, date.split('/')[1]], - ['inputText', validationArr.label3, date.split('/')[2]]); - }else if(item.type === 'invalid'){ - await performActions('Enter Date', - ['inputText', validationArr.label1, date.split('/')[0]], - ['inputText', validationArr.label2, date.split('/')[1]], - ['inputText', validationArr.label3, date.split('/')[2]]); - await performAction('clickButton', validationArr.button); - await performValidation('errorMessage', validationArr.header1, item.errMessage ); - + await enterDate(); + } else if (item.type === 'invalid') { + await enterDate(); + await performAction('clickButton', validationArr.button); + await performValidation('errorMessage', validationArr.header1, item.errMessage); } - else { - - await performActions('Enter Date', - ['inputText', validationArr.label1, date.split('/')[0]], - ['inputText', validationArr.label2, date.split('/')[1]], - ['inputText', validationArr.label3, date.split('/')[2]]); + else { + await enterDate(); await performAction('clickButton', validationArr.button); - //await performValidation('inputError', !validationArr?.label ? validationArr.question : validationArr.label, item.errInlineMessage); - //await performValidation('errorMessage', !validationArr?.header ? validationArr.header = 'There is a problem' : validationArr.header, item.errMessage); await performValidation('errorMessage', { header: validationArr.header, message: item.errMessage }); } break; diff --git a/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagementErrorValidation.action.ts b/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagementErrorValidation.action.ts index 4e96b2c94d..5cb952761e 100644 --- a/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagementErrorValidation.action.ts +++ b/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagementErrorValidation.action.ts @@ -85,7 +85,7 @@ export class ErrorValidationAction implements IAction { validationType: enterGenappApplication.errorValidationType.one, inputArray: enterGenappApplication.errorValidationField.errorTextField, header: enterGenappApplication.eventCouldNotBeCreatedErrorMessageHeader, - label: enterGenappApplication.whichCategoriesHiddenLabel, + label: enterGenappApplication.whichCategoriesHiddenTextLabel, button: enterGenappApplication.continueButton }); From b3d94ecfc7683684ed4531a79fe4e05628f3e77a Mon Sep 17 00:00:00 2001 From: srinijg Date: Mon, 20 Jul 2026 16:04:12 +0100 Subject: [PATCH 64/70] remove tests --- ...seManagement.caseWorkerChangeState.spec.ts | 58 ------------------- 1 file changed, 58 deletions(-) delete mode 100644 src/e2eTest/tests/test-caseManagement/caseManagement.caseWorkerChangeState.spec.ts diff --git a/src/e2eTest/tests/test-caseManagement/caseManagement.caseWorkerChangeState.spec.ts b/src/e2eTest/tests/test-caseManagement/caseManagement.caseWorkerChangeState.spec.ts deleted file mode 100644 index 79d601ca28..0000000000 --- a/src/e2eTest/tests/test-caseManagement/caseManagement.caseWorkerChangeState.spec.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { createCaseApiData, makeAnApplicationApiData, submitCaseApiData } from '@data/api-data'; -import { initializeExecutor, performValidation } from '@utils/controller'; -import test from '@playwright/test'; -import { caseInfo, defendantUserDetails } from '@utils/actions/custom-actions'; -import { PageContentValidation } from '@utils/validations/element-validations/pageContent.validation'; -import { caseSummary, user } from '@data/page-data'; -import { dismissCookieBanner } from '@config/cookie-banner'; -import { initializeCMExecutor, performAction } from '@utils/controller-caseManagement'; -import { changeCaseState, checkYourAnswersChangeState } from '@data/page-data-figma/page-data-caseManagement-figma'; - -test.use({ storageState: undefined }) - -test.beforeEach(async ({ page, context }) => { - await context.clearCookies(); - initializeExecutor(page); - initializeCMExecutor(page); - await performAction('createCaseAPI', { data: createCaseApiData.createCasePayload }); - await performAction('submitCaseAPI', { data: submitCaseApiData.submitCasePayloadCaseFileView }); - await performAction('updatePaymentAPI'); - await performAction('getCaseAPI', 'Link Solicitor'); - - for (const defendant of defendantUserDetails) { - await performAction('makeAnApplicationAPI', { - data: makeAnApplicationApiData.makeAnApplicationAdjournPayload( - defendant.id, - defendant.name - ), - }); - }; - await performAction('navigateToUrl', process.env.MANAGE_CASE_BASE_URL); - await dismissCookieBanner(page, 'additional'); - await performAction('login', user.staffAdmin); - await dismissCookieBanner(page, 'analytics'); - await performAction('navigateToSummaryPage'); -}); - -test.afterEach(async () => { - if (caseInfo.id) { - await performAction('deleteCaseRole', '[CLAIMANTSOLICITOR]'); - } - PageContentValidation.finaliseTest(); - -}); - -test.describe('Case management - Case Worker change case state @nightly', async () => { - test('Case management - Case Worker change case state @CM @regression', async () => { - await performAction('selectAnEvent', { eventType: caseSummary.changeCaseState }); - await performValidation('mainHeader', changeCaseState.mainHeader); - await performAction('errorValidationChangeCaseStatePage', changeCaseState.errorValidation); - await performAction('changeCaseState', { - question: changeCaseState.whichStateYouMovingCaseToQuestion, option: changeCaseState.caseStateHiddenOption, - nextPage: checkYourAnswersChangeState.mainHeader - }); - await performAction('clickButton', checkYourAnswersChangeState.submitButton); - await performAction('confirmCaseStateChange'); - await performValidation('bannerAlert', 'Case #.* has been updated with event: Change case state'); - }); -}); From 6e557d87899931fe8f37f283fde70c937a5b036b Mon Sep 17 00:00:00 2001 From: srinijg Date: Mon, 20 Jul 2026 16:49:01 +0100 Subject: [PATCH 65/70] merge conflicts --- .../uk/gov/hmcts/reform/pcs/ccd/CaseType.java | 1 - .../pcs/ccd/accesscontrol/AccessGrants.java | 2 - .../pcs/ccd/accesscontrol/AccessProfile.java | 11 ++- .../pcs/ccd/domain/CaseStateOption.java | 32 -------- .../hmcts/reform/pcs/ccd/domain/PCSCase.java | 7 -- .../hmcts/reform/pcs/ccd/domain/State.java | 69 +--------------- .../changecasestate/ChangeCaseState.java | 78 ------------------- .../changecasestate/ChangeCaseStatePage.java | 23 ------ .../accesscontrol/CaseworkerRolesTest.java | 27 ------- .../pcs/ccd/domain/CaseStateOptionTest.java | 16 ---- .../changecasestate/ChangeCaseStateTest.java | 76 ------------------ 11 files changed, 7 insertions(+), 335 deletions(-) delete mode 100644 src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/CaseStateOption.java delete mode 100644 src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/changecasestate/ChangeCaseState.java delete mode 100644 src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/changecasestate/ChangeCaseStatePage.java delete mode 100644 src/test/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/CaseworkerRolesTest.java delete mode 100644 src/test/java/uk/gov/hmcts/reform/pcs/ccd/domain/CaseStateOptionTest.java delete mode 100644 src/test/java/uk/gov/hmcts/reform/pcs/ccd/event/changecasestate/ChangeCaseStateTest.java diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/CaseType.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/CaseType.java index e7abb69988..76340feb7d 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/CaseType.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/CaseType.java @@ -33,7 +33,6 @@ public class CaseType implements CCDConfig { AccessProfile.CITIZEN, AccessProfile.DEFENDANT, AccessProfile.PCS_SOLICITOR, - AccessProfile.PCS_CASE_WORKER, AccessProfile.JUDGE, AccessProfile.FEE_PAID_JUDGE, AccessProfile.CIRCUIT_JUDGE, diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/AccessGrants.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/AccessGrants.java index 33882d4cfb..2040c1352c 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/AccessGrants.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/AccessGrants.java @@ -15,7 +15,6 @@ import static uk.gov.hmcts.reform.pcs.ccd.accesscontrol.UserRole.HEARING_CENTRE_ADMIN; import static uk.gov.hmcts.reform.pcs.ccd.accesscontrol.UserRole.JUDGE; import static uk.gov.hmcts.reform.pcs.ccd.accesscontrol.UserRole.LEADERSHIP_JUDGE; -import static uk.gov.hmcts.reform.pcs.ccd.accesscontrol.UserRole.PCS_CASE_WORKER; import static uk.gov.hmcts.reform.pcs.ccd.accesscontrol.UserRole.PCS_SOLICITOR; import static uk.gov.hmcts.reform.pcs.ccd.accesscontrol.UserRole.WLU_ADMIN; @@ -25,7 +24,6 @@ final class AccessGrants { CITIZEN, DEFENDANT, PCS_SOLICITOR, - PCS_CASE_WORKER, JUDGE, FEE_PAID_JUDGE, CIRCUIT_JUDGE, diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/AccessProfile.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/AccessProfile.java index 9218e2726f..f2fb204fb9 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/AccessProfile.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/AccessProfile.java @@ -1,16 +1,15 @@ package uk.gov.hmcts.reform.pcs.ccd.accesscontrol; +import static java.util.Arrays.stream; +import static uk.gov.hmcts.ccd.sdk.api.Permission.CRU; +import static uk.gov.hmcts.ccd.sdk.api.Permission.R; + import com.fasterxml.jackson.annotation.JsonValue; +import java.util.Set; import lombok.Getter; import uk.gov.hmcts.ccd.sdk.api.HasRole; import uk.gov.hmcts.ccd.sdk.api.Permission; -import java.util.Set; - -import static java.util.Arrays.stream; -import static uk.gov.hmcts.ccd.sdk.api.Permission.CRU; -import static uk.gov.hmcts.ccd.sdk.api.Permission.R; - @Getter public enum AccessProfile implements HasRole { diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/CaseStateOption.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/CaseStateOption.java deleted file mode 100644 index d9230aeac6..0000000000 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/CaseStateOption.java +++ /dev/null @@ -1,32 +0,0 @@ -package uk.gov.hmcts.reform.pcs.ccd.domain; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import uk.gov.hmcts.ccd.sdk.api.HasLabel; - - -/** - * Representation of selectable case states for the Change Case State event. - * Each constant here MUST have a matching constant of the same name in {@link State}. - */ -@Getter -@AllArgsConstructor -public enum CaseStateOption implements HasLabel { - - JUDICIAL_REFERRAL("Judicial Referral"), - HEARING_READINESS("Hearing Readiness"), - PREPARE_FOR_HEARING_CONDUCT_HEARING("Prepare For Hearing Conduct Hearing"), - DECISION_OUTCOME("Decision Outcome"), - CASE_PROGRESSION("Case Progression"), - ALL_FINAL_ORDERS_ISSUED("All Final Orders"), - CASE_STAYED("Case Stayed"), - BREATHING_SPACE("Breathing space"); - - private final String label; - - // Converts to the matching State constant — constant names must stay in sync with State enum - public State toState() { - return State.valueOf(this.name()); - } - -} diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/PCSCase.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/PCSCase.java index edf128b6a3..af05ecaabc 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/PCSCase.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/PCSCase.java @@ -72,7 +72,6 @@ import static uk.gov.hmcts.ccd.sdk.type.FieldType.Collection; import static uk.gov.hmcts.ccd.sdk.type.FieldType.DynamicRadioList; -import static uk.gov.hmcts.ccd.sdk.type.FieldType.FixedList; import static uk.gov.hmcts.ccd.sdk.type.FieldType.MultiSelectList; import static uk.gov.hmcts.ccd.sdk.type.FieldType.TextArea; @@ -740,10 +739,4 @@ public class PCSCase { @CCD private String dateIssuedString; - - @CCD(label = "Which state are you moving the case to?", - typeOverride = FixedList, - typeParameterOverride = "CaseStateOption" - ) - private CaseStateOption targetState; } diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/State.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/State.java index 0e2a2ed6f5..7a61d9cf7e 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/State.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/State.java @@ -7,8 +7,8 @@ import uk.gov.hmcts.reform.pcs.ccd.accesscontrol.CitizenAccess; import uk.gov.hmcts.reform.pcs.ccd.accesscontrol.ClaimantAccess; import uk.gov.hmcts.reform.pcs.ccd.accesscontrol.DefendantAccess; -import uk.gov.hmcts.reform.pcs.ccd.accesscontrol.GlobalSearchAccess; import uk.gov.hmcts.reform.pcs.ccd.accesscontrol.InternalCaseFlagAccess; +import uk.gov.hmcts.reform.pcs.ccd.accesscontrol.GlobalSearchAccess; import uk.gov.hmcts.reform.pcs.ccd.accesscontrol.RasValidationAccess; /** @@ -40,70 +40,5 @@ public enum State { GlobalSearchAccess.class}, hint = "${caseTitleMarkdown}" ) - CASE_ISSUED, - - @CCD( - label = "Judicial Referral", - access = {CaseworkerReadAccess.class, ClaimantAccess.class, RasValidationAccess.class, - GlobalSearchAccess.class}, - hint = "${caseTitleMarkdown}" - ) - JUDICIAL_REFERRAL, - - @CCD( - label = "Hearing Readiness", - access = {CaseworkerReadAccess.class, ClaimantAccess.class, RasValidationAccess.class, - GlobalSearchAccess.class}, - hint = "${caseTitleMarkdown}" - ) - HEARING_READINESS, - - @CCD( - label = "Prepare For Hearing Conduct Hearing", - access = {CaseworkerReadAccess.class, ClaimantAccess.class, RasValidationAccess.class, - GlobalSearchAccess.class}, - hint = "${caseTitleMarkdown}" - ) - PREPARE_FOR_HEARING_CONDUCT_HEARING, - - @CCD( - label = "Decision Outcome", - access = {CaseworkerReadAccess.class, ClaimantAccess.class, RasValidationAccess.class, - GlobalSearchAccess.class}, - hint = "${caseTitleMarkdown}" - ) - DECISION_OUTCOME, - - @CCD( - label = "Case Progression", - access = {CaseworkerReadAccess.class, ClaimantAccess.class, RasValidationAccess.class, - GlobalSearchAccess.class}, - hint = "${caseTitleMarkdown}" - ) - CASE_PROGRESSION, - - @CCD( - label = "All Final Orders", - access = {CaseworkerReadAccess.class, ClaimantAccess.class, RasValidationAccess.class, - GlobalSearchAccess.class}, - hint = "${caseTitleMarkdown}" - ) - ALL_FINAL_ORDERS_ISSUED, - - @CCD( - label = "Case Stayed", - access = {CaseworkerReadAccess.class, ClaimantAccess.class, RasValidationAccess.class, - GlobalSearchAccess.class}, - hint = "${caseTitleMarkdown}" - ) - CASE_STAYED, - - @CCD( - label = "Breathing Space", - access = {CaseworkerReadAccess.class, ClaimantAccess.class, RasValidationAccess.class, - GlobalSearchAccess.class}, - hint = "${caseTitleMarkdown}" - ) - BREATHING_SPACE + CASE_ISSUED } - diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/changecasestate/ChangeCaseState.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/changecasestate/ChangeCaseState.java deleted file mode 100644 index 3b1246a12c..0000000000 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/changecasestate/ChangeCaseState.java +++ /dev/null @@ -1,78 +0,0 @@ -package uk.gov.hmcts.reform.pcs.ccd.event.changecasestate; - -import lombok.AllArgsConstructor; -import org.springframework.stereotype.Component; -import uk.gov.hmcts.ccd.sdk.api.CCDConfig; -import uk.gov.hmcts.ccd.sdk.api.DecentralisedConfigBuilder; -import uk.gov.hmcts.ccd.sdk.api.Event; -import uk.gov.hmcts.ccd.sdk.api.EventPayload; -import uk.gov.hmcts.ccd.sdk.api.Permission; -import uk.gov.hmcts.ccd.sdk.api.callback.SubmitResponse; -import uk.gov.hmcts.reform.pcs.ccd.accesscontrol.UserRole; -import uk.gov.hmcts.reform.pcs.ccd.common.PageBuilder; -import uk.gov.hmcts.reform.pcs.ccd.domain.PCSCase; -import uk.gov.hmcts.reform.pcs.ccd.domain.State; -import uk.gov.hmcts.reform.pcs.ccd.page.changecasestate.ChangeCaseStatePage; -import uk.gov.hmcts.reform.pcs.ccd.util.AddressFormatter; - -import static uk.gov.hmcts.reform.pcs.ccd.accesscontrol.CaseworkerRoles.CASEWORKER_ROLES; -import static uk.gov.hmcts.reform.pcs.ccd.event.EventId.changeCaseState; -import static uk.gov.hmcts.reform.pcs.ccd.util.AddressFormatter.COMMA_DELIMITER; - -@Component -@AllArgsConstructor -public class ChangeCaseState implements CCDConfig { - - private final AddressFormatter addressFormatter; - - @Override - public void configureDecentralised(DecentralisedConfigBuilder configBuilder) { - Event.EventBuilder eventBuilder = configBuilder - .decentralisedEvent(changeCaseState.name(), this::submit) - .forStates( - State.CASE_ISSUED, - State.JUDICIAL_REFERRAL, - State.HEARING_READINESS, - State.PREPARE_FOR_HEARING_CONDUCT_HEARING, - State.DECISION_OUTCOME, - State.CASE_PROGRESSION, - State.ALL_FINAL_ORDERS_ISSUED, - State.CASE_STAYED, - State.BREATHING_SPACE - ) - .name("Change case state") - .grant(Permission.CRUD, CASEWORKER_ROLES) - .grantHistoryOnly(UserRole.CIRCUIT_JUDGE, UserRole.FEE_PAID_JUDGE, - UserRole.JUDGE, UserRole.LEADERSHIP_JUDGE) - .showSummary() - .endButtonLabel("Submit"); - - new PageBuilder(eventBuilder) - .add(new ChangeCaseStatePage()); - } - - private SubmitResponse submit(EventPayload eventPayload) { - PCSCase pcsCase = eventPayload.caseData(); - State targetState = pcsCase.getTargetState().toState(); - return SubmitResponse.builder() - .state(targetState) - .confirmationBody(buildConfirmationMarkdown(pcsCase, eventPayload.caseReference())) - .build(); - } - - private String buildConfirmationMarkdown(PCSCase pcsCase, long caseReference) { - String address = addressFormatter.formatShortAddress(pcsCase.getPropertyAddress(), COMMA_DELIMITER); - return """ - --- -
- Case state changed
- Case number: %s
- Property address: %s -
- -

What happens next

-

The case will progress according to the state it has been - changed to.

- """.formatted(caseReference, address); - } -} diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/changecasestate/ChangeCaseStatePage.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/changecasestate/ChangeCaseStatePage.java deleted file mode 100644 index f0bfbc66ed..0000000000 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/changecasestate/ChangeCaseStatePage.java +++ /dev/null @@ -1,23 +0,0 @@ -package uk.gov.hmcts.reform.pcs.ccd.page.changecasestate; - -import lombok.AllArgsConstructor; -import org.springframework.stereotype.Component; -import uk.gov.hmcts.reform.pcs.ccd.common.CcdPageConfiguration; -import uk.gov.hmcts.reform.pcs.ccd.common.PageBuilder; -import uk.gov.hmcts.reform.pcs.ccd.domain.PCSCase; - - -@AllArgsConstructor -@Component -public class ChangeCaseStatePage implements CcdPageConfiguration { - - @Override - public void addTo(PageBuilder pageBuilder) { - pageBuilder.page("changeCaseStatePage") - .pageLabel("Case state to change to") - .label("changeCaseStatePage-lineSeparator", "---") - .label("changeCaseState-currentState", "Current state: ${[STATE]}") - .mandatory(PCSCase::getTargetState); - } - -} diff --git a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/CaseworkerRolesTest.java b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/CaseworkerRolesTest.java deleted file mode 100644 index 0c29c0d95a..0000000000 --- a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/CaseworkerRolesTest.java +++ /dev/null @@ -1,27 +0,0 @@ -package uk.gov.hmcts.reform.pcs.ccd.accesscontrol; - -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; -import static uk.gov.hmcts.reform.pcs.ccd.accesscontrol.CaseworkerRoles.CASEWORKER_ROLES; -import static uk.gov.hmcts.reform.pcs.ccd.accesscontrol.UserRole.CTSC_ADMIN; -import static uk.gov.hmcts.reform.pcs.ccd.accesscontrol.UserRole.CTSC_TEAM_LEADER; -import static uk.gov.hmcts.reform.pcs.ccd.accesscontrol.UserRole.HEARING_CENTRE_ADMIN; -import static uk.gov.hmcts.reform.pcs.ccd.accesscontrol.UserRole.HEARING_CENTRE_TEAM_LEADER; -import static uk.gov.hmcts.reform.pcs.ccd.accesscontrol.UserRole.WLU_ADMIN; -import static uk.gov.hmcts.reform.pcs.ccd.accesscontrol.UserRole.WLU_TEAM_LEADER; - -class CaseworkerRolesTest { - - @Test - void shouldContainAllCaseworkerRasRoles() { - assertThat(CASEWORKER_ROLES).containsExactlyInAnyOrder( - HEARING_CENTRE_TEAM_LEADER, - HEARING_CENTRE_ADMIN, - CTSC_TEAM_LEADER, - CTSC_ADMIN, - WLU_TEAM_LEADER, - WLU_ADMIN - ); - } -} diff --git a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/domain/CaseStateOptionTest.java b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/domain/CaseStateOptionTest.java deleted file mode 100644 index 1475f6e163..0000000000 --- a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/domain/CaseStateOptionTest.java +++ /dev/null @@ -1,16 +0,0 @@ -package uk.gov.hmcts.reform.pcs.ccd.domain; - -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.EnumSource; - -import static org.assertj.core.api.Assertions.assertThatCode; - -class CaseStateOptionTest { - - @ParameterizedTest - @EnumSource(CaseStateOption.class) - void shouldConvertToMatchingStateWithoutThrowing(CaseStateOption caseStateOption) { - assertThatCode(caseStateOption::toState).doesNotThrowAnyException(); - } - -} \ No newline at end of file diff --git a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/event/changecasestate/ChangeCaseStateTest.java b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/event/changecasestate/ChangeCaseStateTest.java deleted file mode 100644 index 26d469c42e..0000000000 --- a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/event/changecasestate/ChangeCaseStateTest.java +++ /dev/null @@ -1,76 +0,0 @@ -package uk.gov.hmcts.reform.pcs.ccd.event.changecasestate; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.EnumSource; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; -import uk.gov.hmcts.ccd.sdk.api.callback.SubmitResponse; -import uk.gov.hmcts.reform.pcs.ccd.domain.CaseStateOption; -import uk.gov.hmcts.reform.pcs.ccd.domain.PCSCase; -import uk.gov.hmcts.reform.pcs.ccd.domain.State; -import uk.gov.hmcts.reform.pcs.ccd.event.BaseEventTest; -import uk.gov.hmcts.reform.pcs.ccd.util.AddressFormatter; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.ArgumentMatchers.isNull; -import static org.mockito.Mockito.when; -import static uk.gov.hmcts.reform.pcs.ccd.util.AddressFormatter.COMMA_DELIMITER; - -@ExtendWith(MockitoExtension.class) -class ChangeCaseStateTest extends BaseEventTest { - - private static final String FORMATTED_ADDRESS = "1 Test Street, London, SW1A 1AA"; - - @Mock - private AddressFormatter addressFormatter; - - @InjectMocks - private ChangeCaseState changeCaseState; - - @BeforeEach - void setUp() { - setEventUnderTest(changeCaseState); - when(addressFormatter.formatShortAddress(isNull(), eq(COMMA_DELIMITER))) - .thenReturn(FORMATTED_ADDRESS); - } - - @ParameterizedTest - @EnumSource(CaseStateOption.class) - void shouldTransitionToSelectedTargetState(CaseStateOption targetState) { - PCSCase pcsCase = PCSCase.builder() - .targetState(targetState) - .build(); - - SubmitResponse response = callSubmitHandler(pcsCase); - - assertThat(response.getState()).isEqualTo(targetState.toState()); - } - - @Test - void shouldIncludeCaseReferenceInConfirmationBody() { - PCSCase pcsCase = PCSCase.builder() - .targetState(CaseStateOption.JUDICIAL_REFERRAL) - .build(); - - SubmitResponse response = callSubmitHandler(pcsCase); - - assertThat(response.getConfirmationBody()) - .contains(String.valueOf(TEST_CASE_REFERENCE)); - } - - @Test - void shouldIncludeFormattedAddressInConfirmationBody() { - PCSCase pcsCase = PCSCase.builder() - .targetState(CaseStateOption.HEARING_READINESS) - .build(); - - SubmitResponse response = callSubmitHandler(pcsCase); - - assertThat(response.getConfirmationBody()).contains(FORMATTED_ADDRESS); - } -} \ No newline at end of file From ce4a8874e59bbe78aee2e6f37b9a7d5a4e9b7d63 Mon Sep 17 00:00:00 2001 From: srinijg Date: Mon, 20 Jul 2026 16:50:15 +0100 Subject: [PATCH 66/70] spacing adjustment --- src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/State.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/State.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/State.java index 7a61d9cf7e..8c8da441cd 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/State.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/State.java @@ -41,4 +41,4 @@ public enum State { hint = "${caseTitleMarkdown}" ) CASE_ISSUED -} +} \ No newline at end of file From 44bbde9b54873cc370aa8c9b803a071d61f58aae Mon Sep 17 00:00:00 2001 From: srinijg Date: Mon, 20 Jul 2026 16:51:09 +0100 Subject: [PATCH 67/70] spacing --- src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/State.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/State.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/State.java index 8c8da441cd..7a61d9cf7e 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/State.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/State.java @@ -41,4 +41,4 @@ public enum State { hint = "${caseTitleMarkdown}" ) CASE_ISSUED -} \ No newline at end of file +} From d211b268bb61214b9b230a4712096bcf9fd3c39c Mon Sep 17 00:00:00 2001 From: srinijg Date: Mon, 20 Jul 2026 16:53:35 +0100 Subject: [PATCH 68/70] adjusting space --- src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/State.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/State.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/State.java index 7a61d9cf7e..8c8da441cd 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/State.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/State.java @@ -41,4 +41,4 @@ public enum State { hint = "${caseTitleMarkdown}" ) CASE_ISSUED -} +} \ No newline at end of file From 1e0c3e361395113bad814b1218a3854c259630af Mon Sep 17 00:00:00 2001 From: srinijg Date: Mon, 20 Jul 2026 16:55:48 +0100 Subject: [PATCH 69/70] spacing --- src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/State.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/State.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/State.java index 8c8da441cd..32aeec350c 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/State.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/State.java @@ -41,4 +41,5 @@ public enum State { hint = "${caseTitleMarkdown}" ) CASE_ISSUED -} \ No newline at end of file +} + From f8dc5c19e679941f669b9d6c95b22fb17072a2b1 Mon Sep 17 00:00:00 2001 From: srinijg Date: Mon, 20 Jul 2026 21:05:35 +0100 Subject: [PATCH 70/70] field updated --- .../enterGenAppapplicationDetails.page.data.ts | 2 +- .../custom-actions-caseManagement/caseManagement.action.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/enterGenAppapplicationDetails.page.data.ts b/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/enterGenAppapplicationDetails.page.data.ts index e10cc005f7..7419ef3fc0 100644 --- a/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/enterGenAppapplicationDetails.page.data.ts +++ b/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/enterGenAppapplicationDetails.page.data.ts @@ -15,7 +15,7 @@ export const enterGenappApplication = { errorValidation: `YES`, eventCouldNotBeCreatedErrorMessageHeader: `The event could not be created`, thereIsProbErrorMessageHeader: `There is a problem`, - errorValidationType: { one: `textField`, two: `radioOptions`, three: `checkBox`, four: `dropDown`, five: `appReceivedDateField` }, + errorValidationType: { one: `textField`, two: `radioOptions`, three: `checkBox`, four: `dropDown`, five: `dateField` }, errorValidationField: { errorRadioOption1: [ { type: `none`, input: ``, errMessage: `Which party made the application? is required`, errInlineMessage: `Field is required` }, diff --git a/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagement.action.ts b/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagement.action.ts index 90d399f9d2..175af48151 100644 --- a/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagement.action.ts +++ b/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagement.action.ts @@ -199,7 +199,7 @@ export class CaseManagementAction implements IAction { }); break; - case 'appReceivedDateField': + case 'dateField': let date: string = CaseManagementCommonUtils.getRandomDate(item.type as string); const enterDate = () => performActions(