From 508d5008ccf0d16bfc379c9f9201d0235ca385ba Mon Sep 17 00:00:00 2001 From: sadmanrahman Date: Mon, 29 Jun 2026 14:04:46 +0100 Subject: [PATCH 01/42] 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 47e4dd3e66d10db7abfcee2d8652cfffe0d5c465 Mon Sep 17 00:00:00 2001 From: sadmanrahman Date: Tue, 30 Jun 2026 10:26:23 +0100 Subject: [PATCH 02/42] 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 03/42] 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 04/42] 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 05/42] 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 06/42] 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 07/42] 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 08/42] 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 09/42] 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 10/42] 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 183d5b90ebf6195ca9094c278af8af072df01b2c Mon Sep 17 00:00:00 2001 From: sadmanrahman Date: Wed, 1 Jul 2026 11:29:14 +0100 Subject: [PATCH 11/42] 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 12/42] 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 13/42] 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 14/42] 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 15/42] 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 16/42] 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 b0b507d475b3ebaef2c8e0212feb2ce92fcb4d4b Mon Sep 17 00:00:00 2001 From: sadmanrahman Date: Thu, 2 Jul 2026 09:17:30 +0100 Subject: [PATCH 17/42] 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 2c6a8d7dca993248c4ba492c5df7ec0fe25a9023 Mon Sep 17 00:00:00 2001 From: sadmanrahman Date: Thu, 2 Jul 2026 14:10:48 +0100 Subject: [PATCH 18/42] 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 19/42] 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 20/42] 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 21/42] 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 22/42] 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 23/42] 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 139c6dde8841cc650a6d755253434d0c9c3be624 Mon Sep 17 00:00:00 2001 From: sadmanrahman Date: Fri, 3 Jul 2026 11:59:08 +0100 Subject: [PATCH 24/42] 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 6152dfd2b1f93d4b27195529138bde0054c00516 Mon Sep 17 00:00:00 2001 From: sadmanrahman Date: Tue, 7 Jul 2026 14:07:24 +0100 Subject: [PATCH 25/42] 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 ab13b58d016d4fbac8916a2e8c8c864cc64986c6 Mon Sep 17 00:00:00 2001 From: sadmanrahman Date: Mon, 13 Jul 2026 11:21:03 +0100 Subject: [PATCH 26/42] 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 27/42] 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 606ff4932a5f85296a7e9a4c24e822acadae7e39 Mon Sep 17 00:00:00 2001 From: srinijg Date: Wed, 15 Jul 2026 15:27:12 +0100 Subject: [PATCH 28/42] Hdpi 7308 automation (#2169) Co-authored-by: sadmanrahman Co-authored-by: Arunabha Roy Chowdhury <90389022+ArunabhaChowdhury@users.noreply.github.com> Co-authored-by: PadmaDeenadayalan --- src/e2eTest/data/api-data/index.ts | 1 + src/e2eTest/data/api-data/payment.api.data.ts | 31 ++++ .../data/api-data/submitCase.api.data.ts | 20 +- .../amendDocumentDetails.page.data.ts | 3 + .../page-data-caseManagement-figma/index.ts | 2 + .../selectDocument.page.data.ts | 20 ++ .../urlToFileMappingCM.ts | 3 + .../data/page-data/caseSummary.page.data.ts | 5 +- src/e2eTest/data/page-data/home.page.data.ts | 2 +- .../data/user-data/permanent.user.data.ts | 4 + .../caseManagement.manageDocuments.spec.ts | 56 ++++++ .../custom-actions/createCaseAPI.action.ts | 38 +++- .../caseManagement.action.ts | 110 +++++++++++ .../caseManagementErrorValidation.action.ts | 36 ++++ .../custom-actions-caseManagement/index.ts | 1 + .../utils/controller-caseManagement.ts | 173 ++++++++++++++++++ src/e2eTest/utils/registry/action.registry.ts | 1 + .../action-caseManagement.registry.ts | 58 ++++++ .../registry/registry-caseManagement/index.ts | 2 + .../validation-caseManagement.registry.ts | 44 +++++ .../pageContent.validation.ts | 6 + 21 files changed, 610 insertions(+), 6 deletions(-) create mode 100644 src/e2eTest/data/api-data/payment.api.data.ts create mode 100644 src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/amendDocumentDetails.page.data.ts 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/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/caseManagementErrorValidation.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 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/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..f15ff99b94 --- /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.CASE_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/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 new file mode 100644 index 0000000000..2afc27d86e --- /dev/null +++ b/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/index.ts @@ -0,0 +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 new file mode 100644 index 0000000000..b7b5d611d7 --- /dev/null +++ b/src/e2eTest/data/page-data-figma/page-data-caseManagement-figma/selectDocument.page.data.ts @@ -0,0 +1,20 @@ +export const selectDocument = { + mainHeader: `Select document`, + whichFolderQuestion: `Which folder is the document in?`, + documentToAmendHiddenQuestion: `Which document do you want to amend?`, + docFolderHiddenOption: `Property documents`, + 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 folder is the document in? 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/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/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/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 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..bd8ae4a657 --- /dev/null +++ b/src/e2eTest/tests/test-caseManagement/caseManagement.manageDocuments.spec.ts @@ -0,0 +1,56 @@ +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/e2eTest/utils/actions/custom-actions/createCaseAPI.action.ts b/src/e2eTest/utils/actions/custom-actions/createCaseAPI.action.ts index 1f74592408..a462269487 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}'`); @@ -448,4 +450,38 @@ 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 + actionRetries; + const delayMs = VERY_SHORT_TIMEOUT; + for (let attempt = 1; attempt <= maxRetries; attempt++) { + try { + const response = await paymentApi.get(paymentApiData.getFeePaymentInfoApiEndPoint()); + const paymentInfo = response.data; + 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) + ); + 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; + if (attempt === maxRetries) { + if (Axios.isAxiosError(error)) { + throw new Error(`Payment API failed after retries: ${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..6aa019db95 --- /dev/null +++ b/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagement.action.ts @@ -0,0 +1,110 @@ + +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'; +import { selectDocument } from '@data/page-data-figma/page-data-caseManagement-figma'; + + +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)], + ['selectDocumentToAmend', () => this.selectDocumentToAmend(fieldName as actionRecord)], + ['inputErrorValidation', () => this.inputErrorValidation(page, 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) { + 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); + } + + 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) { + + + 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`); + }; + } + } + 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..52c7f6fbc5 --- /dev/null +++ b/src/e2eTest/utils/actions/custom-actions/custom-actions-caseManagement/caseManagementErrorValidation.action.ts @@ -0,0 +1,36 @@ +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'; + +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: 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/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..33e6d27ac0 --- /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 { 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 = ''; +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..1858b2e686 --- /dev/null +++ b/src/e2eTest/utils/registry/registry-caseManagement/action-caseManagement.registry.ts @@ -0,0 +1,58 @@ +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 { 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"; + + +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()], + ['selectDocumentToAmend', new CaseManagementAction()], + ['errorValidationSelectDocumentPage', new ErrorValidationAction()], + ['inputErrorValidation', new CaseManagementAction()], + ['reTryOnCallBackError', new RetryOnCallBackError()], + + ]); + + 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()); + } +} 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 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 e5b049bce76bfbbb8e2fd5b782763d080353ec2d Mon Sep 17 00:00:00 2001 From: sstewart <202802468+scottstewart-sl@users.noreply.github.com> Date: Thu, 16 Jul 2026 14:41:21 +0100 Subject: [PATCH 29/42] HDPI-7308: Add feature flag control to event --- .../resources/cftlib-am-role-assignments.json | 17 +++++ .../uk/gov/hmcts/reform/pcs/ccd/CaseType.java | 3 +- .../hmcts/reform/pcs/ccd/ShowConditions.java | 22 +++++++ .../ccd/accesscontrol/CaseworkerRoles.java | 12 ++++ .../reform/pcs/ccd/event/AmendDocuments.java | 13 ++-- .../hmcts/reform/pcs/ccd/CaseTypeTest.java | 2 +- .../reform/pcs/ccd/ShowConditionsTest.java | 63 +++++++++++++++++-- 7 files changed, 119 insertions(+), 13 deletions(-) create mode 100644 src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/CaseworkerRoles.java diff --git a/src/cftlib/resources/cftlib-am-role-assignments.json b/src/cftlib/resources/cftlib-am-role-assignments.json index a76894ca41..4a39a5402d 100644 --- a/src/cftlib/resources/cftlib-am-role-assignments.json +++ b/src/cftlib/resources/cftlib-am-role-assignments.json @@ -15,5 +15,22 @@ "authorisations": [] } ] + }, + { + "email": "caseworker@pcs.com", + "id": "74e702fa-e20f-3a40-bc1d-d915f0874d00", + "roleAssignments": [ + { + "roleType": "ORGANISATION", + "roleName": "hearing-centre-admin", + "grantType": "STANDARD", + "roleCategory": "LEGAL_OPERATIONS", + "classification": "PUBLIC", + "readOnly": false, + "attributes": { + }, + "authorisations": [] + } + ] } ] 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 cc49dcdb73..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 @@ -144,7 +144,8 @@ public void configure(final ConfigBuilder builder builder.tab("hidden", "HiddenFields") .showCondition(NEVER_SHOW) .field(PCSCase::getCaseTitleMarkdown) - .field(PCSCase::getDashboardData); + .field(PCSCase::getDashboardData) + .field(PCSCase::getFeatureFlags); builder.tab("serviceRequest", "Service Request") .forRoles(PARTY_VISIBLE_TAB_ROLES) diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/ShowConditions.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/ShowConditions.java index 38659245a5..d947602e81 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/ShowConditions.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/ShowConditions.java @@ -3,6 +3,10 @@ import lombok.AccessLevel; import lombok.NoArgsConstructor; import uk.gov.hmcts.reform.pcs.ccd.domain.State; +import uk.gov.hmcts.reform.pcs.service.FeatureFlag; + +import java.util.Arrays; +import java.util.stream.Collectors; @NoArgsConstructor(access = AccessLevel.PRIVATE) public class ShowConditions { @@ -31,4 +35,22 @@ public static String and(String... conditions) { return String.join(" AND ", conditions); } + public static String featureFlagsEnabled(FeatureFlag... featureFlags) { + return Arrays.stream(featureFlags) + .map(featureFlag -> { + String name = getCcdFieldName(featureFlag); + return "featureFlags.%s=\"YES\"".formatted(name); + }) + .collect(Collectors.joining(" AND ")); + } + + private static String getCcdFieldName(FeatureFlag featureFlag) { + return switch (featureFlag) { + case RELEASE_1_DOT_2 -> "release1dot2Enabled"; + case CASEWORKER_EVENTS -> "caseWorkerEventsEnabled"; + default -> throw new IllegalArgumentException("Flag %s does not have a CCD field yet" + .formatted(featureFlag.name())); + }; + } + } 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..c278000f1e --- /dev/null +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/CaseworkerRoles.java @@ -0,0 +1,12 @@ +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, + }; + + private CaseworkerRoles() { + } +} 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 2893ae7a00..d117a6e8c1 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 @@ -8,6 +8,7 @@ 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.ShowConditions; 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; @@ -16,7 +17,10 @@ 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.accesscontrol.CaseworkerRoles.CASEWORKER_ROLES; import static uk.gov.hmcts.reform.pcs.ccd.event.EventId.amendDocuments; +import static uk.gov.hmcts.reform.pcs.service.FeatureFlag.CASEWORKER_EVENTS; +import static uk.gov.hmcts.reform.pcs.service.FeatureFlag.RELEASE_1_DOT_2; @Component @AllArgsConstructor @@ -33,13 +37,8 @@ public void configureDecentralised(DecentralisedConfigBuilder showConditionsToJoin, String ex private static Stream joinWithAndScenarios() { return Stream.of( // Show conditions to join, expected joined show condition - Arguments.argumentSet("no params", List.of(), ""), - Arguments.argumentSet("one param", List.of("a"), "a"), - Arguments.argumentSet("two params", List.of("a", "b"), "a AND b"), - Arguments.argumentSet("three params", List.of("a", "b", "c"), "a AND b AND c") + argumentSet("no params", List.of(), ""), + argumentSet("one param", List.of("a"), "a"), + argumentSet("two params", List.of("a", "b"), "a AND b"), + argumentSet("three params", List.of("a", "b", "c"), "a AND b AND c") + ); + } + + @ParameterizedTest + @MethodSource("featureFlagScenarios") + void shouldCreateShowConditionForFeatureFlags(List featureFlags, + String expectedShowCondition) { + + // When + String actualShowCondition = ShowConditions.featureFlagsEnabled(featureFlags.toArray(new FeatureFlag[0])); + + // Then + assertThat(actualShowCondition).isEqualTo(expectedShowCondition); + } + + @ParameterizedTest + @EnumSource(value = FeatureFlag.class, names = {"RELEASE_1_DOT_2", "CASEWORKER_EVENTS"}, mode = INCLUDE) + void shouldNotThrowExceptionForFeatureFlagWithCcdField(FeatureFlag featureFlag) { + // When / Then + assertThatNoException().isThrownBy(() -> ShowConditions.featureFlagsEnabled(featureFlag)); + } + + @ParameterizedTest + @EnumSource(value = FeatureFlag.class, names = {"RELEASE_1_DOT_2", "CASEWORKER_EVENTS"}, mode = EXCLUDE) + void shouldThrowExceptionForFeatureFlagWithNoCcdField(FeatureFlag featureFlag) { + // When + Throwable throwable = catchThrowable(() -> ShowConditions.featureFlagsEnabled(featureFlag)); + + // Then + assertThat(throwable) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Flag %s does not have a CCD field yet", featureFlag.name()); + } + + private static Stream featureFlagScenarios() { + return Stream.of( + // Feature flag(s), expected show condition + arguments(List.of(), + ""), + arguments(List.of(RELEASE_1_DOT_2), + "featureFlags.release1dot2Enabled=\"YES\""), + arguments(List.of(CASEWORKER_EVENTS), + "featureFlags.caseWorkerEventsEnabled=\"YES\""), + arguments(List.of(RELEASE_1_DOT_2, CASEWORKER_EVENTS), + "featureFlags.release1dot2Enabled=\"YES\" AND featureFlags.caseWorkerEventsEnabled=\"YES\"") ); } From 153403fde55d2a37ca09dd34bb424035467d1699 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 13:42:18 +0000 Subject: [PATCH 30/42] 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 93a66c540f63223c9c51b46633f224dea7f090cf Mon Sep 17 00:00:00 2001 From: Liban Abdirahman Date: Fri, 17 Jul 2026 14:07:41 +0100 Subject: [PATCH 31/42] HDPI-6454:WIP --- .../hmcts/reform/pcs/ccd/domain/PCSCase.java | 37 +++- .../documentamend/DocumentAmendDetails.java | 85 +++------- .../DocumentRemovalDetails.java | 135 +++++++++++++++ .../reform/pcs/ccd/event/AmendDocuments.java | 11 +- .../hmcts/reform/pcs/ccd/event/EventId.java | 3 +- .../reform/pcs/ccd/event/RemoveDocuments.java | 68 ++++++++ .../documentamend/DocumentCategoryField.java | 23 +-- .../documentamend/SelectDocumentPage.java | 33 ++-- .../DocumentCategoryField.java | 104 ++++++++++++ .../SelectDocumentToRemovePage.java | 160 ++++++++++++++++++ .../DocumentAmendSelectionService.java | 85 ++++------ .../document/DocumentFolderSelection.java | 21 +++ 12 files changed, 616 insertions(+), 149 deletions(-) create mode 100644 src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentremoval/DocumentRemovalDetails.java create mode 100644 src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/RemoveDocuments.java create mode 100644 src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentremoval/DocumentCategoryField.java create mode 100644 src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentremoval/SelectDocumentToRemovePage.java create mode 100644 src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentFolderSelection.java 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 98616c5707..581ad6f3b8 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 @@ -33,11 +33,12 @@ 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.documentremoval.DocumentRemovalDetails; +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; @@ -49,8 +50,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; @@ -58,8 +59,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; @@ -485,6 +486,36 @@ public class PCSCase { @JsonUnwrapped(prefix = "documentAmend_") private DocumentAmendDetails documentAmendDetails; + @JsonUnwrapped(prefix = "documentRemoval_") + private DocumentRemovalDetails documentRemovalDetails; + + @CCD(searchable = false, typeOverride = DynamicRadioList) + private DynamicList statementsOfCaseDocuments; + + @CCD(searchable = false, typeOverride = DynamicRadioList) + private DynamicList propertyDocuments; + + @CCD(searchable = false, typeOverride = DynamicRadioList) + private DynamicList evidenceDocuments; + + @CCD(searchable = false, typeOverride = DynamicRadioList) + private DynamicList hearingDocuments; + + @CCD(searchable = false, typeOverride = DynamicRadioList) + private DynamicList ordersAndNoticeOfHearingsDocuments; + + @CCD(searchable = false, typeOverride = DynamicRadioList) + private DynamicList applicationsDocuments; + + @CCD(searchable = false, typeOverride = DynamicRadioList) + private DynamicList appealsDocuments; + + @CCD(searchable = false, typeOverride = DynamicRadioList) + private DynamicList correspondenceDocuments; + + @CCD(searchable = false, typeOverride = DynamicRadioList) + private DynamicList uncategorisedDocuments; + @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 index bd0f751490..c647a5e837 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 @@ -1,5 +1,6 @@ package uk.gov.hmcts.reform.pcs.ccd.domain.documentamend; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.databind.PropertyNamingStrategies; @@ -10,10 +11,9 @@ 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 uk.gov.hmcts.reform.pcs.ccd.service.document.DocumentFolderSelection; -import static uk.gov.hmcts.ccd.sdk.type.FieldType.DynamicRadioList; import static uk.gov.hmcts.ccd.sdk.type.FieldType.FixedList; @Builder @@ -22,7 +22,7 @@ @AllArgsConstructor @JsonInclude(Include.NON_NULL) @JsonNaming(PropertyNamingStrategies.UpperCamelCaseStrategy.class) -public class DocumentAmendDetails { +public class DocumentAmendDetails implements DocumentFolderSelection { @CCD( label = "Which folder is the document in?", @@ -35,69 +35,6 @@ public class DocumentAmendDetails { @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; @@ -136,4 +73,20 @@ public class DocumentAmendDetails { @CCD(searchable = false) private String selectedDocumentFileName; + + @JsonIgnore + @Override + public void setEmptyForCategory(CaseFileCategory category, YesOrNo empty) { + switch (category) { + case STATEMENTS_OF_CASE -> statementsOfCaseEmpty = empty; + case PROPERTY_DOCUMENTS -> propertyDocumentsEmpty = empty; + case EVIDENCE -> evidenceEmpty = empty; + case HEARING_DOCUMENTS -> hearingDocumentsEmpty = empty; + case ORDERS_AND_NOTICE_OF_HEARINGS -> ordersAndNoticeOfHearingsEmpty = empty; + case APPLICATIONS -> applicationsEmpty = empty; + case APPEALS -> appealsEmpty = empty; + case CORRESPONDENCE -> correspondenceEmpty = empty; + case UNCATEGORISED_DOCUMENTS -> uncategorisedDocumentsEmpty = empty; + } + } } diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentremoval/DocumentRemovalDetails.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentremoval/DocumentRemovalDetails.java new file mode 100644 index 0000000000..a88a679464 --- /dev/null +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentremoval/DocumentRemovalDetails.java @@ -0,0 +1,135 @@ +package uk.gov.hmcts.reform.pcs.ccd.domain.documentremoval; + +import com.fasterxml.jackson.annotation.JsonIgnore; +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.ccd.sdk.type.YesOrNo; +import uk.gov.hmcts.reform.pcs.ccd.domain.CaseFileCategory; +import uk.gov.hmcts.reform.pcs.ccd.service.document.DocumentFolderSelection; + +import static uk.gov.hmcts.ccd.sdk.type.FieldType.FixedList; +import static uk.gov.hmcts.ccd.sdk.type.FieldType.TextArea; + +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +@JsonInclude(Include.NON_NULL) +@JsonNaming(PropertyNamingStrategies.UpperCamelCaseStrategy.class) +public class DocumentRemovalDetails implements DocumentFolderSelection { + + @CCD( + label = "Which folder is the document in?", + searchable = false, + typeOverride = FixedList, + typeParameterOverride = "CaseFileCategory" + ) + private CaseFileCategory selectedFolder; + + @CCD(searchable = false) + private String propertyAddressSummary; + + @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; + + @CCD(searchable = false, typeOverride = TextArea) + private String statementsOfCaseReason; + + @CCD(searchable = false, typeOverride = TextArea) + private String propertyDocumentsReason; + + @CCD(searchable = false, typeOverride = TextArea) + private String evidenceReason; + + @CCD(searchable = false, typeOverride = TextArea) + private String hearingDocumentsReason; + + @CCD(searchable = false, typeOverride = TextArea) + private String ordersAndNoticeOfHearingsReason; + + @CCD(searchable = false, typeOverride = TextArea) + private String applicationsReason; + + @CCD(searchable = false, typeOverride = TextArea) + private String appealsReason; + + @CCD(searchable = false, typeOverride = TextArea) + private String correspondenceReason; + + @CCD(searchable = false, typeOverride = TextArea) + private String uncategorisedDocumentsReason; + + @JsonIgnore + @Override + public void setEmptyForCategory(CaseFileCategory category, YesOrNo empty) { + switch (category) { + case STATEMENTS_OF_CASE -> statementsOfCaseEmpty = empty; + case PROPERTY_DOCUMENTS -> propertyDocumentsEmpty = empty; + case EVIDENCE -> evidenceEmpty = empty; + case HEARING_DOCUMENTS -> hearingDocumentsEmpty = empty; + case ORDERS_AND_NOTICE_OF_HEARINGS -> ordersAndNoticeOfHearingsEmpty = empty; + case APPLICATIONS -> applicationsEmpty = empty; + case APPEALS -> appealsEmpty = empty; + case CORRESPONDENCE -> correspondenceEmpty = empty; + case UNCATEGORISED_DOCUMENTS -> uncategorisedDocumentsEmpty = empty; + } + } + + @JsonIgnore + public String getReasonForCategory(CaseFileCategory category) { + return switch (category) { + case STATEMENTS_OF_CASE -> statementsOfCaseReason; + case PROPERTY_DOCUMENTS -> propertyDocumentsReason; + case EVIDENCE -> evidenceReason; + case HEARING_DOCUMENTS -> hearingDocumentsReason; + case ORDERS_AND_NOTICE_OF_HEARINGS -> ordersAndNoticeOfHearingsReason; + case APPLICATIONS -> applicationsReason; + case APPEALS -> appealsReason; + case CORRESPONDENCE -> correspondenceReason; + case UNCATEGORISED_DOCUMENTS -> uncategorisedDocumentsReason; + }; + } +} 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 2893ae7a00..df1c39debb 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 @@ -12,6 +12,7 @@ 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.domain.documentamend.DocumentAmendDetails; 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; @@ -22,7 +23,7 @@ @AllArgsConstructor public class AmendDocuments implements CCDConfig { - private final DocumentAmendSelectionService documentAmendSelectionService; + private final DocumentAmendSelectionService documentSelectionService; private final SelectDocumentPage selectDocumentPage; private final AmendDocumentDetailsPlaceholderPage amendDocumentDetailsPlaceholderPage; @@ -49,7 +50,13 @@ public void configureDecentralised(DecentralisedConfigBuilder eventPayload) { PCSCase caseData = eventPayload.caseData(); - documentAmendSelectionService.initialise(eventPayload.caseReference(), caseData); + + if (caseData.getDocumentAmendDetails() == null) { + caseData.setDocumentAmendDetails(new DocumentAmendDetails()); + } + DocumentAmendDetails details = caseData.getDocumentAmendDetails(); + + documentSelectionService.initialise(eventPayload.caseReference(), caseData, details); return caseData; } 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 eb00b7ce14..7e3934717c 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 @@ -19,5 +19,6 @@ public enum EventId { addCaseNote, createFlags, amendFlags, - claimIssuePayment + claimIssuePayment, + removeDocuments } diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/RemoveDocuments.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/RemoveDocuments.java new file mode 100644 index 0000000000..c2e2a8ad61 --- /dev/null +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/RemoveDocuments.java @@ -0,0 +1,68 @@ +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.domain.documentremoval.DocumentRemovalDetails; +import uk.gov.hmcts.reform.pcs.ccd.page.documentremoval.SelectDocumentToRemovePage; +import uk.gov.hmcts.reform.pcs.ccd.service.document.DocumentAmendSelectionService; +import uk.gov.hmcts.reform.pcs.ccd.service.document.DocumentRemovalService; + +import java.util.UUID; + +import static uk.gov.hmcts.reform.pcs.ccd.event.EventId.removeDocuments; + +@Component +@AllArgsConstructor +public class RemoveDocuments implements CCDConfig { + + private final DocumentAmendSelectionService documentSelectionService; + private final DocumentRemovalService documentRemovalService; + private final SelectDocumentToRemovePage selectDocumentToRemovePage; + + @Override + public void configureDecentralised(DecentralisedConfigBuilder configBuilder) { + Event.EventBuilder eventBuilder = + configBuilder + .decentralisedEvent(removeDocuments.name(), this::submit, this::start) + .forStates(State.CASE_ISSUED) + .name("Manage documents: Remove") + .grant(Permission.CRU, UserRole.HEARING_CENTRE_ADMIN) + .grant(Permission.CRU, UserRole.HEARING_CENTRE_TEAM_LEADER) + .showSummary() + .endButtonLabel("Submit"); + + PageBuilder pageBuilder = new PageBuilder(eventBuilder); + selectDocumentToRemovePage.addTo(pageBuilder); + } + + private PCSCase start(EventPayload eventPayload) { + PCSCase caseData = eventPayload.caseData(); + + if (caseData.getDocumentRemovalDetails() == null) { + caseData.setDocumentRemovalDetails(new DocumentRemovalDetails()); + } + DocumentRemovalDetails details = caseData.getDocumentRemovalDetails(); + + documentSelectionService.initialise(eventPayload.caseReference(), caseData, details); + return caseData; + } + + private SubmitResponse submit(EventPayload eventPayload) { + DocumentRemovalDetails details = eventPayload.caseData().getDocumentRemovalDetails(); + String reason = details.getReasonForCategory(details.getSelectedFolder()); + + documentRemovalService.removeDocument(UUID.fromString(details.getSelectedDocumentId()), reason); + + return SubmitResponse.defaultResponse(); + } +} 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 index f00bd1792c..7f34b113bf 100644 --- 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 @@ -4,72 +4,73 @@ 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.PCSCase; import uk.gov.hmcts.reform.pcs.ccd.domain.documentamend.DocumentAmendDetails; enum DocumentCategoryField { STATEMENTS_OF_CASE( CaseFileCategory.STATEMENTS_OF_CASE, "statementsOfCase", - DocumentAmendDetails::getStatementsOfCaseDocuments, + PCSCase::getStatementsOfCaseDocuments, DocumentAmendDetails::getStatementsOfCaseEmpty ), PROPERTY_DOCUMENTS( CaseFileCategory.PROPERTY_DOCUMENTS, "propertyDocuments", - DocumentAmendDetails::getPropertyDocuments, + PCSCase::getPropertyDocuments, DocumentAmendDetails::getPropertyDocumentsEmpty ), EVIDENCE( CaseFileCategory.EVIDENCE, "evidence", - DocumentAmendDetails::getEvidenceDocuments, + PCSCase::getEvidenceDocuments, DocumentAmendDetails::getEvidenceEmpty ), HEARING_DOCUMENTS( CaseFileCategory.HEARING_DOCUMENTS, "hearingDocuments", - DocumentAmendDetails::getHearingDocuments, + PCSCase::getHearingDocuments, DocumentAmendDetails::getHearingDocumentsEmpty ), ORDERS_AND_NOTICE_OF_HEARINGS( CaseFileCategory.ORDERS_AND_NOTICE_OF_HEARINGS, "ordersAndNoticeOfHearings", - DocumentAmendDetails::getOrdersAndNoticeOfHearingsDocuments, + PCSCase::getOrdersAndNoticeOfHearingsDocuments, DocumentAmendDetails::getOrdersAndNoticeOfHearingsEmpty ), APPLICATIONS( CaseFileCategory.APPLICATIONS, "applications", - DocumentAmendDetails::getApplicationsDocuments, + PCSCase::getApplicationsDocuments, DocumentAmendDetails::getApplicationsEmpty ), APPEALS( CaseFileCategory.APPEALS, "appeals", - DocumentAmendDetails::getAppealsDocuments, + PCSCase::getAppealsDocuments, DocumentAmendDetails::getAppealsEmpty ), CORRESPONDENCE( CaseFileCategory.CORRESPONDENCE, "correspondence", - DocumentAmendDetails::getCorrespondenceDocuments, + PCSCase::getCorrespondenceDocuments, DocumentAmendDetails::getCorrespondenceEmpty ), UNCATEGORISED_DOCUMENTS( CaseFileCategory.UNCATEGORISED_DOCUMENTS, "uncategorisedDocuments", - DocumentAmendDetails::getUncategorisedDocuments, + PCSCase::getUncategorisedDocuments, DocumentAmendDetails::getUncategorisedDocumentsEmpty ); final CaseFileCategory category; final String idPrefix; - final TypedPropertyGetter documentsGetter; + final TypedPropertyGetter documentsGetter; final TypedPropertyGetter emptyGetter; DocumentCategoryField(CaseFileCategory category, String idPrefix, - TypedPropertyGetter documentsGetter, + TypedPropertyGetter documentsGetter, TypedPropertyGetter emptyGetter) { this.category = category; this.idPrefix = idPrefix; 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 c15e9da9aa..8c474427c5 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 @@ -24,13 +24,14 @@ public class SelectDocumentPage implements CcdPageConfiguration { private static final String PAGE_ID = "selectDocument"; private static final String FIELD_PREFIX = "documentAmend_"; + private static final String DOCUMENT_QUESTION_LABEL = "Which document do you want to amend?"; private static final String YES = "=\"Yes\""; private static final String NO = "=\"No\""; - private final DocumentAmendSelectionService documentAmendSelectionService; + private final DocumentAmendSelectionService documentSelectionService; @Override public void addTo(PageBuilder pageBuilder) { - FieldCollectionBuilder documentAmendPage = pageBuilder + FieldCollectionBuilder page = pageBuilder .page(PAGE_ID, this::midEvent) .pageLabel("Select document") .label(PAGE_ID + "-separator", "---") @@ -39,17 +40,21 @@ public void addTo(PageBuilder pageBuilder) { .mandatory(DocumentAmendDetails::getSelectedFolder) .label("emptyFolderDocumentError", "", NEVER_SHOW) .label("selectedFolderEmptyErrorMessage", "", NEVER_SHOW) - .label("emptyFolderDocumentQuestion", "", NEVER_SHOW); + .label("emptyFolderDocumentQuestion", "", NEVER_SHOW) + .done(); for (DocumentCategoryField categoryField : DocumentCategoryField.values()) { - addCategoryFields(documentAmendPage, categoryField); + addCategoryFields(page, categoryField); } + FieldCollectionBuilder documentAmendDetailsFields = + page.complex(PCSCase::getDocumentAmendDetails); + for (DocumentCategoryField categoryField : DocumentCategoryField.values()) { - documentAmendPage.readonly(categoryField.emptyGetter, NEVER_SHOW, true); + documentAmendDetailsFields.readonly(categoryField.emptyGetter, NEVER_SHOW, true); } - documentAmendPage + documentAmendDetailsFields .readonly(DocumentAmendDetails::getSelectedFolderId, NEVER_SHOW, true) .readonly(DocumentAmendDetails::getSelectedFolderLabel, NEVER_SHOW, true) .readonly(DocumentAmendDetails::getSelectedDocumentId, NEVER_SHOW, true) @@ -57,21 +62,27 @@ public void addTo(PageBuilder pageBuilder) { .done(); } - private void addCategoryFields(FieldCollectionBuilder page, + 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); + .mandatoryWithoutDefaultValue(categoryField.documentsGetter, documentsShowCondition(category), + DOCUMENT_QUESTION_LABEL, true); } private AboutToStartOrSubmitResponse midEvent(CaseDetails details, CaseDetails detailsBefore) { PCSCase caseData = details.getData(); - documentAmendSelectionService.initialise(details.getId(), caseData); - List errors = documentAmendSelectionService.validateAndStoreSelection(caseData); + if (caseData.getDocumentAmendDetails() == null) { + caseData.setDocumentAmendDetails(new DocumentAmendDetails()); + } + DocumentAmendDetails documentAmendDetails = caseData.getDocumentAmendDetails(); + + documentSelectionService.initialise(details.getId(), caseData, documentAmendDetails); + List errors = documentSelectionService.validateAndStoreSelection(caseData, documentAmendDetails); return AboutToStartOrSubmitResponse.builder() .data(caseData) @@ -106,7 +117,7 @@ private String emptyFieldId(CaseFileCategory category) { } private String emptyFolderMessage(CaseFileCategory category) { - return "Which document do you want to amend?" + return DOCUMENT_QUESTION_LABEL + "
" + "No documents in '" + category.getLabel() + "'"; } diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentremoval/DocumentCategoryField.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentremoval/DocumentCategoryField.java new file mode 100644 index 0000000000..7fed595ac4 --- /dev/null +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentremoval/DocumentCategoryField.java @@ -0,0 +1,104 @@ +package uk.gov.hmcts.reform.pcs.ccd.page.documentremoval; + +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.PCSCase; +import uk.gov.hmcts.reform.pcs.ccd.domain.documentremoval.DocumentRemovalDetails; + +enum DocumentCategoryField { + STATEMENTS_OF_CASE( + CaseFileCategory.STATEMENTS_OF_CASE, + "StatementsOfCaseDocuments", + "StatementsOfCaseEmpty", + PCSCase::getStatementsOfCaseDocuments, + DocumentRemovalDetails::getStatementsOfCaseEmpty, + DocumentRemovalDetails::getStatementsOfCaseReason + ), + PROPERTY_DOCUMENTS( + CaseFileCategory.PROPERTY_DOCUMENTS, + "PropertyDocuments", + "PropertyDocumentsEmpty", + PCSCase::getPropertyDocuments, + DocumentRemovalDetails::getPropertyDocumentsEmpty, + DocumentRemovalDetails::getPropertyDocumentsReason + ), + EVIDENCE( + CaseFileCategory.EVIDENCE, + "EvidenceDocuments", + "EvidenceEmpty", + PCSCase::getEvidenceDocuments, + DocumentRemovalDetails::getEvidenceEmpty, + DocumentRemovalDetails::getEvidenceReason + ), + HEARING_DOCUMENTS( + CaseFileCategory.HEARING_DOCUMENTS, + "HearingDocuments", + "HearingDocumentsEmpty", + PCSCase::getHearingDocuments, + DocumentRemovalDetails::getHearingDocumentsEmpty, + DocumentRemovalDetails::getHearingDocumentsReason + ), + ORDERS_AND_NOTICE_OF_HEARINGS( + CaseFileCategory.ORDERS_AND_NOTICE_OF_HEARINGS, + "OrdersAndNoticeOfHearingsDocuments", + "OrdersAndNoticeOfHearingsEmpty", + PCSCase::getOrdersAndNoticeOfHearingsDocuments, + DocumentRemovalDetails::getOrdersAndNoticeOfHearingsEmpty, + DocumentRemovalDetails::getOrdersAndNoticeOfHearingsReason + ), + APPLICATIONS( + CaseFileCategory.APPLICATIONS, + "ApplicationsDocuments", + "ApplicationsEmpty", + PCSCase::getApplicationsDocuments, + DocumentRemovalDetails::getApplicationsEmpty, + DocumentRemovalDetails::getApplicationsReason + ), + APPEALS( + CaseFileCategory.APPEALS, + "AppealsDocuments", + "AppealsEmpty", + PCSCase::getAppealsDocuments, + DocumentRemovalDetails::getAppealsEmpty, + DocumentRemovalDetails::getAppealsReason + ), + CORRESPONDENCE( + CaseFileCategory.CORRESPONDENCE, + "CorrespondenceDocuments", + "CorrespondenceEmpty", + PCSCase::getCorrespondenceDocuments, + DocumentRemovalDetails::getCorrespondenceEmpty, + DocumentRemovalDetails::getCorrespondenceReason + ), + UNCATEGORISED_DOCUMENTS( + CaseFileCategory.UNCATEGORISED_DOCUMENTS, + "UncategorisedDocuments", + "UncategorisedDocumentsEmpty", + PCSCase::getUncategorisedDocuments, + DocumentRemovalDetails::getUncategorisedDocumentsEmpty, + DocumentRemovalDetails::getUncategorisedDocumentsReason + ); + + final CaseFileCategory category; + final String documentsFieldId; + final String emptyFieldId; + final TypedPropertyGetter documentsGetter; + final TypedPropertyGetter emptyGetter; + final TypedPropertyGetter reasonGetter; + + DocumentCategoryField(CaseFileCategory category, + String documentsFieldId, + String emptyFieldId, + TypedPropertyGetter documentsGetter, + TypedPropertyGetter emptyGetter, + TypedPropertyGetter reasonGetter) { + this.category = category; + this.documentsFieldId = documentsFieldId; + this.emptyFieldId = emptyFieldId; + this.documentsGetter = documentsGetter; + this.emptyGetter = emptyGetter; + this.reasonGetter = reasonGetter; + } +} diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentremoval/SelectDocumentToRemovePage.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentremoval/SelectDocumentToRemovePage.java new file mode 100644 index 0000000000..0bf04566c4 --- /dev/null +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentremoval/SelectDocumentToRemovePage.java @@ -0,0 +1,160 @@ +package uk.gov.hmcts.reform.pcs.ccd.page.documentremoval; + +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.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.documentremoval.DocumentRemovalDetails; +import uk.gov.hmcts.reform.pcs.ccd.service.TextAreaValidationService; +import uk.gov.hmcts.reform.pcs.ccd.service.document.DocumentAmendSelectionService; +import uk.gov.hmcts.reform.pcs.ccd.util.StringUtils; + +import java.util.ArrayList; +import java.util.List; + +import static uk.gov.hmcts.reform.pcs.ccd.ShowConditions.NEVER_SHOW; + +@AllArgsConstructor +@Component +public class SelectDocumentToRemovePage implements CcdPageConfiguration { + + private static final String PAGE_ID = "selectDocumentToRemove"; + private static final String FIELD_PREFIX = "documentRemoval_"; + private static final String YES = "=\"Yes\""; + private static final String NO = "=\"No\""; + private static final String DOCUMENT_QUESTION_LABEL = "Which document do you want to remove?"; + private static final String REASON_LABEL = "Why are you removing this document?"; + + private final DocumentAmendSelectionService documentSelectionService; + private final TextAreaValidationService textAreaValidationService; + + @Override + public void addTo(PageBuilder pageBuilder) { + FieldCollectionBuilder page = pageBuilder + .page(PAGE_ID, this::midEvent) + .pageLabel("Select document") + .label(PAGE_ID + "-separator", "---"); + + page.complex(PCSCase::getDocumentRemovalDetails) + .readonly(DocumentRemovalDetails::getPropertyAddressSummary, NEVER_SHOW, true) + .mandatory(DocumentRemovalDetails::getSelectedFolder) + .label("emptyFolderDocumentError", "", NEVER_SHOW) + .label("selectedFolderEmptyErrorMessage", "", NEVER_SHOW) + .label("emptyFolderDocumentQuestion", "", NEVER_SHOW) + .done(); + + for (DocumentCategoryField categoryField : DocumentCategoryField.values()) { + addCategoryFields(page, categoryField); + } + + FieldCollectionBuilder documentRemovalDetailsFields = + page.complex(PCSCase::getDocumentRemovalDetails); + + for (DocumentCategoryField categoryField : DocumentCategoryField.values()) { + documentRemovalDetailsFields.readonly(categoryField.emptyGetter, NEVER_SHOW, true); + } + + for (DocumentCategoryField categoryField : DocumentCategoryField.values()) { + documentRemovalDetailsFields.mandatoryWithoutDefaultValue(categoryField.reasonGetter, + reasonShowCondition(categoryField), REASON_LABEL, false); + } + + documentRemovalDetailsFields + .readonly(DocumentRemovalDetails::getSelectedFolderId, NEVER_SHOW, true) + .readonly(DocumentRemovalDetails::getSelectedFolderLabel, NEVER_SHOW, true) + .readonly(DocumentRemovalDetails::getSelectedDocumentId, NEVER_SHOW, true) + .readonly(DocumentRemovalDetails::getSelectedDocumentFileName, NEVER_SHOW, true) + .done(); + } + + private void addCategoryFields(FieldCollectionBuilder page, + DocumentCategoryField categoryField) { + page + .label(categoryField.documentsFieldId + "EmptyFolderMessage", + emptyFolderMessage(categoryField.category), noDocumentsShowCondition(categoryField)) + .mandatoryWithoutDefaultValue(categoryField.documentsGetter, documentsShowCondition(categoryField), + DOCUMENT_QUESTION_LABEL, false); + } + + private AboutToStartOrSubmitResponse midEvent(CaseDetails details, + CaseDetails detailsBefore) { + PCSCase caseData = details.getData(); + + if (caseData.getDocumentRemovalDetails() == null) { + caseData.setDocumentRemovalDetails(new DocumentRemovalDetails()); + } + DocumentRemovalDetails documentRemovalDetails = caseData.getDocumentRemovalDetails(); + + documentSelectionService.initialise(details.getId(), caseData, documentRemovalDetails); + List errors = new ArrayList<>( + documentSelectionService.validateAndStoreSelection(caseData, documentRemovalDetails)); + + CaseFileCategory selectedFolder = documentRemovalDetails.getSelectedFolder(); + if (selectedFolder != null) { + String reason = documentRemovalDetails.getReasonForCategory(selectedFolder); + errors.addAll(textAreaValidationService.validateSingleTextArea( + reason, REASON_LABEL, TextAreaValidationService.SHORT_TEXT_LIMIT)); + } + + return AboutToStartOrSubmitResponse.builder() + .data(caseData) + .errorMessageOverride(StringUtils.joinIfNotEmpty("\n", errors)) + .build(); + } + + private String documentsShowCondition(DocumentCategoryField categoryField) { + return selectedFolderCondition(categoryField.category) + " AND " + FIELD_PREFIX + + categoryField.emptyFieldId + NO; + } + + private String noDocumentsShowCondition(DocumentCategoryField categoryField) { + return selectedFolderCondition(categoryField.category) + " AND " + FIELD_PREFIX + + categoryField.emptyFieldId + YES; + } + + private String reasonShowCondition(DocumentCategoryField categoryField) { + return selectedFolderCondition(categoryField.category) + " AND " + + sharedDocumentsFieldId(categoryField.category) + "!=\"\""; + } + + private String sharedDocumentsFieldId(CaseFileCategory category) { + return switch (category) { + case STATEMENTS_OF_CASE -> "statementsOfCaseDocuments"; + case PROPERTY_DOCUMENTS -> "propertyDocuments"; + case EVIDENCE -> "evidenceDocuments"; + case HEARING_DOCUMENTS -> "hearingDocuments"; + case ORDERS_AND_NOTICE_OF_HEARINGS -> "ordersAndNoticeOfHearingsDocuments"; + case APPLICATIONS -> "applicationsDocuments"; + case APPEALS -> "appealsDocuments"; + case CORRESPONDENCE -> "correspondenceDocuments"; + case UNCATEGORISED_DOCUMENTS -> "uncategorisedDocuments"; + }; + } + + private String selectedFolderCondition(CaseFileCategory category) { + return FIELD_PREFIX + "SelectedFolder=\"" + category.name() + "\""; + } + + private TypedPropertyGetter reasonGetter(CaseFileCategory category) { + for (DocumentCategoryField categoryField : DocumentCategoryField.values()) { + if (categoryField.category == category) { + return categoryField.reasonGetter; + } + } + throw new IllegalStateException("No reason field configured for category " + category); + } + + private String emptyFolderMessage(CaseFileCategory category) { + return DOCUMENT_QUESTION_LABEL + + "
" + + "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 3cfbd8e8cc..4d57cb90b7 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,7 +8,6 @@ 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; @@ -36,25 +35,23 @@ public DocumentAmendSelectionService(PcsCaseService pcsCaseService, AddressForma this.addressFormatter = addressFormatter; } - public void initialise(long caseReference, PCSCase caseData) { - DocumentAmendDetails details = getOrCreateDetails(caseData); + public void initialise(long caseReference, PCSCase caseData, DocumentFolderSelection details) { PcsCaseEntity pcsCase = pcsCaseService.loadCase(caseReference); + details.setPropertyAddressSummary( + addressFormatter.formatShortAddress(caseData.getPropertyAddress(), COMMA_DELIMITER)); - details.setPropertyAddressSummary(addressFormatter.formatShortAddress(caseData.getPropertyAddress(), - COMMA_DELIMITER)); for (CaseFileCategory category : CaseFileCategory.values()) { - setDocumentsForCategory(details, pcsCase, category); + setDocumentsForCategory(details, caseData, pcsCase, category); } } - public List validateAndStoreSelection(PCSCase caseData) { - DocumentAmendDetails details = caseData.getDocumentAmendDetails(); + public List validateAndStoreSelection(PCSCase caseData, DocumentFolderSelection details) { if (details == null || details.getSelectedFolder() == null) { return List.of(); } CaseFileCategory selectedFolder = details.getSelectedFolder(); - DynamicList selectedDocuments = documentsForCategory(details, selectedFolder); + DynamicList selectedDocuments = documentsForCategory(caseData, selectedFolder); details.setSelectedFolderId(selectedFolder.getId()); details.setSelectedFolderLabel(selectedFolder.getLabel()); @@ -76,11 +73,11 @@ public List validateAndStoreSelection(PCSCase caseData) { return List.of(); } - private void setDocumentsForCategory(DocumentAmendDetails details, PcsCaseEntity pcsCase, + private void setDocumentsForCategory(DocumentFolderSelection details, PCSCase caseData, PcsCaseEntity pcsCase, CaseFileCategory category) { - DynamicList documents = documentList(pcsCase, category, documentsForCategory(details, category)); - applyDocumentsForCategory(details, category, documents); - setEmptyForCategory(details, category, YesOrNo.from(isEmpty(documents))); + DynamicList documents = documentList(pcsCase, category, documentsForCategory(caseData, category)); + applyDocumentsForCategory(caseData, category, documents); + details.setEmptyForCategory(category, YesOrNo.from(isEmpty(documents))); } private DynamicList documentList(PcsCaseEntity pcsCase, CaseFileCategory category, @@ -126,53 +123,31 @@ 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) { + private DynamicList documentsForCategory(PCSCase caseData, 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(); + case STATEMENTS_OF_CASE -> caseData.getStatementsOfCaseDocuments(); + case PROPERTY_DOCUMENTS -> caseData.getPropertyDocuments(); + case EVIDENCE -> caseData.getEvidenceDocuments(); + case HEARING_DOCUMENTS -> caseData.getHearingDocuments(); + case ORDERS_AND_NOTICE_OF_HEARINGS -> caseData.getOrdersAndNoticeOfHearingsDocuments(); + case APPLICATIONS -> caseData.getApplicationsDocuments(); + case APPEALS -> caseData.getAppealsDocuments(); + case CORRESPONDENCE -> caseData.getCorrespondenceDocuments(); + case UNCATEGORISED_DOCUMENTS -> caseData.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) { + private void applyDocumentsForCategory(PCSCase caseData, CaseFileCategory category, DynamicList documents) { 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); + case STATEMENTS_OF_CASE -> caseData.setStatementsOfCaseDocuments(documents); + case PROPERTY_DOCUMENTS -> caseData.setPropertyDocuments(documents); + case EVIDENCE -> caseData.setEvidenceDocuments(documents); + case HEARING_DOCUMENTS -> caseData.setHearingDocuments(documents); + case ORDERS_AND_NOTICE_OF_HEARINGS -> caseData.setOrdersAndNoticeOfHearingsDocuments(documents); + case APPLICATIONS -> caseData.setApplicationsDocuments(documents); + case APPEALS -> caseData.setAppealsDocuments(documents); + case CORRESPONDENCE -> caseData.setCorrespondenceDocuments(documents); + case UNCATEGORISED_DOCUMENTS -> caseData.setUncategorisedDocuments(documents); } } } diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentFolderSelection.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentFolderSelection.java new file mode 100644 index 0000000000..568abcee78 --- /dev/null +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentFolderSelection.java @@ -0,0 +1,21 @@ +package uk.gov.hmcts.reform.pcs.ccd.service.document; + +import uk.gov.hmcts.ccd.sdk.type.YesOrNo; +import uk.gov.hmcts.reform.pcs.ccd.domain.CaseFileCategory; + +public interface DocumentFolderSelection { + + CaseFileCategory getSelectedFolder(); + + void setPropertyAddressSummary(String propertyAddressSummary); + + void setEmptyForCategory(CaseFileCategory category, YesOrNo empty); + + void setSelectedFolderId(String id); + + void setSelectedFolderLabel(String label); + + void setSelectedDocumentId(String id); + + void setSelectedDocumentFileName(String fileName); +} From e03982f62f3c04f3c5cf6626c91dcf73de4e42c7 Mon Sep 17 00:00:00 2001 From: Liban Abdirahman Date: Fri, 17 Jul 2026 14:10:13 +0100 Subject: [PATCH 32/42] HDPI-6454:Adding migration script and document removal service --- .../reform/pcs/ccd/entity/DocumentEntity.java | 7 ++++ .../document/DocumentRemovalService.java | 32 +++++++++++++++++++ .../V136__add_document_removal_columns.sql | 12 +++++++ 3 files changed, 51 insertions(+) create mode 100644 src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentRemovalService.java create mode 100644 src/main/resources/db/migration/V136__add_document_removal_columns.sql diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/entity/DocumentEntity.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/entity/DocumentEntity.java index b5d92ae2ec..6bd80e6f04 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/entity/DocumentEntity.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/entity/DocumentEntity.java @@ -26,6 +26,7 @@ import uk.gov.hmcts.reform.pcs.ccd.entity.respondpossessionclaim.DefendantResponseEntity; import java.time.Instant; +import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; import java.util.UUID; @@ -103,6 +104,12 @@ public class DocumentEntity { @JoinColumn(name = "counter_claim_id") private CounterClaimEntity counterClaim; + private boolean removed; + + private String removalReason; + + private LocalDateTime removedAt; + @PrePersist void prePersist() { if (submittedDate == null) { diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentRemovalService.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentRemovalService.java new file mode 100644 index 0000000000..4e19d2de5d --- /dev/null +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentRemovalService.java @@ -0,0 +1,32 @@ +package uk.gov.hmcts.reform.pcs.ccd.service.document; + +import org.springframework.stereotype.Service; +import uk.gov.hmcts.reform.pcs.ccd.entity.DocumentEntity; +import uk.gov.hmcts.reform.pcs.ccd.repository.DocumentRepository; + +import java.time.LocalDateTime; +import java.util.UUID; + +@Service +public class DocumentRemovalService { + + private final DocumentRepository documentRepository; + private final DocumentImportService documentImportService; + + public DocumentRemovalService(DocumentRepository documentRepository, + DocumentImportService documentImportService) { + this.documentRepository = documentRepository; + this.documentImportService = documentImportService; + } + + public void removeDocument(UUID documentEntityId, String reason) { + DocumentEntity documentEntity = documentRepository.findById(documentEntityId).orElseThrow(); + + documentImportService.deleteDocument(documentEntity.getUrl()); + + documentEntity.setRemoved(true); + documentEntity.setRemovalReason(reason); + documentEntity.setRemovedAt(LocalDateTime.now()); + documentRepository.save(documentEntity); + } +} diff --git a/src/main/resources/db/migration/V136__add_document_removal_columns.sql b/src/main/resources/db/migration/V136__add_document_removal_columns.sql new file mode 100644 index 0000000000..e0b0b7b6c5 --- /dev/null +++ b/src/main/resources/db/migration/V136__add_document_removal_columns.sql @@ -0,0 +1,12 @@ +ALTER TABLE document +ADD COLUMN removed BOOLEAN, +ADD COLUMN removal_reason VARCHAR(250), +ADD COLUMN removed_at TIMESTAMP; + +UPDATE document +SET removed = FALSE +WHERE removed IS NULL; + +ALTER TABLE document +ALTER COLUMN removed SET DEFAULT FALSE, +ALTER COLUMN removed SET NOT NULL; \ No newline at end of file From a28e4dba0df9989b9e09da4c6c0a18c31679eefd Mon Sep 17 00:00:00 2001 From: Liban Abdirahman Date: Fri, 17 Jul 2026 14:11:33 +0100 Subject: [PATCH 33/42] HDPI-6454:Updating document views to filter out documents flagged for removal --- .../service/document/DocumentAmendSelectionService.java | 1 + .../java/uk/gov/hmcts/reform/pcs/ccd/view/ClaimView.java | 3 +++ .../uk/gov/hmcts/reform/pcs/ccd/view/DocumentsView.java | 7 ++++++- .../hmcts/reform/pcs/ccd/view/NoticeOfPossessionView.java | 1 + .../uk/gov/hmcts/reform/pcs/ccd/view/RentArrearsView.java | 1 + .../gov/hmcts/reform/pcs/ccd/view/TenancyLicenceView.java | 2 ++ 6 files changed, 14 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 4d57cb90b7..2dbc395dc6 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 @@ -90,6 +90,7 @@ private DynamicList documentList(PcsCaseEntity pcsCase, CaseFileCategory categor .filter(Objects::nonNull) .filter(document -> isInCategory(document, category)) .filter(document -> document.getType() != DocumentType.DEFENDANT_ACCESS_CODE) + .filter(document -> !document.isRemoved()) .sorted(DOCUMENT_ORDER) .map(document -> DynamicListElement.builder() .code(document.getId()) diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/view/ClaimView.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/view/ClaimView.java index 2e6eb0dfa8..28235b8527 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/view/ClaimView.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/view/ClaimView.java @@ -100,6 +100,7 @@ private static List> getEnergyPerformanceCertificate(PcsCase return pcsCaseEntity.getDocuments().stream() .filter(ClaimView::isEnergyPerformanceCertificate) .filter(DocumentsView::isDescriptionEmpty) + .filter(DocumentsView::isNotRemoved) .map(ClaimView::toDocument) .toList(); } @@ -112,6 +113,7 @@ private static List> getGasSafetyReport(PcsCaseEntity pcsCas return pcsCaseEntity.getDocuments().stream() .filter(ClaimView::isGasSafetyReport) .filter(DocumentsView::isDescriptionEmpty) + .filter(DocumentsView::isNotRemoved) .map(ClaimView::toDocument) .toList(); } @@ -124,6 +126,7 @@ private static List> getElectricalInstallationCondition(PcsC return pcsCaseEntity.getDocuments().stream() .filter(ClaimView::isElectricalInstallationCondition) .filter(DocumentsView::isDescriptionEmpty) + .filter(DocumentsView::isNotRemoved) .map(ClaimView::toDocument) .toList(); } 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..0139c8172b 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 @@ -77,7 +77,8 @@ public boolean isDocumentVisibleToUser(DocumentEntity documentEntity, UUID curre } private boolean isExcludedFromCaseFile(DocumentEntity documentEntity) { - return documentEntity.getType() == DocumentType.DEFENDANT_ACCESS_CODE; + return documentEntity.getType() == DocumentType.DEFENDANT_ACCESS_CODE + || documentEntity.isRemoved(); } public static boolean isDescriptionEmpty(DocumentEntity documentEntity) { @@ -85,6 +86,10 @@ public static boolean isDescriptionEmpty(DocumentEntity documentEntity) { || documentEntity.getDescription().trim().isEmpty(); } + public static boolean isNotRemoved(DocumentEntity documentEntity) { + return !documentEntity.isRemoved(); + } + private boolean isNotInCaseDetailsTab(DocumentEntity documentEntity) { List caseDetailsDocuments = List.of( DocumentType.TENANCY_AGREEMENT, diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/view/NoticeOfPossessionView.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/view/NoticeOfPossessionView.java index eae6346760..0243153c64 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/view/NoticeOfPossessionView.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/view/NoticeOfPossessionView.java @@ -96,6 +96,7 @@ private static List> getNoticeStatement(PcsCaseEntity pcsCas return pcsCaseEntity.getDocuments().stream() .filter(NoticeOfPossessionView::isNoticeStatement) .filter(DocumentsView::isDescriptionEmpty) + .filter(DocumentsView::isNotRemoved) .map(NoticeOfPossessionView::toDocument) .toList(); } diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/view/RentArrearsView.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/view/RentArrearsView.java index 06a0369cd3..77a04557ea 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/view/RentArrearsView.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/view/RentArrearsView.java @@ -48,6 +48,7 @@ private static List> getRentStatement(PcsCaseEntity pcsCaseE return pcsCaseEntity.getDocuments().stream() .filter(RentArrearsView::isRentStatement) .filter(DocumentsView::isDescriptionEmpty) + .filter(DocumentsView::isNotRemoved) .map(RentArrearsView::toDocument) .toList(); } diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/view/TenancyLicenceView.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/view/TenancyLicenceView.java index 6c6dd3570f..4a27a5947a 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/view/TenancyLicenceView.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/view/TenancyLicenceView.java @@ -75,6 +75,7 @@ private static List> getTenancyLicenceDocument(PcsCaseEntity return pcsCaseEntity.getDocuments().stream() .filter(TenancyLicenceView::isTenancyLicence) .filter(DocumentsView::isDescriptionEmpty) + .filter(DocumentsView::isNotRemoved) .map(TenancyLicenceView::toDocument) .toList(); } @@ -91,6 +92,7 @@ private static List> getOccupationLicenceDocument(PcsCaseEnt return pcsCaseEntity.getDocuments().stream() .filter(TenancyLicenceView::isOccupationLicence) .filter(DocumentsView::isDescriptionEmpty) + .filter(DocumentsView::isNotRemoved) .map(TenancyLicenceView::toDocument) .toList(); } From 6560d4efe566b526300128946ab6c5906dcf08f6 Mon Sep 17 00:00:00 2001 From: srinijg Date: Fri, 17 Jul 2026 15:02:42 +0100 Subject: [PATCH 34/42] user update --- src/e2eTest/data/user-data/permanent.user.data.ts | 4 ++++ .../caseManagement.manageDocuments.spec.ts | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) 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.manageDocuments.spec.ts b/src/e2eTest/tests/test-caseManagement/caseManagement.manageDocuments.spec.ts index bd8ae4a657..614f721fba 100644 --- a/src/e2eTest/tests/test-caseManagement/caseManagement.manageDocuments.spec.ts +++ b/src/e2eTest/tests/test-caseManagement/caseManagement.manageDocuments.spec.ts @@ -29,7 +29,7 @@ test.beforeEach(async ({ page, context }) => { }; await performAction('navigateToUrl', process.env.MANAGE_CASE_BASE_URL); await dismissCookieBanner(page, 'additional'); - await performAction('login', user.staffAdmin); + await performAction('login', user.hearingCenterAdmin); await dismissCookieBanner(page, 'analytics'); await performAction('navigateToSummaryPage'); }); From dc481c840716b433f2ef3470feb3fd311fb349c7 Mon Sep 17 00:00:00 2001 From: Liban Abdirahman Date: Fri, 17 Jul 2026 16:34:41 +0100 Subject: [PATCH 35/42] HDPI-6454:Adding and updating existing tests --- .../ccd/accesscontrol/CaseworkerRoles.java | 12 ++ .../accesscontrol/ManageDocumentsStates.java | 14 ++ .../DocumentRemoval.java} | 32 +++- .../document/DocumentRemovalService.java | 4 +- .../exception/DocumentNotFoundException.java | 10 ++ .../documentremoval/DocumentRemovalTest.java | 92 +++++++++++ .../SelectDocumentToRemovePageTest.java | 100 ++++++++++++ .../DocumentAmendSelectionServiceTest.java | 145 ++++++++++-------- .../document/DocumentRemovalServiceTest.java | 90 +++++++++++ 9 files changed, 430 insertions(+), 69 deletions(-) create mode 100644 src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/CaseworkerRoles.java create mode 100644 src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/ManageDocumentsStates.java rename src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/{RemoveDocuments.java => documentremoval/DocumentRemoval.java} (63%) create mode 100644 src/main/java/uk/gov/hmcts/reform/pcs/exception/DocumentNotFoundException.java create mode 100644 src/test/java/uk/gov/hmcts/reform/pcs/ccd/event/documentremoval/DocumentRemovalTest.java create mode 100644 src/test/java/uk/gov/hmcts/reform/pcs/ccd/page/documentremoval/SelectDocumentToRemovePageTest.java create mode 100644 src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentRemovalServiceTest.java 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..3f3e950bc6 --- /dev/null +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/CaseworkerRoles.java @@ -0,0 +1,12 @@ +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, + }; + + private CaseworkerRoles() { + } +} \ No newline at end of file diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/ManageDocumentsStates.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/ManageDocumentsStates.java new file mode 100644 index 0000000000..93b6031ed6 --- /dev/null +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/ManageDocumentsStates.java @@ -0,0 +1,14 @@ +package uk.gov.hmcts.reform.pcs.ccd.accesscontrol; + +import uk.gov.hmcts.reform.pcs.ccd.domain.State; + +public final class ManageDocumentsStates { + + public static final State[] MANAGE_DOCUMENTS_STATES = { + State.PENDING_CASE_ISSUED, + State.CASE_ISSUED + }; + + private ManageDocumentsStates() { + } +} \ No newline at end of file diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/RemoveDocuments.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/documentremoval/DocumentRemoval.java similarity index 63% rename from src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/RemoveDocuments.java rename to src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/documentremoval/DocumentRemoval.java index c2e2a8ad61..e906a88675 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/RemoveDocuments.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/documentremoval/DocumentRemoval.java @@ -1,4 +1,4 @@ -package uk.gov.hmcts.reform.pcs.ccd.event; +package uk.gov.hmcts.reform.pcs.ccd.event.documentremoval; import lombok.AllArgsConstructor; import org.springframework.stereotype.Component; @@ -19,11 +19,14 @@ import java.util.UUID; +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.accesscontrol.ManageDocumentsStates.MANAGE_DOCUMENTS_STATES; import static uk.gov.hmcts.reform.pcs.ccd.event.EventId.removeDocuments; @Component @AllArgsConstructor -public class RemoveDocuments implements CCDConfig { +public class DocumentRemoval implements CCDConfig { private final DocumentAmendSelectionService documentSelectionService; private final DocumentRemovalService documentRemovalService; @@ -34,10 +37,10 @@ public void configureDecentralised(DecentralisedConfigBuilder eventBuilder = configBuilder .decentralisedEvent(removeDocuments.name(), this::submit, this::start) - .forStates(State.CASE_ISSUED) + .forStates(MANAGE_DOCUMENTS_STATES) .name("Manage documents: Remove") - .grant(Permission.CRU, UserRole.HEARING_CENTRE_ADMIN) - .grant(Permission.CRU, UserRole.HEARING_CENTRE_TEAM_LEADER) + .grant(Permission.CRU, CASEWORKER_ROLES) + .grantHistoryOnly(JUDICIAL_HISTORY_ROLES) .showSummary() .endButtonLabel("Submit"); @@ -63,6 +66,23 @@ private SubmitResponse submit(EventPayload eventPayload) documentRemovalService.removeDocument(UUID.fromString(details.getSelectedDocumentId()), reason); - return SubmitResponse.defaultResponse(); + return SubmitResponse.builder() + .confirmationBody(buildConfirmationMarkdown(details, eventPayload.caseReference())) + .build(); + } + + private String buildConfirmationMarkdown(DocumentRemovalDetails details, long caseReference) { + return """ + --- +
+ %s removed
+ Case number: %s
+ Property address: %s +
+ +

What happens next

+

The document will no longer appear in case file view

+ """.formatted( + details.getSelectedDocumentFileName(), caseReference, details.getPropertyAddressSummary()); } } diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentRemovalService.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentRemovalService.java index 4e19d2de5d..604ceb57f1 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentRemovalService.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentRemovalService.java @@ -3,6 +3,7 @@ import org.springframework.stereotype.Service; import uk.gov.hmcts.reform.pcs.ccd.entity.DocumentEntity; import uk.gov.hmcts.reform.pcs.ccd.repository.DocumentRepository; +import uk.gov.hmcts.reform.pcs.exception.DocumentNotFoundException; import java.time.LocalDateTime; import java.util.UUID; @@ -20,7 +21,8 @@ public DocumentRemovalService(DocumentRepository documentRepository, } public void removeDocument(UUID documentEntityId, String reason) { - DocumentEntity documentEntity = documentRepository.findById(documentEntityId).orElseThrow(); + DocumentEntity documentEntity = documentRepository.findById(documentEntityId) + .orElseThrow(() -> new DocumentNotFoundException(documentEntityId)); documentImportService.deleteDocument(documentEntity.getUrl()); diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/exception/DocumentNotFoundException.java b/src/main/java/uk/gov/hmcts/reform/pcs/exception/DocumentNotFoundException.java new file mode 100644 index 0000000000..06e13c5c2e --- /dev/null +++ b/src/main/java/uk/gov/hmcts/reform/pcs/exception/DocumentNotFoundException.java @@ -0,0 +1,10 @@ +package uk.gov.hmcts.reform.pcs.exception; + +import java.util.UUID; + +public class DocumentNotFoundException extends RuntimeException { + + public DocumentNotFoundException(UUID documentId) { + super("No document found with id: " + documentId); + } +} diff --git a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/event/documentremoval/DocumentRemovalTest.java b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/event/documentremoval/DocumentRemovalTest.java new file mode 100644 index 0000000000..6ba04bacfc --- /dev/null +++ b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/event/documentremoval/DocumentRemovalTest.java @@ -0,0 +1,92 @@ +package uk.gov.hmcts.reform.pcs.ccd.event.documentremoval; + +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.api.callback.SubmitResponse; +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.documentremoval.DocumentRemovalDetails; +import uk.gov.hmcts.reform.pcs.ccd.event.BaseEventTest; +import uk.gov.hmcts.reform.pcs.ccd.page.documentremoval.SelectDocumentToRemovePage; +import uk.gov.hmcts.reform.pcs.ccd.service.document.DocumentAmendSelectionService; +import uk.gov.hmcts.reform.pcs.ccd.service.document.DocumentRemovalService; + +import java.util.UUID; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.verify; + +@ExtendWith(MockitoExtension.class) +class DocumentRemovalTest extends BaseEventTest { + + @Mock + private DocumentAmendSelectionService documentSelectionService; + @Mock + private DocumentRemovalService documentRemovalService; + @Mock + private SelectDocumentToRemovePage selectDocumentToRemovePage; + + @BeforeEach + void setUp() { + DocumentRemoval underTest = new DocumentRemoval( + documentSelectionService, documentRemovalService, selectDocumentToRemovePage + ); + + setEventUnderTest(underTest); + } + + @Test + void shouldCreateDocumentRemovalDetailsWhenAbsentOnStart() { + PCSCase caseData = PCSCase.builder().build(); + + PCSCase result = callStartHandler(caseData); + + assertThat(result.getDocumentRemovalDetails()).isNotNull(); + verify(documentSelectionService).initialise( + eq(TEST_CASE_REFERENCE), eq(result), eq(result.getDocumentRemovalDetails())); + } + + @Test + void shouldReuseExistingDocumentRemovalDetailsOnStart() { + DocumentRemovalDetails existingDetails = DocumentRemovalDetails.builder() + .selectedFolder(CaseFileCategory.EVIDENCE) + .build(); + PCSCase caseData = PCSCase.builder() + .documentRemovalDetails(existingDetails) + .build(); + + PCSCase result = callStartHandler(caseData); + + assertThat(result.getDocumentRemovalDetails()).isSameAs(existingDetails); + verify(documentSelectionService).initialise(TEST_CASE_REFERENCE, result, existingDetails); + } + + @Test + void shouldBuildConfirmationPageWithRemovedDocumentDetails() { + UUID documentId = UUID.randomUUID(); + String reason = "No longer required"; + DocumentRemovalDetails details = DocumentRemovalDetails.builder() + .selectedFolder(CaseFileCategory.EVIDENCE) + .selectedDocumentId(documentId.toString()) + .selectedDocumentFileName("evidence.pdf") + .propertyAddressSummary("123 Test Street, Testville, TE1 1ST") + .evidenceReason(reason) + .build(); + PCSCase caseData = PCSCase.builder() + .documentRemovalDetails(details) + .build(); + + SubmitResponse response = callSubmitHandler(caseData); + + verify(documentRemovalService).removeDocument(documentId, reason); + assertThat(response.getConfirmationBody()) + .contains("evidence.pdf") + .contains("Case number: " + TEST_CASE_REFERENCE) + .contains("123 Test Street, Testville, TE1 1ST"); + } +} diff --git a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/page/documentremoval/SelectDocumentToRemovePageTest.java b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/page/documentremoval/SelectDocumentToRemovePageTest.java new file mode 100644 index 0000000000..4422ec16c9 --- /dev/null +++ b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/page/documentremoval/SelectDocumentToRemovePageTest.java @@ -0,0 +1,100 @@ +package uk.gov.hmcts.reform.pcs.ccd.page.documentremoval; + +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.api.callback.AboutToStartOrSubmitResponse; +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.documentremoval.DocumentRemovalDetails; +import uk.gov.hmcts.reform.pcs.ccd.page.BasePageTest; +import uk.gov.hmcts.reform.pcs.ccd.service.TextAreaValidationService; +import uk.gov.hmcts.reform.pcs.ccd.service.document.DocumentAmendSelectionService; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class SelectDocumentToRemovePageTest extends BasePageTest { + + @Mock + private DocumentAmendSelectionService documentSelectionService; + + @BeforeEach + void setUp() { + setPageUnderTest(new SelectDocumentToRemovePage(documentSelectionService, new TextAreaValidationService())); + } + + @Test + void shouldCreateDocumentRemovalDetailsWhenAbsent() { + PCSCase caseData = PCSCase.builder().build(); + + callMidEventHandler(caseData); + + assertThat(caseData.getDocumentRemovalDetails()).isNotNull(); + verify(documentSelectionService).initialise( + TEST_CASE_REFERENCE, caseData, caseData.getDocumentRemovalDetails()); + } + + @Test + void shouldReuseExistingDocumentRemovalDetails() { + DocumentRemovalDetails existingDetails = DocumentRemovalDetails.builder() + .selectedFolder(CaseFileCategory.EVIDENCE) + .build(); + PCSCase caseData = PCSCase.builder() + .documentRemovalDetails(existingDetails) + .build(); + + callMidEventHandler(caseData); + + assertThat(caseData.getDocumentRemovalDetails()).isSameAs(existingDetails); + verify(documentSelectionService).initialise(TEST_CASE_REFERENCE, caseData, existingDetails); + } + + @Test + void shouldSurfaceErrorsFromDocumentSelectionService() { + PCSCase caseData = PCSCase.builder().build(); + when(documentSelectionService.validateAndStoreSelection(eq(caseData), any())) + .thenReturn(List.of("Select a different folder to continue")); + + AboutToStartOrSubmitResponse response = callMidEventHandler(caseData); + + assertThat(response.getErrorMessageOverride()).isEqualTo("Select a different folder to continue"); + } + + @Test + void shouldNotValidateReasonWhenNoFolderSelected() { + PCSCase caseData = PCSCase.builder() + .documentRemovalDetails(DocumentRemovalDetails.builder().build()) + .build(); + + AboutToStartOrSubmitResponse response = callMidEventHandler(caseData); + + assertThat(response.getErrorMessageOverride()).isNull(); + } + + @Test + void shouldValidateRemovalReasonLengthForSelectedDocument() { + String tooLongReason = "a".repeat(TextAreaValidationService.SHORT_TEXT_LIMIT + 1); + DocumentRemovalDetails details = DocumentRemovalDetails.builder() + .selectedFolder(CaseFileCategory.EVIDENCE) + .evidenceReason(tooLongReason) + .build(); + PCSCase caseData = PCSCase.builder() + .documentRemovalDetails(details) + .build(); + + AboutToStartOrSubmitResponse response = callMidEventHandler(caseData); + + assertThat(response.getErrorMessageOverride()) + .contains("Why are you removing this document?"); + } +} 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 bd89aa8488..3b6607c623 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 @@ -7,6 +7,7 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import uk.gov.hmcts.ccd.sdk.type.AddressUK; import uk.gov.hmcts.ccd.sdk.type.DynamicList; import uk.gov.hmcts.ccd.sdk.type.DynamicListElement; import uk.gov.hmcts.ccd.sdk.type.YesOrNo; @@ -67,16 +68,17 @@ void shouldDefineFolderDropdownWithCaseFileViewFolders() { void shouldPopulatePropertyAddressSummary() { when(pcsCaseService.loadCase(CASE_REFERENCE)).thenReturn(PcsCaseEntity.builder().build()); PCSCase caseData = PCSCase.builder() - .propertyAddress(uk.gov.hmcts.ccd.sdk.type.AddressUK.builder() + .propertyAddress(AddressUK.builder() .addressLine1("15 Garden Drive") .postTown("Luton") .postCode("LU1 1AB") .build()) .build(); + DocumentAmendDetails details = new DocumentAmendDetails(); - underTest.initialise(CASE_REFERENCE, caseData); + underTest.initialise(CASE_REFERENCE, caseData, details); - assertThat(caseData.getDocumentAmendDetails().getPropertyAddressSummary()) + assertThat(details.getPropertyAddressSummary()) .isEqualTo("15 Garden Drive, Luton, LU1 1AB"); } @@ -90,15 +92,15 @@ void shouldSerialiseDocumentAmendFieldsWithGeneratedCcdFieldIds() throws JsonPro .build())) .build(); PCSCase caseData = PCSCase.builder() + .applicationsDocuments(applicationsDocuments) .documentAmendDetails(DocumentAmendDetails.builder() - .applicationsDocuments(applicationsDocuments) .applicationsEmpty(YesOrNo.NO) .build()) .build(); String serialisedCaseData = new ObjectMapper().writeValueAsString(caseData); - assertThat(serialisedCaseData).contains("\"documentAmend_ApplicationsDocuments\""); + assertThat(serialisedCaseData).contains("\"applicationsDocuments\""); assertThat(serialisedCaseData).contains("\"documentAmend_ApplicationsEmpty\""); assertThat(serialisedCaseData).doesNotContain("documentAmend_applicationsDocuments"); } @@ -121,17 +123,17 @@ void shouldPopulateDocumentsForSelectedCategoryAndIncludeWithoutNoticeApplicatio .build(); when(pcsCaseService.loadCase(CASE_REFERENCE)).thenReturn(pcsCase); PCSCase caseData = PCSCase.builder().build(); + DocumentAmendDetails details = new DocumentAmendDetails(); - underTest.initialise(CASE_REFERENCE, caseData); + underTest.initialise(CASE_REFERENCE, caseData, details); - DocumentAmendDetails details = caseData.getDocumentAmendDetails(); - assertThat(details.getEvidenceDocuments().getListItems()) + assertThat(caseData.getEvidenceDocuments().getListItems()) .extracting(DynamicListElement::getLabel) .containsExactly("visible evidence.pdf"); - assertThat(details.getApplicationsDocuments().getListItems()) + assertThat(caseData.getApplicationsDocuments().getListItems()) .extracting(DynamicListElement::getLabel) .containsExactly("visible application.pdf", "without notice application.pdf"); - assertThat(details.getApplicationsDocuments().getValue()).isNull(); + assertThat(caseData.getApplicationsDocuments().getValue()).isNull(); } @Test @@ -146,38 +148,59 @@ void shouldExcludeDocumentsWithNullCategoryIdFromUncategorisedDocuments() { .documents(List.of(nullCategoryDocument, categorisedDocument)) .build()); PCSCase caseData = PCSCase.builder().build(); + DocumentAmendDetails details = new DocumentAmendDetails(); - underTest.initialise(CASE_REFERENCE, caseData); + underTest.initialise(CASE_REFERENCE, caseData, details); - assertThat(caseData.getDocumentAmendDetails().getUncategorisedDocuments().getListItems()) + assertThat(caseData.getUncategorisedDocuments().getListItems()) .extracting(DynamicListElement::getLabel) .containsExactly("uncategorised document.pdf"); - assertThat(caseData.getDocumentAmendDetails().getUncategorisedDocumentsEmpty()).isEqualTo(YesOrNo.NO); + assertThat(details.getUncategorisedDocumentsEmpty()).isEqualTo(YesOrNo.NO); } @Test void shouldExcludeDefendantAccessCodeDocumentsFromUncategorisedDocuments() { - DocumentEntity accessCodeDocument = documentWithType( + DocumentEntity accessCodeDocument = buildDocumentEntity( null, UNCATEGORISED_DOCUMENTS.getId(), - DocumentType.DEFENDANT_ACCESS_CODE + DocumentType.DEFENDANT_ACCESS_CODE, + false ); - DocumentEntity visibleDocument = documentWithType( + DocumentEntity visibleDocument = buildDocumentEntity( "uncategorised document.pdf", UNCATEGORISED_DOCUMENTS.getId(), - DocumentType.OTHER + DocumentType.OTHER, + false ); when(pcsCaseService.loadCase(CASE_REFERENCE)).thenReturn(PcsCaseEntity.builder() .documents(List.of(accessCodeDocument, visibleDocument)) .build()); PCSCase caseData = PCSCase.builder().build(); + DocumentAmendDetails details = new DocumentAmendDetails(); - underTest.initialise(CASE_REFERENCE, caseData); + underTest.initialise(CASE_REFERENCE, caseData, details); - assertThat(caseData.getDocumentAmendDetails().getUncategorisedDocuments().getListItems()) + assertThat(caseData.getUncategorisedDocuments().getListItems()) .extracting(DynamicListElement::getLabel) .containsExactly("uncategorised document.pdf"); - assertThat(caseData.getDocumentAmendDetails().getUncategorisedDocumentsEmpty()).isEqualTo(YesOrNo.NO); + assertThat(details.getUncategorisedDocumentsEmpty()).isEqualTo(YesOrNo.NO); + } + + @Test + void shouldExcludeRemovedDocumentsFromSelection() { + DocumentEntity removedDocument = buildDocumentEntity("removed evidence.pdf", EVIDENCE.getId(), null, true); + DocumentEntity activeDocument = buildDocumentEntity("active evidence.pdf", EVIDENCE.getId(), null, false); + when(pcsCaseService.loadCase(CASE_REFERENCE)).thenReturn(PcsCaseEntity.builder() + .documents(List.of(removedDocument, activeDocument)) + .build()); + PCSCase caseData = PCSCase.builder().build(); + DocumentAmendDetails details = new DocumentAmendDetails(); + + underTest.initialise(CASE_REFERENCE, caseData, details); + + assertThat(caseData.getEvidenceDocuments().getListItems()) + .extracting(DynamicListElement::getLabel) + .containsExactly("active evidence.pdf"); } @Test @@ -205,10 +228,11 @@ void shouldOrderDocumentsBySubmittedDateDescendingThenFileNameWithNullDatesLast( .documents(List.of(older, nullDate, newerB, newerA)) .build()); PCSCase caseData = PCSCase.builder().build(); + DocumentAmendDetails details = new DocumentAmendDetails(); - underTest.initialise(CASE_REFERENCE, caseData); + underTest.initialise(CASE_REFERENCE, caseData, details); - assertThat(caseData.getDocumentAmendDetails().getEvidenceDocuments().getListItems()) + assertThat(caseData.getEvidenceDocuments().getListItems()) .extracting(DynamicListElement::getLabel) .containsExactly( "a newer evidence.pdf", @@ -220,7 +244,7 @@ void shouldOrderDocumentsBySubmittedDateDescendingThenFileNameWithNullDatesLast( @Test void shouldReturnNoErrorsWhenDocumentAmendDetailsIsNull() { - List errors = underTest.validateAndStoreSelection(PCSCase.builder().build()); + List errors = underTest.validateAndStoreSelection(PCSCase.builder().build(),null); assertThat(errors).isEmpty(); } @@ -228,22 +252,19 @@ void shouldReturnNoErrorsWhenDocumentAmendDetailsIsNull() { @Test void shouldReturnDifferentFolderErrorWhenSelectedFolderHasNoDocuments() { when(pcsCaseService.loadCase(CASE_REFERENCE)).thenReturn(PcsCaseEntity.builder().build()); - PCSCase caseData = PCSCase.builder() - .documentAmendDetails(DocumentAmendDetails.builder() - .selectedFolder(UNCATEGORISED_DOCUMENTS) - .build()) + PCSCase caseData = PCSCase.builder().build(); + DocumentAmendDetails details = DocumentAmendDetails.builder() + .selectedFolder(UNCATEGORISED_DOCUMENTS) .build(); - underTest.initialise(CASE_REFERENCE, caseData); + underTest.initialise(CASE_REFERENCE, caseData, details); - List errors = underTest.validateAndStoreSelection(caseData); + List errors = underTest.validateAndStoreSelection(caseData, details); 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(); + assertThat(details.getSelectedFolderId()).isEqualTo(UNCATEGORISED_DOCUMENTS.getId()); + assertThat(details.getSelectedFolderLabel()).isEqualTo(UNCATEGORISED_DOCUMENTS.getLabel()); + assertThat(details.getSelectedDocumentId()).isNull(); + assertThat(details.getSelectedDocumentFileName()).isNull(); } @Test @@ -253,19 +274,18 @@ void shouldTreatEmptyDocumentSelectionAsNoSelection() { .documents(List.of(document)) .build()); PCSCase caseData = PCSCase.builder() - .documentAmendDetails(DocumentAmendDetails.builder() - .selectedFolder(EVIDENCE) - .evidenceDocuments(DynamicList.builder() - .build()) - .build()) + .evidenceDocuments(DynamicList.builder().build()) .build(); - underTest.initialise(CASE_REFERENCE, caseData); + DocumentAmendDetails details = DocumentAmendDetails.builder() + .selectedFolder(EVIDENCE) + .build(); + underTest.initialise(CASE_REFERENCE, caseData, details); - List errors = underTest.validateAndStoreSelection(caseData); + List errors = underTest.validateAndStoreSelection(caseData, details); assertThat(errors).isEmpty(); - assertThat(caseData.getDocumentAmendDetails().getSelectedDocumentId()).isNull(); - assertThat(caseData.getDocumentAmendDetails().getSelectedDocumentFileName()).isNull(); + assertThat(details.getSelectedDocumentId()).isNull(); + assertThat(details.getSelectedDocumentFileName()).isNull(); } @Test @@ -275,20 +295,20 @@ void shouldPersistSelectedFolderAndDocumentDetails() { .documents(List.of(document)) .build()); PCSCase caseData = PCSCase.builder() - .documentAmendDetails(DocumentAmendDetails.builder() - .selectedFolder(EVIDENCE) - .evidenceDocuments(selectedDocument(document)) - .build()) + .evidenceDocuments(selectedDocument(document)) .build(); - underTest.initialise(CASE_REFERENCE, caseData); + DocumentAmendDetails details = DocumentAmendDetails.builder() + .selectedFolder(EVIDENCE) + .build(); + underTest.initialise(CASE_REFERENCE, caseData, details); - List errors = underTest.validateAndStoreSelection(caseData); + List errors = underTest.validateAndStoreSelection(caseData, details); 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"); + assertThat(details.getSelectedFolderId()).isEqualTo(EVIDENCE.getId()); + assertThat(details.getSelectedFolderLabel()).isEqualTo(EVIDENCE.getLabel()); + assertThat(details.getSelectedDocumentId()).isEqualTo(document.getId().toString()); + assertThat(details.getSelectedDocumentFileName()).isEqualTo("photo.pdf"); } @Test @@ -297,17 +317,16 @@ void shouldLeaveMissingDocumentSelectionToExuiMandatoryValidation() { when(pcsCaseService.loadCase(CASE_REFERENCE)).thenReturn(PcsCaseEntity.builder() .documents(List.of(document)) .build()); - PCSCase caseData = PCSCase.builder() - .documentAmendDetails(DocumentAmendDetails.builder() - .selectedFolder(EVIDENCE) - .build()) + PCSCase caseData = PCSCase.builder().build(); + DocumentAmendDetails details = DocumentAmendDetails.builder() + .selectedFolder(EVIDENCE) .build(); - underTest.initialise(CASE_REFERENCE, caseData); + underTest.initialise(CASE_REFERENCE, caseData, details); - List errors = underTest.validateAndStoreSelection(caseData); + List errors = underTest.validateAndStoreSelection(caseData, details); assertThat(errors).isEmpty(); - assertThat(caseData.getDocumentAmendDetails().getSelectedDocumentId()).isNull(); + assertThat(details.getSelectedDocumentId()).isNull(); } private static DynamicList selectedDocument(DocumentEntity document) { @@ -337,12 +356,14 @@ private static DocumentEntity document(String fileName, String categoryId, GenAp .build(); } - private static DocumentEntity documentWithType(String fileName, String categoryId, DocumentType type) { + private static DocumentEntity buildDocumentEntity(String fileName, String categoryId, DocumentType type, + boolean removed) { return DocumentEntity.builder() .id(UUID.randomUUID()) .fileName(fileName) .categoryId(categoryId) .type(type) + .removed(removed) .submittedDate(Instant.now()) .build(); } diff --git a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentRemovalServiceTest.java b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentRemovalServiceTest.java new file mode 100644 index 0000000000..0a26df1a01 --- /dev/null +++ b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentRemovalServiceTest.java @@ -0,0 +1,90 @@ +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.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import uk.gov.hmcts.reform.pcs.ccd.entity.DocumentEntity; +import uk.gov.hmcts.reform.pcs.ccd.repository.DocumentRepository; +import uk.gov.hmcts.reform.pcs.exception.DocumentNotFoundException; + +import java.time.LocalDateTime; +import java.util.Optional; +import java.util.UUID; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class DocumentRemovalServiceTest { + + @Mock + private DocumentRepository documentRepository; + @Mock + private DocumentImportService documentImportService; + + private DocumentRemovalService underTest; + + @BeforeEach + void setUp() { + underTest = new DocumentRemovalService(documentRepository, documentImportService); + } + + @Test + void shouldSoftDeleteDocumentAndRemoveFromDocumentStore() { + UUID documentId = UUID.randomUUID(); + String reason = "Duplicate upload"; + DocumentEntity documentEntity = DocumentEntity.builder() + .id(documentId) + .url("http://dm-store/documents/" + documentId) + .removed(false) + .build(); + when(documentRepository.findById(documentId)).thenReturn(Optional.of(documentEntity)); + + underTest.removeDocument(documentId, reason); + + ArgumentCaptor captor = ArgumentCaptor.forClass(DocumentEntity.class); + verify(documentRepository).save(captor.capture()); + DocumentEntity saved = captor.getValue(); + + assertThat(saved.isRemoved()).isTrue(); + assertThat(saved.getRemovalReason()).isEqualTo(reason); + assertThat(saved.getRemovedAt()).isNotNull(); + assertThat(saved.getRemovedAt()).isBeforeOrEqualTo(LocalDateTime.now()); + } + + @Test + void shouldDeleteDocumentFromDocumentStoreUsingItsUrl() { + UUID documentId = UUID.randomUUID(); + String url = "http://dm-store/documents/" + documentId; + DocumentEntity documentEntity = DocumentEntity.builder() + .id(documentId) + .url(url) + .build(); + when(documentRepository.findById(documentId)).thenReturn(Optional.of(documentEntity)); + + underTest.removeDocument(documentId, "No longer relevant"); + + verify(documentImportService).deleteDocument(url); + } + + @Test + void shouldThrowWhenDocumentNotFound() { + UUID documentId = UUID.randomUUID(); + when(documentRepository.findById(documentId)).thenReturn(Optional.empty()); + + assertThatThrownBy(() -> underTest.removeDocument(documentId, "reason")) + .isInstanceOf(DocumentNotFoundException.class) + .hasMessageContaining(documentId.toString()); + + verifyNoInteractions(documentImportService); + verify(documentRepository, never()).save(any()); + } +} From 26e69afe9118d6026837043ae332216d2490761c Mon Sep 17 00:00:00 2001 From: srinijg Date: Fri, 17 Jul 2026 16:51:50 +0100 Subject: [PATCH 36/42] user update --- src/e2eTest/data/user-data/users.data.ts | 2 +- src/e2eTest/tests/caseTabs.spec.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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); From 2184ee0c3a70a7f98bf4eddd8eede2a3e7e482d5 Mon Sep 17 00:00:00 2001 From: Liban Abdirahman Date: Fri, 17 Jul 2026 18:09:24 +0100 Subject: [PATCH 37/42] HDPI-6454:Minor refactoring --- ...tsStates.java => ManageDocumentStates.java} | 6 +++--- .../DocumentSelectionDetails.java} | 5 ++--- .../documentamend/DocumentAmendDetails.java | 4 ++-- .../DocumentRemovalDetails.java | 4 ++-- .../hmcts/reform/pcs/ccd/event/EventId.java | 2 +- .../removedocument/RemoveDocument.java} | 14 +++++++------- .../DocumentRemovalCategoryField.java} | 6 +++--- .../SelectDocumentToRemovePage.java | 18 +++++++++--------- ...ld.java => DocumentAmendCategoryField.java} | 4 ++-- .../page/documentamend/SelectDocumentPage.java | 6 +++--- .../DocumentAmendSelectionService.java | 7 ++++--- .../removedocument/RemoveDocumentTest.java} | 8 ++++---- .../SelectDocumentToRemovePageTest.java | 2 +- 13 files changed, 43 insertions(+), 43 deletions(-) rename src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/{ManageDocumentsStates.java => ManageDocumentStates.java} (55%) rename src/main/java/uk/gov/hmcts/reform/pcs/ccd/{service/document/DocumentFolderSelection.java => domain/DocumentSelectionDetails.java} (72%) rename src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/{documentremoval/DocumentRemoval.java => caseworker/removedocument/RemoveDocument.java} (90%) rename src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/{documentremoval/DocumentCategoryField.java => caseworker/removedocument/DocumentRemovalCategoryField.java} (96%) rename src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/{documentremoval => caseworker/removedocument}/SelectDocumentToRemovePage.java (89%) rename src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/{DocumentCategoryField.java => DocumentAmendCategoryField.java} (96%) rename src/test/java/uk/gov/hmcts/reform/pcs/ccd/event/{documentremoval/DocumentRemovalTest.java => caseworker/removedocument/RemoveDocumentTest.java} (92%) rename src/test/java/uk/gov/hmcts/reform/pcs/ccd/page/{documentremoval => caseworker/removedocument}/SelectDocumentToRemovePageTest.java (98%) diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/ManageDocumentsStates.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/ManageDocumentStates.java similarity index 55% rename from src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/ManageDocumentsStates.java rename to src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/ManageDocumentStates.java index 93b6031ed6..fd809758f6 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/ManageDocumentsStates.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/ManageDocumentStates.java @@ -2,13 +2,13 @@ import uk.gov.hmcts.reform.pcs.ccd.domain.State; -public final class ManageDocumentsStates { +public final class ManageDocumentStates { - public static final State[] MANAGE_DOCUMENTS_STATES = { + public static final State[] MANAGE_DOCUMENT_STATES = { State.PENDING_CASE_ISSUED, State.CASE_ISSUED }; - private ManageDocumentsStates() { + private ManageDocumentStates() { } } \ No newline at end of file diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentFolderSelection.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/DocumentSelectionDetails.java similarity index 72% rename from src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentFolderSelection.java rename to src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/DocumentSelectionDetails.java index 568abcee78..975fdea54a 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentFolderSelection.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/DocumentSelectionDetails.java @@ -1,9 +1,8 @@ -package uk.gov.hmcts.reform.pcs.ccd.service.document; +package uk.gov.hmcts.reform.pcs.ccd.domain; import uk.gov.hmcts.ccd.sdk.type.YesOrNo; -import uk.gov.hmcts.reform.pcs.ccd.domain.CaseFileCategory; -public interface DocumentFolderSelection { +public interface DocumentSelectionDetails { CaseFileCategory getSelectedFolder(); 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 c647a5e837..cce2a10d95 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 @@ -12,7 +12,7 @@ import uk.gov.hmcts.ccd.sdk.api.CCD; import uk.gov.hmcts.reform.pcs.ccd.domain.CaseFileCategory; import uk.gov.hmcts.ccd.sdk.type.YesOrNo; -import uk.gov.hmcts.reform.pcs.ccd.service.document.DocumentFolderSelection; +import uk.gov.hmcts.reform.pcs.ccd.domain.DocumentSelectionDetails; import static uk.gov.hmcts.ccd.sdk.type.FieldType.FixedList; @@ -22,7 +22,7 @@ @AllArgsConstructor @JsonInclude(Include.NON_NULL) @JsonNaming(PropertyNamingStrategies.UpperCamelCaseStrategy.class) -public class DocumentAmendDetails implements DocumentFolderSelection { +public class DocumentAmendDetails implements DocumentSelectionDetails { @CCD( label = "Which folder is the document in?", diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentremoval/DocumentRemovalDetails.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentremoval/DocumentRemovalDetails.java index a88a679464..6d0c111286 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentremoval/DocumentRemovalDetails.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/domain/documentremoval/DocumentRemovalDetails.java @@ -12,7 +12,7 @@ import uk.gov.hmcts.ccd.sdk.api.CCD; import uk.gov.hmcts.ccd.sdk.type.YesOrNo; import uk.gov.hmcts.reform.pcs.ccd.domain.CaseFileCategory; -import uk.gov.hmcts.reform.pcs.ccd.service.document.DocumentFolderSelection; +import uk.gov.hmcts.reform.pcs.ccd.domain.DocumentSelectionDetails; import static uk.gov.hmcts.ccd.sdk.type.FieldType.FixedList; import static uk.gov.hmcts.ccd.sdk.type.FieldType.TextArea; @@ -23,7 +23,7 @@ @AllArgsConstructor @JsonInclude(Include.NON_NULL) @JsonNaming(PropertyNamingStrategies.UpperCamelCaseStrategy.class) -public class DocumentRemovalDetails implements DocumentFolderSelection { +public class DocumentRemovalDetails implements DocumentSelectionDetails { @CCD( label = "Which folder is the document in?", 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 7e3934717c..10018d7ace 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 @@ -20,5 +20,5 @@ public enum EventId { createFlags, amendFlags, claimIssuePayment, - removeDocuments + removeDocument } diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/documentremoval/DocumentRemoval.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/caseworker/removedocument/RemoveDocument.java similarity index 90% rename from src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/documentremoval/DocumentRemoval.java rename to src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/caseworker/removedocument/RemoveDocument.java index e906a88675..357964da6a 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/documentremoval/DocumentRemoval.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/caseworker/removedocument/RemoveDocument.java @@ -1,4 +1,4 @@ -package uk.gov.hmcts.reform.pcs.ccd.event.documentremoval; +package uk.gov.hmcts.reform.pcs.ccd.event.caseworker.removedocument; import lombok.AllArgsConstructor; import org.springframework.stereotype.Component; @@ -13,7 +13,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.documentremoval.DocumentRemovalDetails; -import uk.gov.hmcts.reform.pcs.ccd.page.documentremoval.SelectDocumentToRemovePage; +import uk.gov.hmcts.reform.pcs.ccd.page.caseworker.removedocument.SelectDocumentToRemovePage; import uk.gov.hmcts.reform.pcs.ccd.service.document.DocumentAmendSelectionService; import uk.gov.hmcts.reform.pcs.ccd.service.document.DocumentRemovalService; @@ -21,12 +21,12 @@ 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.accesscontrol.ManageDocumentsStates.MANAGE_DOCUMENTS_STATES; -import static uk.gov.hmcts.reform.pcs.ccd.event.EventId.removeDocuments; +import static uk.gov.hmcts.reform.pcs.ccd.accesscontrol.ManageDocumentStates.MANAGE_DOCUMENT_STATES; +import static uk.gov.hmcts.reform.pcs.ccd.event.EventId.removeDocument; @Component @AllArgsConstructor -public class DocumentRemoval implements CCDConfig { +public class RemoveDocument implements CCDConfig { private final DocumentAmendSelectionService documentSelectionService; private final DocumentRemovalService documentRemovalService; @@ -36,8 +36,8 @@ public class DocumentRemoval implements CCDConfig { public void configureDecentralised(DecentralisedConfigBuilder configBuilder) { Event.EventBuilder eventBuilder = configBuilder - .decentralisedEvent(removeDocuments.name(), this::submit, this::start) - .forStates(MANAGE_DOCUMENTS_STATES) + .decentralisedEvent(removeDocument.name(), this::submit, this::start) + .forStates(MANAGE_DOCUMENT_STATES) .name("Manage documents: Remove") .grant(Permission.CRU, CASEWORKER_ROLES) .grantHistoryOnly(JUDICIAL_HISTORY_ROLES) diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentremoval/DocumentCategoryField.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/caseworker/removedocument/DocumentRemovalCategoryField.java similarity index 96% rename from src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentremoval/DocumentCategoryField.java rename to src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/caseworker/removedocument/DocumentRemovalCategoryField.java index 7fed595ac4..8e99d70114 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentremoval/DocumentCategoryField.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/caseworker/removedocument/DocumentRemovalCategoryField.java @@ -1,4 +1,4 @@ -package uk.gov.hmcts.reform.pcs.ccd.page.documentremoval; +package uk.gov.hmcts.reform.pcs.ccd.page.caseworker.removedocument; import uk.gov.hmcts.ccd.sdk.api.TypedPropertyGetter; import uk.gov.hmcts.ccd.sdk.type.DynamicList; @@ -7,7 +7,7 @@ import uk.gov.hmcts.reform.pcs.ccd.domain.PCSCase; import uk.gov.hmcts.reform.pcs.ccd.domain.documentremoval.DocumentRemovalDetails; -enum DocumentCategoryField { +enum DocumentRemovalCategoryField { STATEMENTS_OF_CASE( CaseFileCategory.STATEMENTS_OF_CASE, "StatementsOfCaseDocuments", @@ -88,7 +88,7 @@ enum DocumentCategoryField { final TypedPropertyGetter emptyGetter; final TypedPropertyGetter reasonGetter; - DocumentCategoryField(CaseFileCategory category, + DocumentRemovalCategoryField(CaseFileCategory category, String documentsFieldId, String emptyFieldId, TypedPropertyGetter documentsGetter, diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentremoval/SelectDocumentToRemovePage.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/caseworker/removedocument/SelectDocumentToRemovePage.java similarity index 89% rename from src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentremoval/SelectDocumentToRemovePage.java rename to src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/caseworker/removedocument/SelectDocumentToRemovePage.java index 0bf04566c4..26d904e19a 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentremoval/SelectDocumentToRemovePage.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/caseworker/removedocument/SelectDocumentToRemovePage.java @@ -1,4 +1,4 @@ -package uk.gov.hmcts.reform.pcs.ccd.page.documentremoval; +package uk.gov.hmcts.reform.pcs.ccd.page.caseworker.removedocument; import lombok.AllArgsConstructor; import org.springframework.stereotype.Component; @@ -50,18 +50,18 @@ public void addTo(PageBuilder pageBuilder) { .label("emptyFolderDocumentQuestion", "", NEVER_SHOW) .done(); - for (DocumentCategoryField categoryField : DocumentCategoryField.values()) { + for (DocumentRemovalCategoryField categoryField : DocumentRemovalCategoryField.values()) { addCategoryFields(page, categoryField); } FieldCollectionBuilder documentRemovalDetailsFields = page.complex(PCSCase::getDocumentRemovalDetails); - for (DocumentCategoryField categoryField : DocumentCategoryField.values()) { + for (DocumentRemovalCategoryField categoryField : DocumentRemovalCategoryField.values()) { documentRemovalDetailsFields.readonly(categoryField.emptyGetter, NEVER_SHOW, true); } - for (DocumentCategoryField categoryField : DocumentCategoryField.values()) { + for (DocumentRemovalCategoryField categoryField : DocumentRemovalCategoryField.values()) { documentRemovalDetailsFields.mandatoryWithoutDefaultValue(categoryField.reasonGetter, reasonShowCondition(categoryField), REASON_LABEL, false); } @@ -75,7 +75,7 @@ public void addTo(PageBuilder pageBuilder) { } private void addCategoryFields(FieldCollectionBuilder page, - DocumentCategoryField categoryField) { + DocumentRemovalCategoryField categoryField) { page .label(categoryField.documentsFieldId + "EmptyFolderMessage", emptyFolderMessage(categoryField.category), noDocumentsShowCondition(categoryField)) @@ -109,17 +109,17 @@ private AboutToStartOrSubmitResponse midEvent(CaseDetails reasonGetter(CaseFileCategory category) { - for (DocumentCategoryField categoryField : DocumentCategoryField.values()) { + for (DocumentRemovalCategoryField categoryField : DocumentRemovalCategoryField.values()) { if (categoryField.category == category) { return categoryField.reasonGetter; } 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/DocumentAmendCategoryField.java similarity index 96% rename from src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/DocumentCategoryField.java rename to src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/documentamend/DocumentAmendCategoryField.java index 7f34b113bf..0ce646d605 100644 --- 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/DocumentAmendCategoryField.java @@ -7,7 +7,7 @@ import uk.gov.hmcts.reform.pcs.ccd.domain.PCSCase; import uk.gov.hmcts.reform.pcs.ccd.domain.documentamend.DocumentAmendDetails; -enum DocumentCategoryField { +enum DocumentAmendCategoryField { STATEMENTS_OF_CASE( CaseFileCategory.STATEMENTS_OF_CASE, "statementsOfCase", @@ -68,7 +68,7 @@ enum DocumentCategoryField { final TypedPropertyGetter documentsGetter; final TypedPropertyGetter emptyGetter; - DocumentCategoryField(CaseFileCategory category, + DocumentAmendCategoryField(CaseFileCategory category, String idPrefix, TypedPropertyGetter documentsGetter, TypedPropertyGetter 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 8c474427c5..6be0526222 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,14 +43,14 @@ public void addTo(PageBuilder pageBuilder) { .label("emptyFolderDocumentQuestion", "", NEVER_SHOW) .done(); - for (DocumentCategoryField categoryField : DocumentCategoryField.values()) { + for (DocumentAmendCategoryField categoryField : DocumentAmendCategoryField.values()) { addCategoryFields(page, categoryField); } FieldCollectionBuilder documentAmendDetailsFields = page.complex(PCSCase::getDocumentAmendDetails); - for (DocumentCategoryField categoryField : DocumentCategoryField.values()) { + for (DocumentAmendCategoryField categoryField : DocumentAmendCategoryField.values()) { documentAmendDetailsFields.readonly(categoryField.emptyGetter, NEVER_SHOW, true); } @@ -63,7 +63,7 @@ public void addTo(PageBuilder pageBuilder) { } private void addCategoryFields(FieldCollectionBuilder page, - DocumentCategoryField categoryField) { + DocumentAmendCategoryField categoryField) { CaseFileCategory category = categoryField.category; page .label(categoryField.idPrefix + "EmptyFolderMessage", emptyFolderMessage(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 2dbc395dc6..b73d8aa2b1 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.DocumentSelectionDetails; 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.entity.DocumentEntity; @@ -35,7 +36,7 @@ public DocumentAmendSelectionService(PcsCaseService pcsCaseService, AddressForma this.addressFormatter = addressFormatter; } - public void initialise(long caseReference, PCSCase caseData, DocumentFolderSelection details) { + public void initialise(long caseReference, PCSCase caseData, DocumentSelectionDetails details) { PcsCaseEntity pcsCase = pcsCaseService.loadCase(caseReference); details.setPropertyAddressSummary( addressFormatter.formatShortAddress(caseData.getPropertyAddress(), COMMA_DELIMITER)); @@ -45,7 +46,7 @@ public void initialise(long caseReference, PCSCase caseData, DocumentFolderSelec } } - public List validateAndStoreSelection(PCSCase caseData, DocumentFolderSelection details) { + public List validateAndStoreSelection(PCSCase caseData, DocumentSelectionDetails details) { if (details == null || details.getSelectedFolder() == null) { return List.of(); } @@ -73,7 +74,7 @@ public List validateAndStoreSelection(PCSCase caseData, DocumentFolderSe return List.of(); } - private void setDocumentsForCategory(DocumentFolderSelection details, PCSCase caseData, PcsCaseEntity pcsCase, + private void setDocumentsForCategory(DocumentSelectionDetails details, PCSCase caseData, PcsCaseEntity pcsCase, CaseFileCategory category) { DynamicList documents = documentList(pcsCase, category, documentsForCategory(caseData, category)); applyDocumentsForCategory(caseData, category, documents); diff --git a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/event/documentremoval/DocumentRemovalTest.java b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/event/caseworker/removedocument/RemoveDocumentTest.java similarity index 92% rename from src/test/java/uk/gov/hmcts/reform/pcs/ccd/event/documentremoval/DocumentRemovalTest.java rename to src/test/java/uk/gov/hmcts/reform/pcs/ccd/event/caseworker/removedocument/RemoveDocumentTest.java index 6ba04bacfc..2e8e1b3dcd 100644 --- a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/event/documentremoval/DocumentRemovalTest.java +++ b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/event/caseworker/removedocument/RemoveDocumentTest.java @@ -1,4 +1,4 @@ -package uk.gov.hmcts.reform.pcs.ccd.event.documentremoval; +package uk.gov.hmcts.reform.pcs.ccd.event.caseworker.removedocument; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -11,7 +11,7 @@ import uk.gov.hmcts.reform.pcs.ccd.domain.State; import uk.gov.hmcts.reform.pcs.ccd.domain.documentremoval.DocumentRemovalDetails; import uk.gov.hmcts.reform.pcs.ccd.event.BaseEventTest; -import uk.gov.hmcts.reform.pcs.ccd.page.documentremoval.SelectDocumentToRemovePage; +import uk.gov.hmcts.reform.pcs.ccd.page.caseworker.removedocument.SelectDocumentToRemovePage; import uk.gov.hmcts.reform.pcs.ccd.service.document.DocumentAmendSelectionService; import uk.gov.hmcts.reform.pcs.ccd.service.document.DocumentRemovalService; @@ -22,7 +22,7 @@ import static org.mockito.Mockito.verify; @ExtendWith(MockitoExtension.class) -class DocumentRemovalTest extends BaseEventTest { +class RemoveDocumentTest extends BaseEventTest { @Mock private DocumentAmendSelectionService documentSelectionService; @@ -33,7 +33,7 @@ class DocumentRemovalTest extends BaseEventTest { @BeforeEach void setUp() { - DocumentRemoval underTest = new DocumentRemoval( + RemoveDocument underTest = new RemoveDocument( documentSelectionService, documentRemovalService, selectDocumentToRemovePage ); diff --git a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/page/documentremoval/SelectDocumentToRemovePageTest.java b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/page/caseworker/removedocument/SelectDocumentToRemovePageTest.java similarity index 98% rename from src/test/java/uk/gov/hmcts/reform/pcs/ccd/page/documentremoval/SelectDocumentToRemovePageTest.java rename to src/test/java/uk/gov/hmcts/reform/pcs/ccd/page/caseworker/removedocument/SelectDocumentToRemovePageTest.java index 4422ec16c9..e9bd21d05a 100644 --- a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/page/documentremoval/SelectDocumentToRemovePageTest.java +++ b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/page/caseworker/removedocument/SelectDocumentToRemovePageTest.java @@ -1,4 +1,4 @@ -package uk.gov.hmcts.reform.pcs.ccd.page.documentremoval; +package uk.gov.hmcts.reform.pcs.ccd.page.caseworker.removedocument; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; From a29811236cd1b538bc4c6a31615542b725c907f6 Mon Sep 17 00:00:00 2001 From: Liban Abdirahman Date: Mon, 20 Jul 2026 09:28:25 +0100 Subject: [PATCH 38/42] HDPI-6454:Removing dead code --- .../removedocument/SelectDocumentToRemovePage.java | 12 ------------ .../ccd/service/document/DocumentRemovalService.java | 4 ++-- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/caseworker/removedocument/SelectDocumentToRemovePage.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/caseworker/removedocument/SelectDocumentToRemovePage.java index 26d904e19a..eecb4d794d 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/caseworker/removedocument/SelectDocumentToRemovePage.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/caseworker/removedocument/SelectDocumentToRemovePage.java @@ -4,7 +4,6 @@ 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.reform.pcs.ccd.common.CcdPageConfiguration; import uk.gov.hmcts.reform.pcs.ccd.common.PageBuilder; @@ -67,8 +66,6 @@ public void addTo(PageBuilder pageBuilder) { } documentRemovalDetailsFields - .readonly(DocumentRemovalDetails::getSelectedFolderId, NEVER_SHOW, true) - .readonly(DocumentRemovalDetails::getSelectedFolderLabel, NEVER_SHOW, true) .readonly(DocumentRemovalDetails::getSelectedDocumentId, NEVER_SHOW, true) .readonly(DocumentRemovalDetails::getSelectedDocumentFileName, NEVER_SHOW, true) .done(); @@ -142,15 +139,6 @@ private String selectedFolderCondition(CaseFileCategory category) { return FIELD_PREFIX + "SelectedFolder=\"" + category.name() + "\""; } - private TypedPropertyGetter reasonGetter(CaseFileCategory category) { - for (DocumentRemovalCategoryField categoryField : DocumentRemovalCategoryField.values()) { - if (categoryField.category == category) { - return categoryField.reasonGetter; - } - } - throw new IllegalStateException("No reason field configured for category " + category); - } - private String emptyFolderMessage(CaseFileCategory category) { return DOCUMENT_QUESTION_LABEL + "
" diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentRemovalService.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentRemovalService.java index 604ceb57f1..77adcf3b9a 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentRemovalService.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentRemovalService.java @@ -24,11 +24,11 @@ public void removeDocument(UUID documentEntityId, String reason) { DocumentEntity documentEntity = documentRepository.findById(documentEntityId) .orElseThrow(() -> new DocumentNotFoundException(documentEntityId)); - documentImportService.deleteDocument(documentEntity.getUrl()); - documentEntity.setRemoved(true); documentEntity.setRemovalReason(reason); documentEntity.setRemovedAt(LocalDateTime.now()); documentRepository.save(documentEntity); + + documentImportService.deleteDocument(documentEntity.getUrl()); } } From 1d482ecb0fa598ce5d22734548a4bb43ba75edda Mon Sep 17 00:00:00 2001 From: Liban Abdirahman Date: Mon, 20 Jul 2026 10:12:29 +0100 Subject: [PATCH 39/42] HDPI-6454:Fixing sonar issue with exclusion --- build.gradle | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 9624475872..54d3829414 100644 --- a/build.gradle +++ b/build.gradle @@ -338,7 +338,9 @@ sonarqube { "**/model/**," + "**/uk/gov/hmcts/reform/pcs/testingsupport/**/*.java" property "sonar.cpd.exclusions", "**/uk/gov/hmcts/reform/pcs/ccd/domain/enforcetheorder/warrant/StatementOfTruthDetails.java," + - "**/uk/gov/hmcts/reform/pcs/ccd/domain/genapp/*.java," + "**/uk/gov/hmcts/reform/pcs/ccd/domain/genapp/*.java," + + "**/uk/gov/hmcts/reform/pcs/ccd/domain/documentamend/DocumentAmendDetails.java," + + "**/uk/gov/hmcts/reform/pcs/ccd/domain/documentremoval/DocumentRemovalDetails.java," } } From 49a15ed9633cd3a79e45dd9e5b0656c237a1984c Mon Sep 17 00:00:00 2001 From: Liban Abdirahman Date: Mon, 20 Jul 2026 14:22:53 +0100 Subject: [PATCH 40/42] HDPI-6454:Adding feature flag to event & updating confirmation page --- .../caseworker/removedocument/RemoveDocument.java | 15 +++++++++++---- .../removedocument/RemoveDocumentTest.java | 4 +++- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/caseworker/removedocument/RemoveDocument.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/caseworker/removedocument/RemoveDocument.java index 357964da6a..d3e38b96ee 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/caseworker/removedocument/RemoveDocument.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/caseworker/removedocument/RemoveDocument.java @@ -8,6 +8,7 @@ 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.ShowConditions; 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; @@ -23,6 +24,8 @@ import static uk.gov.hmcts.reform.pcs.ccd.accesscontrol.JudicialHistoryRoles.JUDICIAL_HISTORY_ROLES; import static uk.gov.hmcts.reform.pcs.ccd.accesscontrol.ManageDocumentStates.MANAGE_DOCUMENT_STATES; import static uk.gov.hmcts.reform.pcs.ccd.event.EventId.removeDocument; +import static uk.gov.hmcts.reform.pcs.service.FeatureFlag.CASEWORKER_EVENTS; +import static uk.gov.hmcts.reform.pcs.service.FeatureFlag.RELEASE_1_DOT_2; @Component @AllArgsConstructor @@ -39,6 +42,7 @@ public void configureDecentralised(DecentralisedConfigBuilder eventPayload) { } private SubmitResponse submit(EventPayload eventPayload) { + PCSCase caseData = eventPayload.caseData(); DocumentRemovalDetails details = eventPayload.caseData().getDocumentRemovalDetails(); + String caseName = caseData.getCaseNameHmctsInternal(); String reason = details.getReasonForCategory(details.getSelectedFolder()); documentRemovalService.removeDocument(UUID.fromString(details.getSelectedDocumentId()), reason); return SubmitResponse.builder() - .confirmationBody(buildConfirmationMarkdown(details, eventPayload.caseReference())) + .confirmationBody(buildConfirmationMarkdown(details, eventPayload.caseReference(),caseName)) .build(); } - private String buildConfirmationMarkdown(DocumentRemovalDetails details, long caseReference) { + private String buildConfirmationMarkdown(DocumentRemovalDetails details, long caseReference, String caseName) { return """ ---
%s removed
Case number: %s
Property address: %s + %s

What happens next

The document will no longer appear in case file view

- """.formatted( - details.getSelectedDocumentFileName(), caseReference, details.getPropertyAddressSummary()); + """.formatted(details.getSelectedDocumentFileName(), caseReference, + details.getPropertyAddressSummary(),caseName); } } diff --git a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/event/caseworker/removedocument/RemoveDocumentTest.java b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/event/caseworker/removedocument/RemoveDocumentTest.java index 2e8e1b3dcd..b7af8e3cbb 100644 --- a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/event/caseworker/removedocument/RemoveDocumentTest.java +++ b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/event/caseworker/removedocument/RemoveDocumentTest.java @@ -79,6 +79,7 @@ void shouldBuildConfirmationPageWithRemovedDocumentDetails() { .build(); PCSCase caseData = PCSCase.builder() .documentRemovalDetails(details) + .caseNameHmctsInternal("Smith v Jones") .build(); SubmitResponse response = callSubmitHandler(caseData); @@ -87,6 +88,7 @@ void shouldBuildConfirmationPageWithRemovedDocumentDetails() { assertThat(response.getConfirmationBody()) .contains("evidence.pdf") .contains("Case number: " + TEST_CASE_REFERENCE) - .contains("123 Test Street, Testville, TE1 1ST"); + .contains("123 Test Street, Testville, TE1 1ST") + .contains("Smith v Jones"); } } From 259f46e759a6e5a23b764e5c319c08d50d820c9d Mon Sep 17 00:00:00 2001 From: Liban Abdirahman Date: Tue, 21 Jul 2026 15:11:00 +0100 Subject: [PATCH 41/42] HDPI-6454:Renaming service & adding new allowed states to remove document event --- .../pcs/ccd/accesscontrol/ManageDocumentStates.java | 10 +++++++++- .../gov/hmcts/reform/pcs/ccd/event/AmendDocuments.java | 4 ++-- .../caseworker/removedocument/RemoveDocument.java | 4 ++-- .../removedocument/SelectDocumentToRemovePage.java | 4 ++-- .../pcs/ccd/page/documentamend/SelectDocumentPage.java | 4 ++-- ...ctionService.java => DocumentSelectionService.java} | 4 ++-- .../caseworker/removedocument/RemoveDocumentTest.java | 4 ++-- .../removedocument/SelectDocumentToRemovePageTest.java | 4 ++-- ...viceTest.java => DocumentSelectionServiceTest.java} | 6 +++--- 9 files changed, 26 insertions(+), 18 deletions(-) rename src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/{DocumentAmendSelectionService.java => DocumentSelectionService.java} (97%) rename src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/{DocumentAmendSelectionServiceTest.java => DocumentSelectionServiceTest.java} (98%) diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/ManageDocumentStates.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/ManageDocumentStates.java index fd809758f6..55a77ea180 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/ManageDocumentStates.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/accesscontrol/ManageDocumentStates.java @@ -6,7 +6,15 @@ public final class ManageDocumentStates { public static final State[] MANAGE_DOCUMENT_STATES = { State.PENDING_CASE_ISSUED, - State.CASE_ISSUED + State.CASE_ISSUED, + State.CASE_PROGRESSION, + State.CASE_STAYED, + State.BREATHING_SPACE, + State.JUDICIAL_REFERRAL, + State.HEARING_READINESS, + State.PREPARE_FOR_HEARING_CONDUCT_HEARING, + State.DECISION_OUTCOME, + State.ALL_FINAL_ORDERS_ISSUED }; private ManageDocumentStates() { 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 e184bf97e8..dc09d27fb7 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 @@ -16,7 +16,7 @@ import uk.gov.hmcts.reform.pcs.ccd.domain.documentamend.DocumentAmendDetails; 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 uk.gov.hmcts.reform.pcs.ccd.service.document.DocumentSelectionService; import static uk.gov.hmcts.reform.pcs.ccd.accesscontrol.CaseworkerRoles.CASEWORKER_ROLES; import static uk.gov.hmcts.reform.pcs.ccd.event.EventId.amendDocuments; @@ -27,7 +27,7 @@ @AllArgsConstructor public class AmendDocuments implements CCDConfig { - private final DocumentAmendSelectionService documentSelectionService; + private final DocumentSelectionService documentSelectionService; private final SelectDocumentPage selectDocumentPage; private final AmendDocumentDetailsPlaceholderPage amendDocumentDetailsPlaceholderPage; diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/caseworker/removedocument/RemoveDocument.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/caseworker/removedocument/RemoveDocument.java index d3e38b96ee..9bca4aed88 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/caseworker/removedocument/RemoveDocument.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/caseworker/removedocument/RemoveDocument.java @@ -15,8 +15,8 @@ import uk.gov.hmcts.reform.pcs.ccd.domain.State; import uk.gov.hmcts.reform.pcs.ccd.domain.documentremoval.DocumentRemovalDetails; import uk.gov.hmcts.reform.pcs.ccd.page.caseworker.removedocument.SelectDocumentToRemovePage; -import uk.gov.hmcts.reform.pcs.ccd.service.document.DocumentAmendSelectionService; import uk.gov.hmcts.reform.pcs.ccd.service.document.DocumentRemovalService; +import uk.gov.hmcts.reform.pcs.ccd.service.document.DocumentSelectionService; import java.util.UUID; @@ -31,7 +31,7 @@ @AllArgsConstructor public class RemoveDocument implements CCDConfig { - private final DocumentAmendSelectionService documentSelectionService; + private final DocumentSelectionService documentSelectionService; private final DocumentRemovalService documentRemovalService; private final SelectDocumentToRemovePage selectDocumentToRemovePage; diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/caseworker/removedocument/SelectDocumentToRemovePage.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/caseworker/removedocument/SelectDocumentToRemovePage.java index eecb4d794d..934810006d 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/caseworker/removedocument/SelectDocumentToRemovePage.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/caseworker/removedocument/SelectDocumentToRemovePage.java @@ -12,7 +12,7 @@ import uk.gov.hmcts.reform.pcs.ccd.domain.State; import uk.gov.hmcts.reform.pcs.ccd.domain.documentremoval.DocumentRemovalDetails; import uk.gov.hmcts.reform.pcs.ccd.service.TextAreaValidationService; -import uk.gov.hmcts.reform.pcs.ccd.service.document.DocumentAmendSelectionService; +import uk.gov.hmcts.reform.pcs.ccd.service.document.DocumentSelectionService; import uk.gov.hmcts.reform.pcs.ccd.util.StringUtils; import java.util.ArrayList; @@ -31,7 +31,7 @@ public class SelectDocumentToRemovePage implements CcdPageConfiguration { private static final String DOCUMENT_QUESTION_LABEL = "Which document do you want to remove?"; private static final String REASON_LABEL = "Why are you removing this document?"; - private final DocumentAmendSelectionService documentSelectionService; + private final DocumentSelectionService documentSelectionService; private final TextAreaValidationService textAreaValidationService; @Override 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 6be0526222..4612f33f99 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,7 +11,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.service.document.DocumentAmendSelectionService; +import uk.gov.hmcts.reform.pcs.ccd.service.document.DocumentSelectionService; import uk.gov.hmcts.reform.pcs.ccd.util.StringUtils; import java.util.List; @@ -27,7 +27,7 @@ public class SelectDocumentPage implements CcdPageConfiguration { private static final String DOCUMENT_QUESTION_LABEL = "Which document do you want to amend?"; private static final String YES = "=\"Yes\""; private static final String NO = "=\"No\""; - private final DocumentAmendSelectionService documentSelectionService; + private final DocumentSelectionService documentSelectionService; @Override public void addTo(PageBuilder pageBuilder) { 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/DocumentSelectionService.java similarity index 97% rename from src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionService.java rename to src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentSelectionService.java index b73d8aa2b1..566cdd9822 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/DocumentSelectionService.java @@ -21,7 +21,7 @@ import static uk.gov.hmcts.reform.pcs.ccd.util.AddressFormatter.COMMA_DELIMITER; @Service -public class DocumentAmendSelectionService { +public class DocumentSelectionService { public static final String SELECT_DIFFERENT_FOLDER_ERROR = "Select a different folder to continue"; private static final Comparator DOCUMENT_ORDER = Comparator @@ -31,7 +31,7 @@ public class DocumentAmendSelectionService { private final PcsCaseService pcsCaseService; private final AddressFormatter addressFormatter; - public DocumentAmendSelectionService(PcsCaseService pcsCaseService, AddressFormatter addressFormatter) { + public DocumentSelectionService(PcsCaseService pcsCaseService, AddressFormatter addressFormatter) { this.pcsCaseService = pcsCaseService; this.addressFormatter = addressFormatter; } diff --git a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/event/caseworker/removedocument/RemoveDocumentTest.java b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/event/caseworker/removedocument/RemoveDocumentTest.java index b7af8e3cbb..9354d8c167 100644 --- a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/event/caseworker/removedocument/RemoveDocumentTest.java +++ b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/event/caseworker/removedocument/RemoveDocumentTest.java @@ -12,8 +12,8 @@ import uk.gov.hmcts.reform.pcs.ccd.domain.documentremoval.DocumentRemovalDetails; import uk.gov.hmcts.reform.pcs.ccd.event.BaseEventTest; import uk.gov.hmcts.reform.pcs.ccd.page.caseworker.removedocument.SelectDocumentToRemovePage; -import uk.gov.hmcts.reform.pcs.ccd.service.document.DocumentAmendSelectionService; import uk.gov.hmcts.reform.pcs.ccd.service.document.DocumentRemovalService; +import uk.gov.hmcts.reform.pcs.ccd.service.document.DocumentSelectionService; import java.util.UUID; @@ -25,7 +25,7 @@ class RemoveDocumentTest extends BaseEventTest { @Mock - private DocumentAmendSelectionService documentSelectionService; + private DocumentSelectionService documentSelectionService; @Mock private DocumentRemovalService documentRemovalService; @Mock diff --git a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/page/caseworker/removedocument/SelectDocumentToRemovePageTest.java b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/page/caseworker/removedocument/SelectDocumentToRemovePageTest.java index e9bd21d05a..86b9585e7f 100644 --- a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/page/caseworker/removedocument/SelectDocumentToRemovePageTest.java +++ b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/page/caseworker/removedocument/SelectDocumentToRemovePageTest.java @@ -12,7 +12,7 @@ import uk.gov.hmcts.reform.pcs.ccd.domain.documentremoval.DocumentRemovalDetails; import uk.gov.hmcts.reform.pcs.ccd.page.BasePageTest; import uk.gov.hmcts.reform.pcs.ccd.service.TextAreaValidationService; -import uk.gov.hmcts.reform.pcs.ccd.service.document.DocumentAmendSelectionService; +import uk.gov.hmcts.reform.pcs.ccd.service.document.DocumentSelectionService; import java.util.List; @@ -26,7 +26,7 @@ class SelectDocumentToRemovePageTest extends BasePageTest { @Mock - private DocumentAmendSelectionService documentSelectionService; + private DocumentSelectionService documentSelectionService; @BeforeEach void setUp() { 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/DocumentSelectionServiceTest.java similarity index 98% rename from src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentAmendSelectionServiceTest.java rename to src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/document/DocumentSelectionServiceTest.java index 3b6607c623..2229226aa5 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/DocumentSelectionServiceTest.java @@ -33,18 +33,18 @@ import static uk.gov.hmcts.reform.pcs.ccd.domain.CaseFileCategory.UNCATEGORISED_DOCUMENTS; @ExtendWith(MockitoExtension.class) -class DocumentAmendSelectionServiceTest { +class DocumentSelectionServiceTest { private static final long CASE_REFERENCE = 1234567890123456L; @Mock private PcsCaseService pcsCaseService; - private DocumentAmendSelectionService underTest; + private DocumentSelectionService underTest; @BeforeEach void setUp() { - underTest = new DocumentAmendSelectionService(pcsCaseService, new AddressFormatter()); + underTest = new DocumentSelectionService(pcsCaseService, new AddressFormatter()); } @Test From 535a4dee76ed736566b771027aea02811fec06dd Mon Sep 17 00:00:00 2001 From: Liban Abdirahman Date: Wed, 22 Jul 2026 09:35:43 +0100 Subject: [PATCH 42/42] HDPI-6454:Updating migration script number post update with master --- ...removal_columns.sql => V002__add_document_removal_columns.sql} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/main/resources/db/migration/{V136__add_document_removal_columns.sql => V002__add_document_removal_columns.sql} (100%) diff --git a/src/main/resources/db/migration/V136__add_document_removal_columns.sql b/src/main/resources/db/migration/V002__add_document_removal_columns.sql similarity index 100% rename from src/main/resources/db/migration/V136__add_document_removal_columns.sql rename to src/main/resources/db/migration/V002__add_document_removal_columns.sql