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 0c17c09c93..a7b0c72939 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 @@ -74,7 +74,8 @@ public void configure(final ConfigBuilder builder) { .field("nextStepsMarkdown", NEVER_SHOW); builder.tab("summary", "Summary") - .showCondition(ShowConditions.stateNotEquals(AWAITING_SUBMISSION_TO_HMCTS)) + .label("confirmEvictionSummaryMarkupLabel", null, "${confirmEvictionSummaryMarkup}") + .field("confirmEvictionSummaryMarkup", NEVER_SHOW) .field(PCSCase::getPropertyAddress); builder.tab("CaseHistory", "History") diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/EnforcementOrderMediator.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/EnforcementOrderMediator.java new file mode 100644 index 0000000000..9d80b75ffb --- /dev/null +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/EnforcementOrderMediator.java @@ -0,0 +1,69 @@ +package uk.gov.hmcts.reform.pcs.ccd; + +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import uk.gov.hmcts.ccd.sdk.type.YesOrNo; +import uk.gov.hmcts.reform.pcs.ccd.domain.PCSCase; +import uk.gov.hmcts.reform.pcs.ccd.entity.ClaimEntity; +import uk.gov.hmcts.reform.pcs.ccd.entity.PcsCaseEntity; +import uk.gov.hmcts.reform.pcs.ccd.entity.enforcetheorder.EnforcementOrderEntity; +import uk.gov.hmcts.reform.pcs.ccd.repository.PcsCaseRepository; +import uk.gov.hmcts.reform.pcs.ccd.repository.enforcetheorder.EnforcementOrderRepository; +import uk.gov.hmcts.reform.pcs.ccd.util.DateUtil; +import uk.gov.hmcts.reform.pcs.exception.CaseNotFoundException; + +import java.time.Instant; +import java.util.List; +import java.util.Optional; + +import static uk.gov.hmcts.reform.pcs.ccd.page.enforcetheorder.confirmeviction.MarkupContent.CONFIRM_EVICTION_SUMMARY_NO_DATES; +import static uk.gov.hmcts.reform.pcs.ccd.page.enforcetheorder.confirmeviction.MarkupContent.CONFIRM_EVICTION_SUMMARY_WITH_DATES; + +@Component +@Slf4j +@AllArgsConstructor +public class EnforcementOrderMediator { + + private final PcsCaseRepository pcsCaseRepository; + private final EnforcementOrderRepository enforcementOrderRepository; + private final DateUtil dateUtil; + + public void handleEnforcementRequirements(long caseReference, PCSCase pcsCase) { + if (caseReference > 0 && pcsCase != null) { + Optional optionalEnforcementOrder = getEnforcementOrder(caseReference); + if (optionalEnforcementOrder.isPresent()) { + EnforcementOrderEntity enforcementOrderEntity = optionalEnforcementOrder.get(); + if (enforcementOrderEntity.getBailiffDate() != null) { + hasBailiffDate(pcsCase, enforcementOrderEntity.getBailiffDate()); + } else { + noBailiffDate(pcsCase); + } + } + } + } + + Optional getEnforcementOrder(long caseReference) { + PcsCaseEntity pcsCaseEntity = pcsCaseRepository.findByCaseReference(caseReference) + .orElseThrow(() -> new CaseNotFoundException(caseReference)); + List claims = pcsCaseEntity.getClaims(); + if (claims != null && !claims.isEmpty()) { + return enforcementOrderRepository.findByClaimId(claims.getFirst().getId()); + } + return Optional.empty(); + } + + private void hasBailiffDate(PCSCase pcsCase, Instant instant) { + pcsCase.setShowConfirmEvictionJourney(YesOrNo.YES); + pcsCase.setConfirmEvictionSummaryMarkup(String.format( + CONFIRM_EVICTION_SUMMARY_WITH_DATES, + dateUtil.formatDate(instant), + dateUtil.minusHoursFormatted(instant, 72))); + } + + private static void noBailiffDate(PCSCase pcsCase) { + pcsCase.setShowConfirmEvictionJourney(YesOrNo.NO); + pcsCase.setConfirmEvictionSummaryMarkup(CONFIRM_EVICTION_SUMMARY_NO_DATES); + } + +} diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/PCSCaseView.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/PCSCaseView.java index bf3d8e6bbc..a9b7e9575e 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/PCSCaseView.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/PCSCaseView.java @@ -69,7 +69,7 @@ public class PCSCaseView implements CaseView { private final NoticeOfPossessionView noticeOfPossessionView; private final StatementOfTruthView statementOfTruthView; private final CaseNameHmctsFormatter caseNameHmctsFormatter; - + private final EnforcementOrderMediator enforcementOrderMediator; /** * Invoked by CCD to load PCS cases by reference. @@ -80,12 +80,12 @@ public PCSCase getCase(CaseViewRequest request) { long caseReference = request.caseRef(); State state = request.state(); PCSCase pcsCase = getSubmittedCase(caseReference); - boolean hasUnsubmittedCaseData = caseHasUnsubmittedData(caseReference, state); caseNameHmctsFormatter.setCaseNameHmctsField(pcsCase); setMarkdownFields(pcsCase, hasUnsubmittedCaseData); + enforcementOrderMediator.handleEnforcementRequirements(caseReference, pcsCase); //allows indexing for Global Search pcsCase.setSearchCriteria(new SearchCriteria()); 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 bcf12830fc..6696023691 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 @@ -521,4 +521,10 @@ public class PCSCase { ) private String caseNamePublic; + @CCD(searchable = false) + private String confirmEvictionSummaryMarkup; + + @CCD(searchable = false, access = {ClaimantAccess.class}) + private YesOrNo showConfirmEvictionJourney; + } diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/entity/enforcetheorder/EnforcementOrderEntity.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/entity/enforcetheorder/EnforcementOrderEntity.java index 3a90601007..fcd9f814f5 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/entity/enforcetheorder/EnforcementOrderEntity.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/entity/enforcetheorder/EnforcementOrderEntity.java @@ -10,13 +10,16 @@ import jakarta.persistence.ManyToOne; import jakarta.persistence.OneToOne; import jakarta.persistence.Table; +import lombok.AllArgsConstructor; import lombok.Getter; +import lombok.NoArgsConstructor; import lombok.Setter; import org.hibernate.annotations.JdbcTypeCode; import org.hibernate.type.SqlTypes; import uk.gov.hmcts.reform.pcs.ccd.domain.enforcetheorder.EnforcementOrder; import uk.gov.hmcts.reform.pcs.ccd.entity.ClaimEntity; +import java.time.Instant; import java.util.UUID; import static jakarta.persistence.FetchType.LAZY; @@ -25,6 +28,8 @@ @Table(name = "enf_case") @Getter @Setter +@NoArgsConstructor +@AllArgsConstructor public class EnforcementOrderEntity { @Id @@ -43,4 +48,7 @@ public class EnforcementOrderEntity { @OneToOne(mappedBy = "enforcementOrder", fetch = LAZY) private WarrantEntity warrantDetails; + @Column(name = "bailiff_date") + private Instant bailiffDate; + } 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 3a84e15878..8e48fabc23 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 @@ -7,5 +7,6 @@ public enum EventId { enforceTheOrder, respondPossessionClaim, submitDefendantResponse, - createTestCase + createTestCase, + confirmEviction } diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/confirmeviction/ConfirmEviction.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/confirmeviction/ConfirmEviction.java new file mode 100644 index 0000000000..7357d5fcfd --- /dev/null +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/event/confirmeviction/ConfirmEviction.java @@ -0,0 +1,41 @@ +package uk.gov.hmcts.reform.pcs.ccd.event.confirmeviction; + +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.enforcetheorder.confirmeviction.ConfirmEvictionConfigurer; + +import static uk.gov.hmcts.reform.pcs.ccd.event.EventId.confirmEviction; + +@Component +@AllArgsConstructor +public class ConfirmEviction implements CCDConfig { + + private final ConfirmEvictionConfigurer confirmEvictionConfigurer; + + @Override + public void configureDecentralised(DecentralisedConfigBuilder configBuilder) { + Event.EventBuilder eventBuilder = + configBuilder + .decentralisedEvent(confirmEviction.name(), this::submit) + .forAllStates() + .name("Confirm the eviction details") + .grant(Permission.CRUD, UserRole.PCS_SOLICITOR) + .showSummary(); + confirmEvictionConfigurer.configurePages(new PageBuilder(eventBuilder)); + } + + private SubmitResponse submit(EventPayload eventPayload) { + return SubmitResponse.defaultResponse(); + } + +} diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/enforcetheorder/confirmeviction/ConfirmEvictionConfigurer.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/enforcetheorder/confirmeviction/ConfirmEvictionConfigurer.java new file mode 100644 index 0000000000..393290c726 --- /dev/null +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/enforcetheorder/confirmeviction/ConfirmEvictionConfigurer.java @@ -0,0 +1,18 @@ +package uk.gov.hmcts.reform.pcs.ccd.page.enforcetheorder.confirmeviction; + +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Component; +import uk.gov.hmcts.reform.pcs.ccd.common.PageBuilder; +import uk.gov.hmcts.reform.pcs.ccd.common.PageConfigurer; + +@Component +@AllArgsConstructor +public class ConfirmEvictionConfigurer implements PageConfigurer { + + @Override + public void configurePages(PageBuilder pageBuilder) { + pageBuilder + .add(new ConfirmEvictionDetailsPage()) + .add(new EvictionDatePage()); + } +} diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/enforcetheorder/confirmeviction/ConfirmEvictionDetailsPage.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/enforcetheorder/confirmeviction/ConfirmEvictionDetailsPage.java new file mode 100644 index 0000000000..252ac449c1 --- /dev/null +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/enforcetheorder/confirmeviction/ConfirmEvictionDetailsPage.java @@ -0,0 +1,56 @@ +package uk.gov.hmcts.reform.pcs.ccd.page.enforcetheorder.confirmeviction; + +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.page.CcdPage; + +public class ConfirmEvictionDetailsPage implements CcdPageConfiguration, CcdPage { + + public static final String CONFIRM_EVICTION_DETAILS_CONTENT = """ +

+ The bailiff has arranged a date for the eviction and they need you to confirm if you are + available. +

+

+ They will also ask you to confirm if the person being evicted poses any risk. +

+

+ The bailiff needs this information to carry out the eviction safely. If you do not provide it, + they may not be able to complete the eviction. +

+

What you’ll need +

+

You’ll need to know:

+
    +
  • who will attend the eviction (you, or someone else)
  • +
  • if you (or they) can attend the eviction on the date suggested + by the bailiff
  • +
+

We will also ask you to:

+
    +
  • describe the person who will be evicted
  • +
  • tell us how to access the property
  • +
  • book a locksmith (this is to make sure that the person being + evicted cannot return to the property)
  • +
+

+ Once you have confirmed the eviction date, we’ll send you an email reminding you to book a + locksmith. +

+ """; + + @Override + public void addTo(PageBuilder pageBuilder) { + String pageKey = getPageKey(); + pageBuilder + .page(pageKey) + .pageLabel("Confirm the eviction details") + .label(pageKey + "-line-separator", "---") + .label(pageKey + "-content", CONFIRM_EVICTION_DETAILS_CONTENT); + } + + @Override + public String getPageKey() { + return CcdPage.derivePageKey(this.getClass()); + } +} diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/enforcetheorder/confirmeviction/EvictionDatePage.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/enforcetheorder/confirmeviction/EvictionDatePage.java new file mode 100644 index 0000000000..beebe71a6e --- /dev/null +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/enforcetheorder/confirmeviction/EvictionDatePage.java @@ -0,0 +1,23 @@ +package uk.gov.hmcts.reform.pcs.ccd.page.enforcetheorder.confirmeviction; + +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.page.CcdPage; + +public class EvictionDatePage implements CcdPageConfiguration, CcdPage { + + @Override + public void addTo(PageBuilder pageBuilder) { + String pageKey = getPageKey(); + pageBuilder + .page(pageKey) + .pageLabel("The eviction date") + .label(pageKey + "-line-separator", "---"); + } + + @Override + public String getPageKey() { + return CcdPage.derivePageKey(this.getClass()); + } + +} diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/enforcetheorder/confirmeviction/MarkupContent.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/enforcetheorder/confirmeviction/MarkupContent.java new file mode 100644 index 0000000000..1eed86129f --- /dev/null +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/page/enforcetheorder/confirmeviction/MarkupContent.java @@ -0,0 +1,55 @@ +package uk.gov.hmcts.reform.pcs.ccd.page.enforcetheorder.confirmeviction; + +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class MarkupContent { + + public static String CONFIRM_EVICTION_SUMMARY_WITH_DATES = + """ +

Confirm the eviction date

+

+ The bailiff has given you an eviction date of %s. + They need you to confirm if you are available on this date. +

+

+ You must confirm the eviction details before %s. + If you try to confirm the eviction after this + date, the bailiff will cancel your eviction. + They will also ask you to confirm if the defendants + (the person or people being evicted) pose any risk to the + bailiff. + The bailiff needs this information to carry out the eviction + safely. +

+

+ To confirm the eviction date, select ‘Confirm the eviction + date’ from the dropdown menu. +

+ """; + + public static String CONFIRM_EVICTION_SUMMARY_NO_DATES = + """ +

You cannot enforce the order at the moment

+

+ You cannot enforce the order at the moment (use a bailiff to evict someone). +

+

How to find out why you cannot + enforce the order +

+

To find out why you cannot enforce the order, you can:

+
    +
  • check the tab: ‘Case file view’ (you should see an order from the court, + explaining why you cannot enforce), or
  • +
  • + + contact your local court. You will need to tell them your case number + (you can find this at the top of this page). If you do not know the name of your local court, select the + ‘Money’ category and then the ‘Housing’ category to find it.
  • +
+ """; + +} diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/repository/enforcetheorder/EnforcementOrderRepository.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/repository/enforcetheorder/EnforcementOrderRepository.java index a7c0ce7e94..11e43d1ee4 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/repository/enforcetheorder/EnforcementOrderRepository.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/repository/enforcetheorder/EnforcementOrderRepository.java @@ -3,8 +3,9 @@ import org.springframework.data.jpa.repository.JpaRepository; import uk.gov.hmcts.reform.pcs.ccd.entity.enforcetheorder.EnforcementOrderEntity; +import java.util.Optional; import java.util.UUID; public interface EnforcementOrderRepository extends JpaRepository { - + Optional findByClaimId(UUID claimId); } diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/util/DateUtil.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/util/DateUtil.java new file mode 100644 index 0000000000..48e5d27952 --- /dev/null +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/util/DateUtil.java @@ -0,0 +1,23 @@ +package uk.gov.hmcts.reform.pcs.ccd.util; + +import org.springframework.stereotype.Component; + +import java.time.Instant; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; +import java.util.Locale; + +@Component +public class DateUtil { + + public String formatDate(Instant instant) { + DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("EEEE, d MMMM yyyy", Locale.UK); + return instant.atZone(ZoneId.of("UTC")).format(outputFormatter); + } + + public String minusHoursFormatted(Instant instant, int hours) { + DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("d MMMM yyyy", Locale.UK); + return instant.atZone(ZoneId.of("UTC")).minusHours(hours).format(outputFormatter); + } + +} diff --git a/src/main/resources/db/migration/V073__add_bailiff_date_enf_case.sql b/src/main/resources/db/migration/V073__add_bailiff_date_enf_case.sql new file mode 100644 index 0000000000..c377a15e31 --- /dev/null +++ b/src/main/resources/db/migration/V073__add_bailiff_date_enf_case.sql @@ -0,0 +1,2 @@ +ALTER TABLE enf_case + ADD COLUMN bailiff_date timestamp with time zone; diff --git a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/EnforcementOrderMediatorTest.java b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/EnforcementOrderMediatorTest.java new file mode 100644 index 0000000000..89f6589244 --- /dev/null +++ b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/EnforcementOrderMediatorTest.java @@ -0,0 +1,333 @@ +package uk.gov.hmcts.reform.pcs.ccd; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import uk.gov.hmcts.ccd.sdk.type.YesOrNo; +import uk.gov.hmcts.reform.pcs.ccd.domain.PCSCase; +import uk.gov.hmcts.reform.pcs.ccd.domain.enforcetheorder.EnforcementOrder; +import uk.gov.hmcts.reform.pcs.ccd.entity.ClaimEntity; +import uk.gov.hmcts.reform.pcs.ccd.entity.PcsCaseEntity; +import uk.gov.hmcts.reform.pcs.ccd.entity.enforcetheorder.EnforcementOrderEntity; +import uk.gov.hmcts.reform.pcs.ccd.repository.PcsCaseRepository; +import uk.gov.hmcts.reform.pcs.ccd.repository.enforcetheorder.EnforcementOrderRepository; +import uk.gov.hmcts.reform.pcs.ccd.util.DateUtil; +import uk.gov.hmcts.reform.pcs.exception.CaseNotFoundException; + +import java.time.Instant; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.Optional; +import java.util.UUID; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.Mockito.lenient; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class EnforcementOrderMediatorTest { + + public static final long CASE_REFERENCE = 1234567890L; + + @Mock + private PcsCaseRepository pcsCaseRepository; + @Mock + private EnforcementOrderRepository enforcementOrderRepository; + @Mock + private DateUtil dateUtil; + + @InjectMocks + private EnforcementOrderMediator underTest; + + private PCSCase pcsCase; + + @BeforeEach + void beforeEach() { + pcsCase = PCSCase.builder() + .enforcementOrder(EnforcementOrder.builder().build()) + .build(); + lenient().when(dateUtil.formatDate(any(Instant.class))).thenCallRealMethod(); + lenient().when(dateUtil.minusHoursFormatted(any(Instant.class), anyInt())).thenCallRealMethod(); + } + + @Test + void shouldSetShowConfirmEvictionJourneyToYesWhenBailiffDateExists() { + // Given + long caseReference = 1234567890L; + Instant bailiffDate = Instant.parse("2026-04-15T10:00:00Z"); + + PcsCaseEntity pcsCaseEntity = createPcsCaseEntity(); + EnforcementOrderEntity enforcementOrderEntity = createEnforcementOrderEntity(bailiffDate); + + when(pcsCaseRepository.findByCaseReference(caseReference)) + .thenReturn(Optional.of(pcsCaseEntity)); + when(enforcementOrderRepository.findByClaimId(any(UUID.class))) + .thenReturn(Optional.of(enforcementOrderEntity)); + + // When + underTest.handleEnforcementRequirements(caseReference, pcsCase); + + // Then + assertEquals(YesOrNo.YES, pcsCase.getShowConfirmEvictionJourney()); + assertNotNull(pcsCase.getConfirmEvictionSummaryMarkup()); + assertTrue(pcsCase.getConfirmEvictionSummaryMarkup().contains("Confirm the eviction date")); + verify(pcsCaseRepository).findByCaseReference(caseReference); + verify(enforcementOrderRepository).findByClaimId(any(UUID.class)); + } + + @Test + void shouldSetShowConfirmEvictionJourneyToNoWhenBailiffDateIsNull() { + // Given + long caseReference = 1234567890L; + PcsCaseEntity pcsCaseEntity = createPcsCaseEntity(); + EnforcementOrderEntity enforcementOrderEntity = createEnforcementOrderEntity(null); + + when(pcsCaseRepository.findByCaseReference(caseReference)) + .thenReturn(Optional.of(pcsCaseEntity)); + when(enforcementOrderRepository.findByClaimId(any(UUID.class))) + .thenReturn(Optional.of(enforcementOrderEntity)); + + // When + underTest.handleEnforcementRequirements(caseReference, pcsCase); + + // Then + assertEquals(YesOrNo.NO, pcsCase.getShowConfirmEvictionJourney()); + assertNotNull(pcsCase.getConfirmEvictionSummaryMarkup()); + assertTrue(pcsCase.getConfirmEvictionSummaryMarkup().contains("You cannot enforce the order at the moment")); + verify(pcsCaseRepository).findByCaseReference(caseReference); + verify(enforcementOrderRepository).findByClaimId(any(UUID.class)); + } + + @Test + void shouldFormatBailiffDateCorrectlyInMarkup() { + // Given + long caseReference = 1234567890L; + Instant bailiffDate = Instant.parse("2026-05-20T14:30:00Z"); + + PcsCaseEntity pcsCaseEntity = createPcsCaseEntity(); + EnforcementOrderEntity enforcementOrderEntity = createEnforcementOrderEntity(bailiffDate); + + when(pcsCaseRepository.findByCaseReference(caseReference)) + .thenReturn(Optional.of(pcsCaseEntity)); + when(enforcementOrderRepository.findByClaimId(any(UUID.class))) + .thenReturn(Optional.of(enforcementOrderEntity)); + + // When + underTest.handleEnforcementRequirements(caseReference, pcsCase); + + // Then + DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("EEEE, d MMMM yyyy", Locale.UK); + String expectedDate = bailiffDate.atZone(ZoneId.of("UTC")).format(outputFormatter); + assertTrue(pcsCase.getConfirmEvictionSummaryMarkup().contains(expectedDate)); + } + + @Test + void shouldCalculateDeadlineDateAsMinus72HoursFromBailiffDate() { + // Given + long caseReference = 1234567890L; + Instant bailiffDate = Instant.parse("2026-05-20T14:30:00Z"); + + PcsCaseEntity pcsCaseEntity = createPcsCaseEntity(); + EnforcementOrderEntity enforcementOrderEntity = createEnforcementOrderEntity(bailiffDate); + + when(pcsCaseRepository.findByCaseReference(caseReference)) + .thenReturn(Optional.of(pcsCaseEntity)); + when(enforcementOrderRepository.findByClaimId(any(UUID.class))) + .thenReturn(Optional.of(enforcementOrderEntity)); + + // When + underTest.handleEnforcementRequirements(caseReference, pcsCase); + + // Then + DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("d MMMM yyyy", Locale.UK); + String expectedDeadline = bailiffDate.atZone(ZoneId.of("UTC")).minusHours(72).format(outputFormatter); + assertTrue(pcsCase.getConfirmEvictionSummaryMarkup().contains(expectedDeadline)); + } + + @Test + void shouldNotProcessWhenCaseReferenceIsZero() { + // Given + long caseReference = 0L; + + // When + underTest.handleEnforcementRequirements(caseReference, pcsCase); + + // Then + assertNull(pcsCase.getShowConfirmEvictionJourney()); + assertNull(pcsCase.getConfirmEvictionSummaryMarkup()); + verify(pcsCaseRepository, never()).findByCaseReference(anyLong()); + } + + @Test + void shouldNotProcessWhenCaseReferenceIsNegative() { + // Given + long caseReference = -1L; + + // When + underTest.handleEnforcementRequirements(caseReference, pcsCase); + + // Then + assertNull(pcsCase.getShowConfirmEvictionJourney()); + assertNull(pcsCase.getConfirmEvictionSummaryMarkup()); + verify(pcsCaseRepository, never()).findByCaseReference(anyLong()); + } + + @Test + void shouldNotProcessWhenPcsCaseIsNull() { + // Given + long caseReference = 1234567890L; + + // When + underTest.handleEnforcementRequirements(caseReference, null); + + // Then + verify(pcsCaseRepository, never()).findByCaseReference(anyLong()); + } + + @Test + void shouldThrowCaseNotFoundExceptionWhenCaseDoesNotExist() { + // Given + long caseReference = 1234567890L; + + when(pcsCaseRepository.findByCaseReference(caseReference)) + .thenReturn(Optional.empty()); + + // When & Then + assertThrows(CaseNotFoundException.class, () -> + underTest.handleEnforcementRequirements(caseReference, pcsCase) + ); + verify(pcsCaseRepository).findByCaseReference(caseReference); + } + + @Test + void shouldReturnEmptyWhenClaimsListIsNull() { + // Given + long caseReference = 1234567890L; + PcsCaseEntity pcsCaseEntity = new PcsCaseEntity(); + pcsCaseEntity.setClaims(null); + + when(pcsCaseRepository.findByCaseReference(caseReference)) + .thenReturn(Optional.of(pcsCaseEntity)); + + // When + Optional result = underTest.getEnforcementOrder(caseReference); + + // Then + assertTrue(result.isEmpty()); + verify(pcsCaseRepository).findByCaseReference(caseReference); + verify(enforcementOrderRepository, never()).findByClaimId(any()); + } + + @Test + void shouldReturnEmptyWhenClaimsListIsEmpty() { + // Given + long caseReference = 1234567890L; + PcsCaseEntity pcsCaseEntity = new PcsCaseEntity(); + pcsCaseEntity.setClaims(new ArrayList<>()); + + when(pcsCaseRepository.findByCaseReference(caseReference)) + .thenReturn(Optional.of(pcsCaseEntity)); + + // When + Optional result = underTest.getEnforcementOrder(caseReference); + + // Then + assertTrue(result.isEmpty()); + verify(pcsCaseRepository).findByCaseReference(caseReference); + verify(enforcementOrderRepository, never()).findByClaimId(any()); + } + + @Test + void shouldReturnEnforcementOrderWhenFound() { + // Given + long caseReference = 1234567890L; + PcsCaseEntity pcsCaseEntity = createPcsCaseEntity(); + EnforcementOrderEntity enforcementOrderEntity = createEnforcementOrderEntity(Instant.now()); + + when(pcsCaseRepository.findByCaseReference(caseReference)) + .thenReturn(Optional.of(pcsCaseEntity)); + when(enforcementOrderRepository.findByClaimId(any(UUID.class))) + .thenReturn(Optional.of(enforcementOrderEntity)); + + // When + Optional result = underTest.getEnforcementOrder(caseReference); + + // Then + assertTrue(result.isPresent()); + assertEquals(enforcementOrderEntity, result.get()); + verify(pcsCaseRepository).findByCaseReference(caseReference); + verify(enforcementOrderRepository).findByClaimId(any(UUID.class)); + } + + @Test + void shouldReturnEmptyWhenEnforcementOrderNotFound() { + // Given + PcsCaseEntity pcsCaseEntity = createPcsCaseEntity(); + + when(pcsCaseRepository.findByCaseReference(CASE_REFERENCE)) + .thenReturn(Optional.of(pcsCaseEntity)); + when(enforcementOrderRepository.findByClaimId(any(UUID.class))) + .thenReturn(Optional.empty()); + + // When + Optional result = underTest.getEnforcementOrder(CASE_REFERENCE); + + // Then + assertTrue(result.isEmpty()); + verify(pcsCaseRepository).findByCaseReference(CASE_REFERENCE); + verify(enforcementOrderRepository).findByClaimId(any(UUID.class)); + } + + @Test + void shouldNotSetMarkupWhenEnforcementOrderNotPresent() { + // Given + long caseReference = 1234567890L; + PcsCaseEntity pcsCaseEntity = createPcsCaseEntity(); + + when(pcsCaseRepository.findByCaseReference(caseReference)) + .thenReturn(Optional.of(pcsCaseEntity)); + when(enforcementOrderRepository.findByClaimId(any(UUID.class))) + .thenReturn(Optional.empty()); + + // When + underTest.handleEnforcementRequirements(caseReference, pcsCase); + + // Then + assertNull(pcsCase.getShowConfirmEvictionJourney()); + assertNull(pcsCase.getConfirmEvictionSummaryMarkup()); + verify(pcsCaseRepository).findByCaseReference(caseReference); + verify(enforcementOrderRepository).findByClaimId(any(UUID.class)); + } + + // Helper methods + private PcsCaseEntity createPcsCaseEntity() { + PcsCaseEntity entity = new PcsCaseEntity(); + ClaimEntity claimEntity = new ClaimEntity(); + claimEntity.setId(UUID.randomUUID()); + entity.setClaims(List.of(claimEntity)); + return entity; + } + + private EnforcementOrderEntity createEnforcementOrderEntity(Instant bailiffDate) { + EnforcementOrderEntity entity = new EnforcementOrderEntity(); + entity.setId(UUID.randomUUID()); + entity.setBailiffDate(bailiffDate); + return entity; + } + +} diff --git a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/PCSCaseViewTest.java b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/PCSCaseViewTest.java index 204263c825..d7c49011c9 100644 --- a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/PCSCaseViewTest.java +++ b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/PCSCaseViewTest.java @@ -96,6 +96,8 @@ class PCSCaseViewTest { private ClaimEntity claimEntity; @Mock private CaseNameHmctsFormatter caseNameHmctsFormatter; + @Mock + private EnforcementOrderMediator enforcementOrderMediator; private PCSCaseView underTest; @@ -107,8 +109,8 @@ void setUp() { underTest = new PCSCaseView(pcsCaseRepository, securityContextService, modelMapper, draftCaseDataService, caseTitleService, claimView, tenancyLicenceView, claimGroundsView, rentDetailsView, alternativesToPossessionView, housingActWalesView, asbProhibitedConductView, - rentArrearsView, noticeOfPossessionView, - statementOfTruthView, caseNameHmctsFormatter + rentArrearsView, noticeOfPossessionView, statementOfTruthView, + caseNameHmctsFormatter, enforcementOrderMediator ); } @@ -345,6 +347,15 @@ void shouldSetCaseNameHmctsField() { verify(caseNameHmctsFormatter).setCaseNameHmctsField(pcsCase); } + @Test + void shouldCallEnforcementOrderMediator() { + // When + PCSCase pcsCase = underTest.getCase(request(CASE_REFERENCE, DEFAULT_STATE)); + + // Then + verify(enforcementOrderMediator).handleEnforcementRequirements(CASE_REFERENCE, pcsCase); + } + private AddressUK stubAddressEntityModelMapper(AddressEntity addressEntity) { AddressUK addressUK = mock(AddressUK.class); when(modelMapper.map(addressEntity, AddressUK.class)).thenReturn(addressUK); diff --git a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/page/enforcetheorder/PageConfigurerHelper.java b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/page/enforcetheorder/PageConfigurerHelper.java index 1298af5944..6722df7042 100644 --- a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/page/enforcetheorder/PageConfigurerHelper.java +++ b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/page/enforcetheorder/PageConfigurerHelper.java @@ -1,25 +1,29 @@ package uk.gov.hmcts.reform.pcs.ccd.page.enforcetheorder; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; import org.mockito.InOrder; import uk.gov.hmcts.reform.pcs.ccd.common.CcdPageConfiguration; -import uk.gov.hmcts.reform.pcs.ccd.page.builder.SavingPageBuilder; +import uk.gov.hmcts.reform.pcs.ccd.common.PageBuilder; import java.util.concurrent.atomic.AtomicInteger; import static org.mockito.ArgumentMatchers.isA; -public class PageConfigurerHelper { +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public final class PageConfigurerHelper { - public static void verifyAndCount(InOrder inOrder, SavingPageBuilder pageBuilder, + public static void verifyAndCount(InOrder inOrder, PageBuilder pageBuilder, Class pageClass, AtomicInteger counter) { inOrder.verify(pageBuilder).add(isA(pageClass)); counter.incrementAndGet(); } - public static void verifyAndCount(InOrder inOrder, SavingPageBuilder pageBuilder, + public static void verifyAndCount(InOrder inOrder, PageBuilder pageBuilder, CcdPageConfiguration specificInstance, AtomicInteger counter) { inOrder.verify(pageBuilder).add(specificInstance); counter.incrementAndGet(); } + } diff --git a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/page/enforcetheorder/confirmeviction/ConfirmEvictionPageConfigurerTest.java b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/page/enforcetheorder/confirmeviction/ConfirmEvictionPageConfigurerTest.java new file mode 100644 index 0000000000..78d642dc88 --- /dev/null +++ b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/page/enforcetheorder/confirmeviction/ConfirmEvictionPageConfigurerTest.java @@ -0,0 +1,55 @@ +package uk.gov.hmcts.reform.pcs.ccd.page.enforcetheorder.confirmeviction; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.InOrder; +import org.mockito.InjectMocks; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; +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.page.BasePageTest; + +import java.util.concurrent.atomic.AtomicInteger; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + +import static uk.gov.hmcts.reform.pcs.ccd.page.enforcetheorder.PageConfigurerHelper.verifyAndCount; + +@ExtendWith(MockitoExtension.class) +class ConfirmEvictionPageConfigurerTest extends BasePageTest { + + @InjectMocks + private ConfirmEvictionConfigurer underTest; + + @Test + @SuppressWarnings("squid:S5961") + void shouldConfigurePagesInCorrectOrder() { + // Given + PageBuilder pageBuilder = mock(PageBuilder.class); + when(pageBuilder.add(any())).thenReturn(pageBuilder); + + // When + underTest.configurePages(pageBuilder); + + // Then + ArgumentCaptor pageCaptor = ArgumentCaptor.forClass(CcdPageConfiguration.class); + InOrder inOrder = inOrder(pageBuilder); + Mockito.verify(pageBuilder, Mockito.atLeastOnce()).add(pageCaptor.capture()); + AtomicInteger verificationCount = new AtomicInteger(0); + + verifyAndCount(inOrder, pageBuilder, ConfirmEvictionDetailsPage.class, verificationCount); + verifyAndCount(inOrder, pageBuilder, EvictionDatePage.class, verificationCount); + + int numberOfPages = pageCaptor.getAllValues().size(); + assertThat(verificationCount.get()).isEqualTo(numberOfPages); + + verifyNoMoreInteractions(pageBuilder); + } +}