From 8811cfb38abd10651af211d3aaa5928550a7875d Mon Sep 17 00:00:00 2001 From: jamesrferguson1 <94848497+jamesrferguson1@users.noreply.github.com> Date: Thu, 9 Jan 2025 14:59:35 +0000 Subject: [PATCH] DFPL-2631 Adds ability to remove refused orders through the removal tool (#5786) * Adds ability to remove refused orders through the removal tool * Fix to handle case where the refusedHearingOrders collection is null. * Add test for refused orders action to OrderRemovalActionsTest * Fix failing order action test. * Fix failing order action test. --------- Co-authored-by: Braimah101 <41795070+Braimah101@users.noreply.github.com> --- .../removeorder/DraftCMORemovalAction.java | 3 +- .../removeorder/OrderRemovalActions.java | 4 +- .../RefusedHearingOrderRemovalAction.java | 60 +++++++++ .../removeorder/RemoveOrderService.java | 1 + .../DraftCMORemovalActionTest.java | 8 ++ .../removeorder/OrderRemovalActionsTest.java | 13 ++ .../RefusedHearingOrderRemovalActionTest.java | 117 ++++++++++++++++++ 7 files changed, 204 insertions(+), 2 deletions(-) create mode 100644 service/src/main/java/uk/gov/hmcts/reform/fpl/service/removeorder/RefusedHearingOrderRemovalAction.java create mode 100644 service/src/test/java/uk/gov/hmcts/reform/fpl/service/removeorder/RefusedHearingOrderRemovalActionTest.java diff --git a/service/src/main/java/uk/gov/hmcts/reform/fpl/service/removeorder/DraftCMORemovalAction.java b/service/src/main/java/uk/gov/hmcts/reform/fpl/service/removeorder/DraftCMORemovalAction.java index 2e00136409e..8681810f400 100644 --- a/service/src/main/java/uk/gov/hmcts/reform/fpl/service/removeorder/DraftCMORemovalAction.java +++ b/service/src/main/java/uk/gov/hmcts/reform/fpl/service/removeorder/DraftCMORemovalAction.java @@ -3,6 +3,7 @@ import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import uk.gov.hmcts.reform.fpl.enums.CMOStatus; import uk.gov.hmcts.reform.fpl.enums.HearingOrderType; import uk.gov.hmcts.reform.fpl.exceptions.CMONotFoundException; import uk.gov.hmcts.reform.fpl.model.CaseData; @@ -38,7 +39,7 @@ public class DraftCMORemovalAction implements OrderRemovalAction { @Override public boolean isAccepted(RemovableOrder removableOrder) { return removableOrder instanceof HearingOrder && Optional.of((HearingOrder) removableOrder) - .filter(order -> order.getType() != HearingOrderType.C21) + .filter(order -> order.getType() != HearingOrderType.C21 && order.getStatus() != CMOStatus.RETURNED) .isPresent(); } diff --git a/service/src/main/java/uk/gov/hmcts/reform/fpl/service/removeorder/OrderRemovalActions.java b/service/src/main/java/uk/gov/hmcts/reform/fpl/service/removeorder/OrderRemovalActions.java index 9319efa0b36..c7510de6ad6 100644 --- a/service/src/main/java/uk/gov/hmcts/reform/fpl/service/removeorder/OrderRemovalActions.java +++ b/service/src/main/java/uk/gov/hmcts/reform/fpl/service/removeorder/OrderRemovalActions.java @@ -16,6 +16,7 @@ public class OrderRemovalActions { private final GeneratedOrderRemovalAction generatedOrderRemovalAction; private final SDORemovalAction sdoRemovalAction; private final DraftCMORemovalAction draftCMORemovalAction; + private final RefusedHearingOrderRemovalAction refusedDraftOrderRemovalAction; public OrderRemovalAction getAction(RemovableOrder removableOrder) { return getActions() @@ -31,7 +32,8 @@ private Stream getActions() { generatedOrderRemovalAction, sdoRemovalAction, draftOrderRemovalAction, - draftCMORemovalAction + draftCMORemovalAction, + refusedDraftOrderRemovalAction ); } } diff --git a/service/src/main/java/uk/gov/hmcts/reform/fpl/service/removeorder/RefusedHearingOrderRemovalAction.java b/service/src/main/java/uk/gov/hmcts/reform/fpl/service/removeorder/RefusedHearingOrderRemovalAction.java new file mode 100644 index 00000000000..b0a196b99f6 --- /dev/null +++ b/service/src/main/java/uk/gov/hmcts/reform/fpl/service/removeorder/RefusedHearingOrderRemovalAction.java @@ -0,0 +1,60 @@ +package uk.gov.hmcts.reform.fpl.service.removeorder; + +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import uk.gov.hmcts.reform.fpl.model.CaseData; +import uk.gov.hmcts.reform.fpl.model.common.Element; +import uk.gov.hmcts.reform.fpl.model.interfaces.RemovableOrder; +import uk.gov.hmcts.reform.fpl.model.order.HearingOrder; +import uk.gov.hmcts.reform.fpl.utils.CaseDetailsMap; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +import static org.apache.commons.lang3.StringUtils.EMPTY; +import static uk.gov.hmcts.reform.fpl.enums.CMOStatus.RETURNED; +import static uk.gov.hmcts.reform.fpl.enums.YesNo.NO; + +@Component +@RequiredArgsConstructor(onConstructor_ = {@Autowired}) +public class RefusedHearingOrderRemovalAction implements OrderRemovalAction { + + @Override + public boolean isAccepted(RemovableOrder removableOrder) { + return removableOrder instanceof HearingOrder && Optional.of((HearingOrder) removableOrder) + .filter(this::isRemovableOrder) + .isPresent(); + } + + @Override + public void populateCaseFields(CaseData caseData, CaseDetailsMap data, UUID removedOrderId, + RemovableOrder removableOrder) { + HearingOrder draftOrder = (HearingOrder) removableOrder; + + data.put("orderToBeRemoved", draftOrder.getOrder()); + data.put("orderTitleToBeRemoved", draftOrder.getTitle()); + data.put("showRemoveCMOFieldsFlag", EMPTY); + data.put("showReasonFieldFlag", NO.getValue()); + } + + @Override + public void remove(CaseData caseData, CaseDetailsMap data, UUID removedOrderId, RemovableOrder removableOrder) { + HearingOrder draftOrder = (HearingOrder) removableOrder; + + Element refusedHearingOrderElement = caseData.getRefusedHearingOrders() + .stream() + .filter(element -> element.getId().equals(removedOrderId)) + .findFirst() + .orElseThrow(() -> new IllegalStateException("Failed to find refused hearing order")); + + List> refusedHearingOrders = caseData.getRefusedHearingOrders(); + refusedHearingOrders.removeIf(element -> element.getId().equals(refusedHearingOrderElement.getId())); + data.putIfNotEmpty("refusedHearingOrders", refusedHearingOrders); + } + + private boolean isRemovableOrder(HearingOrder hearingOrder) { + return RETURNED == hearingOrder.getStatus(); + } +} diff --git a/service/src/main/java/uk/gov/hmcts/reform/fpl/service/removeorder/RemoveOrderService.java b/service/src/main/java/uk/gov/hmcts/reform/fpl/service/removeorder/RemoveOrderService.java index cc0700fd772..6d55dcf4136 100644 --- a/service/src/main/java/uk/gov/hmcts/reform/fpl/service/removeorder/RemoveOrderService.java +++ b/service/src/main/java/uk/gov/hmcts/reform/fpl/service/removeorder/RemoveOrderService.java @@ -98,6 +98,7 @@ private List> getRemovableOrderList(CaseData c orders.addAll(caseData.getOrderCollection()); orders.addAll(caseData.getSealedCMOs()); orders.addAll(getDraftHearingOrders(caseData)); + orders.addAll(Optional.ofNullable(caseData.getRefusedHearingOrders()).orElse(new ArrayList<>())); if (!FINAL_HEARING.equals(caseData.getState())) { if (caseData.getStandardDirectionOrder() != null) { diff --git a/service/src/test/java/uk/gov/hmcts/reform/fpl/service/removeorder/DraftCMORemovalActionTest.java b/service/src/test/java/uk/gov/hmcts/reform/fpl/service/removeorder/DraftCMORemovalActionTest.java index fc997701a23..229edcbe1df 100644 --- a/service/src/test/java/uk/gov/hmcts/reform/fpl/service/removeorder/DraftCMORemovalActionTest.java +++ b/service/src/test/java/uk/gov/hmcts/reform/fpl/service/removeorder/DraftCMORemovalActionTest.java @@ -8,6 +8,7 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import uk.gov.hmcts.reform.ccd.client.model.CaseDetails; +import uk.gov.hmcts.reform.fpl.enums.CMOStatus; import uk.gov.hmcts.reform.fpl.enums.HearingStatus; import uk.gov.hmcts.reform.fpl.enums.RemovableType; import uk.gov.hmcts.reform.fpl.exceptions.CMONotFoundException; @@ -112,6 +113,13 @@ void isAcceptedWhenHearingOrderTypeIsNull() { assertThat(underTest.isAccepted(order)).isTrue(); } + @Test + void isNotAcceptedWhenDraftCMOStatusIsReturned() { + RemovableOrder order = HearingOrder.builder().type(DRAFT_CMO).status(CMOStatus.RETURNED).build(); + + assertThat(underTest.isAccepted(order)).isFalse(); + } + @Test void isNotAcceptedIfAnyOtherClass() { assertThat(underTest.isAccepted(mock(RemovableOrder.class))).isFalse(); diff --git a/service/src/test/java/uk/gov/hmcts/reform/fpl/service/removeorder/OrderRemovalActionsTest.java b/service/src/test/java/uk/gov/hmcts/reform/fpl/service/removeorder/OrderRemovalActionsTest.java index 30b681c60a8..0ba972484b7 100644 --- a/service/src/test/java/uk/gov/hmcts/reform/fpl/service/removeorder/OrderRemovalActionsTest.java +++ b/service/src/test/java/uk/gov/hmcts/reform/fpl/service/removeorder/OrderRemovalActionsTest.java @@ -18,6 +18,7 @@ import static org.mockito.Mockito.when; import static uk.gov.hmcts.reform.fpl.enums.CMOStatus.APPROVED; import static uk.gov.hmcts.reform.fpl.enums.CMOStatus.DRAFT; +import static uk.gov.hmcts.reform.fpl.enums.CMOStatus.RETURNED; import static uk.gov.hmcts.reform.fpl.enums.CMOStatus.SEND_TO_JUDGE; import static uk.gov.hmcts.reform.fpl.enums.HearingOrderType.AGREED_CMO; import static uk.gov.hmcts.reform.fpl.enums.HearingOrderType.C21; @@ -40,12 +41,16 @@ class OrderRemovalActionsTest { @Mock private DraftOrderRemovalAction draftOrderRemovalAction; + @Mock + private RefusedHearingOrderRemovalAction refusedHearingOrderRemovalAction; + @InjectMocks private OrderRemovalActions orderRemovalActions; private static final HearingOrder SEALED_CASE_MANAGEMENT_ORDER = hearingOrder(AGREED_CMO, APPROVED); private static final HearingOrder DRAFT_CASE_MANAGEMENT_ORDER = hearingOrder(DRAFT_CMO, DRAFT); private static final HearingOrder DRAFT_ORDER = hearingOrder(C21, SEND_TO_JUDGE); + private static final HearingOrder RETURNED_ORDER = hearingOrder(C21, RETURNED); private static final GeneratedOrder GENERATED_ORDER = GeneratedOrder.builder().build(); private static final StandardDirectionOrder STANDARD_DIRECTION_ORDER = StandardDirectionOrder.builder().build(); @@ -88,6 +93,14 @@ void shouldReturnSDOActionWhenGettingActionForSDO() { .isEqualTo(sdoRemovalAction); } + @Test + void shouldReturnRefusedHearingOrderActionWhenGettingActionForRefusedOrder() { + when(sdoRemovalAction.isAccepted(STANDARD_DIRECTION_ORDER)).thenReturn(true); + + assertThat(orderRemovalActions.getAction(STANDARD_DIRECTION_ORDER)) + .isEqualTo(sdoRemovalAction); + } + @Test void shouldThrowAnExceptionWhenActionTypeFailsToMatchToRemovableOrder() { when(sealedCMORemovalAction.isAccepted(GENERATED_ORDER)).thenReturn(false); diff --git a/service/src/test/java/uk/gov/hmcts/reform/fpl/service/removeorder/RefusedHearingOrderRemovalActionTest.java b/service/src/test/java/uk/gov/hmcts/reform/fpl/service/removeorder/RefusedHearingOrderRemovalActionTest.java new file mode 100644 index 00000000000..d9e01d8c907 --- /dev/null +++ b/service/src/test/java/uk/gov/hmcts/reform/fpl/service/removeorder/RefusedHearingOrderRemovalActionTest.java @@ -0,0 +1,117 @@ +package uk.gov.hmcts.reform.fpl.service.removeorder; + +import org.apache.commons.lang3.StringUtils; +import org.junit.jupiter.api.Test; +import uk.gov.hmcts.reform.ccd.client.model.CaseDetails; +import uk.gov.hmcts.reform.fpl.model.CaseData; +import uk.gov.hmcts.reform.fpl.model.common.DocumentReference; +import uk.gov.hmcts.reform.fpl.model.common.Element; +import uk.gov.hmcts.reform.fpl.model.interfaces.RemovableOrder; +import uk.gov.hmcts.reform.fpl.model.order.HearingOrder; +import uk.gov.hmcts.reform.fpl.utils.CaseDetailsMap; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.HashMap; +import java.util.List; +import java.util.UUID; + +import static com.google.common.collect.Lists.newArrayList; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; +import static uk.gov.hmcts.reform.fpl.enums.CMOStatus.RETURNED; +import static uk.gov.hmcts.reform.fpl.enums.HearingOrderType.DRAFT_CMO; +import static uk.gov.hmcts.reform.fpl.enums.YesNo.NO; +import static uk.gov.hmcts.reform.fpl.utils.CaseDetailsMap.caseDetailsMap; +import static uk.gov.hmcts.reform.fpl.utils.DateFormatterHelper.formatLocalDateTimeBaseUsingFormat; +import static uk.gov.hmcts.reform.fpl.utils.ElementUtils.element; +import static uk.gov.hmcts.reform.fpl.utils.TestDataHelper.testDocumentReference; + +class RefusedHearingOrderRemovalActionTest { + + public static final UUID ORDER_TO_REMOVE_ID = UUID.randomUUID(); + + private RefusedHearingOrderRemovalAction underTest = new RefusedHearingOrderRemovalAction(); + + @Test + void acceptsReturnedOrder() { + RemovableOrder order = HearingOrder.builder().status(RETURNED).build(); + + assertThat(underTest.isAccepted(order)).isTrue(); + } + + @Test + void shouldRaiseExceptionIfReturnedHearingIdNotFound() { + DocumentReference order = testDocumentReference(); + + Element orderToBeRemoved = element(ORDER_TO_REMOVE_ID, returnedOrder(testDocumentReference())); + Element anotherOrder = element(returnedOrder(order)); + + CaseData caseData = CaseData.builder() + .refusedHearingOrders(newArrayList(anotherOrder)) + .build(); + + CaseDetailsMap caseDetailsMap = caseDetailsMap(CaseDetails.builder().data(new HashMap<>()).build()); + + assertThatThrownBy(() -> underTest.remove(caseData, caseDetailsMap, ORDER_TO_REMOVE_ID, + orderToBeRemoved.getValue())) + .isInstanceOf(IllegalStateException.class) + .hasMessage("Failed to find refused hearing order"); + } + + @Test + void shouldRemoveReturnedOrder() { + DocumentReference order = testDocumentReference(); + + Element orderToBeRemoved = element(ORDER_TO_REMOVE_ID, returnedOrder(testDocumentReference())); + Element anotherOrder = element(returnedOrder(order)); + + CaseData caseData = CaseData.builder() + .refusedHearingOrders(newArrayList(orderToBeRemoved, anotherOrder)) + .build(); + + CaseDetailsMap caseDetailsMap = caseDetailsMap(CaseDetails.builder().data(new HashMap<>()).build()); + underTest.remove(caseData, caseDetailsMap, ORDER_TO_REMOVE_ID, orderToBeRemoved.getValue()); + + List expectedOrders = newArrayList(anotherOrder); + + assertThat(caseDetailsMap.get("refusedHearingOrders")).isEqualTo(expectedOrders); + } + + @Test + void shouldPopulateCaseFieldsFromRemovableReturnedOrder() { + DocumentReference order = testDocumentReference(); + + Element orderToBeRemoved = element(ORDER_TO_REMOVE_ID, returnedOrder(testDocumentReference())); + Element anotherOrder = element(returnedOrder(order)); + + CaseData caseData = CaseData.builder() + .refusedHearingOrders(newArrayList(orderToBeRemoved, anotherOrder)) + .build(); + + CaseDetailsMap caseDetailsMap = caseDetailsMap(CaseDetails.builder().data(new HashMap<>()).build()); + + underTest.populateCaseFields(caseData, caseDetailsMap, ORDER_TO_REMOVE_ID, orderToBeRemoved.getValue()); + + assertThat(caseDetailsMap) + .extracting("orderToBeRemoved", + "orderTitleToBeRemoved", + "showRemoveCMOFieldsFlag", + "showReasonFieldFlag") + .containsExactly(orderToBeRemoved.getValue().getOrder(), + orderToBeRemoved.getValue().getTitle(), + StringUtils.EMPTY, + NO.getValue()); + } + + private HearingOrder returnedOrder(DocumentReference order) { + return HearingOrder.builder() + .type(DRAFT_CMO) + .status(RETURNED) + .order(order) + .dateSent(LocalDate.now().minusWeeks(1)) + .hearing("Draft Case management hearing sent on " + + formatLocalDateTimeBaseUsingFormat(LocalDateTime.now(), "d MMMM yyyy")) + .build(); + } +}