diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/entity/confirmeviction/EvictionEntity.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/entity/confirmeviction/EvictionEntity.java new file mode 100644 index 0000000000..283f84c3f7 --- /dev/null +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/entity/confirmeviction/EvictionEntity.java @@ -0,0 +1,97 @@ +package uk.gov.hmcts.reform.pcs.ccd.entity.confirmeviction; + +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.OneToMany; +import jakarta.persistence.OneToOne; +import jakarta.persistence.Table; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.hibernate.annotations.CreationTimestamp; +import org.hibernate.annotations.JdbcTypeCode; +import org.hibernate.type.SqlTypes; +import uk.gov.hmcts.reform.pcs.ccd.domain.LanguageUsed; +import uk.gov.hmcts.reform.pcs.ccd.domain.VerticalYesNo; +import uk.gov.hmcts.reform.pcs.ccd.entity.enforcetheorder.EnforcementOrderEntity; +import uk.gov.hmcts.reform.pcs.ccd.entity.enforcetheorder.UnavailableDateEntity; + +import java.time.Instant; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +@Entity +@Builder +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@Table(name = "enf_eviction") +public class EvictionEntity { + + @Id + @GeneratedValue(strategy = GenerationType.UUID) + private UUID id; + + @OneToOne + @JoinColumn(name = "enf_case_id", nullable = false) + private EnforcementOrderEntity enforcementOrder; + + @Enumerated(EnumType.STRING) + @JdbcTypeCode(SqlTypes.NAMED_ENUM) + private VerticalYesNo evictionDateConfirmed; + + @Enumerated(EnumType.STRING) + @JdbcTypeCode(SqlTypes.NAMED_ENUM) + private VerticalYesNo hasUnavailableDates; + + @OneToMany(mappedBy = "eviction", cascade = CascadeType.ALL, orphanRemoval = true) + @Builder.Default + private List unavailableDates = new ArrayList<>(); + + private String beforeEvictionNameOrDepartment; + + private String beforeEvictionTelephoneNumber; + + private String beforeEvictionEmailAddress; + + private String afterEvictionNameOrDepartment; + + private String afterEvictionTelephoneNumber; + + private String afterEvictionEmailAddress; + + @Enumerated(EnumType.STRING) + @JdbcTypeCode(SqlTypes.NAMED_ENUM) + private VerticalYesNo difficultToAccess; + + private String difficultToAccessDetails; + + @Enumerated(EnumType.STRING) + @JdbcTypeCode(SqlTypes.NAMED_ENUM) + private VerticalYesNo anythingElse; + + private String anythingElseDetails; + + @Enumerated(EnumType.STRING) + @JdbcTypeCode(SqlTypes.NAMED_ENUM) + private VerticalYesNo confirmArrangementForAccess; + + @Enumerated(EnumType.STRING) + private LanguageUsed languageUsed; + + @CreationTimestamp + @Column(updatable = false, nullable = false) + private Instant created; + +} diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/entity/enforcetheorder/UnavailableDateEntity.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/entity/enforcetheorder/UnavailableDateEntity.java new file mode 100644 index 0000000000..da89202f48 --- /dev/null +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/entity/enforcetheorder/UnavailableDateEntity.java @@ -0,0 +1,42 @@ +package uk.gov.hmcts.reform.pcs.ccd.entity.enforcetheorder; + +import com.fasterxml.jackson.annotation.JsonBackReference; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import uk.gov.hmcts.reform.pcs.ccd.entity.confirmeviction.EvictionEntity; + +import java.time.LocalDate; +import java.util.UUID; + +@Entity +@Builder +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@Table(name = "enf_unavailable_date") +public class UnavailableDateEntity { + + @Id + @GeneratedValue(strategy = GenerationType.UUID) + private UUID id; + + @ManyToOne + @JoinColumn(name = "enf_eviction_id", nullable = false) + @JsonBackReference + private EvictionEntity eviction; + + private LocalDate unavailableDate; + +} + diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/repository/enforcetheorder/EvictionRepository.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/repository/enforcetheorder/EvictionRepository.java new file mode 100644 index 0000000000..9ec1310f92 --- /dev/null +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/repository/enforcetheorder/EvictionRepository.java @@ -0,0 +1,9 @@ +package uk.gov.hmcts.reform.pcs.ccd.repository.enforcetheorder; + +import org.springframework.data.jpa.repository.JpaRepository; +import uk.gov.hmcts.reform.pcs.ccd.entity.confirmeviction.EvictionEntity; + +import java.util.UUID; + +public interface EvictionRepository extends JpaRepository { +} diff --git a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/enforcetheorder/EnforcementOrderService.java b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/enforcetheorder/EnforcementOrderService.java index b54a25ac9d..f09db29d5b 100644 --- a/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/enforcetheorder/EnforcementOrderService.java +++ b/src/main/java/uk/gov/hmcts/reform/pcs/ccd/service/enforcetheorder/EnforcementOrderService.java @@ -9,8 +9,10 @@ import uk.gov.hmcts.reform.pcs.ccd.domain.enforcetheorder.SelectEnforcementType; 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.confirmeviction.EvictionEntity; import uk.gov.hmcts.reform.pcs.ccd.entity.enforcetheorder.EnforcementOrderEntity; import uk.gov.hmcts.reform.pcs.ccd.event.EventId; +import uk.gov.hmcts.reform.pcs.ccd.repository.enforcetheorder.EvictionRepository; import uk.gov.hmcts.reform.pcs.ccd.repository.enforcetheorder.EnforcementOrderRepository; import uk.gov.hmcts.reform.pcs.ccd.service.DraftCaseDataService; import uk.gov.hmcts.reform.pcs.ccd.service.PcsCaseService; @@ -19,6 +21,8 @@ import java.util.List; import java.util.Set; +import static uk.gov.hmcts.reform.pcs.ccd.domain.enforcetheorder.SelectEnforcementType.getSelectEnforcementTypeFromName; + @Service @Slf4j @AllArgsConstructor @@ -28,15 +32,10 @@ public class EnforcementOrderService { private final PcsCaseService pcsCaseService; private final DraftCaseDataService draftCaseDataService; private final EnforcementTypeStrategyFactory strategyFactory; + private final EvictionRepository evictionRepository; public EnforcementOrder retrieveEnforcementOrder(long caseReference, SelectEnforcementType enforcementType) { - PcsCaseEntity pcsCaseEntity = pcsCaseService.loadCase(caseReference); - ClaimEntity claimEntity = retrieveClaimEntity(pcsCaseEntity); - Set enforcementEntitySet = claimEntity.getEnforcementOrders(); - if (CollectionUtils.isEmpty(enforcementEntitySet)) { - return null; - } - + Set enforcementEntitySet = getEnforcementOrderEntities(caseReference); return enforcementEntitySet .stream() .map(EnforcementOrderEntity::getEnforcementOrder) @@ -46,9 +45,23 @@ public EnforcementOrder retrieveEnforcementOrder(long caseReference, SelectEnfor .orElse(null); } + Set getEnforcementOrderEntities(long caseReference) { + PcsCaseEntity pcsCaseEntity = pcsCaseService.loadCase(caseReference); + ClaimEntity claimEntity = retrieveClaimEntity(pcsCaseEntity); + if (claimEntity == null) { + log.debug("No claim entities found for PCS case when retrieving enforcement order for caseReference={}", + caseReference + ); + return Set.of(); + } + return claimEntity.getEnforcementOrders(); + } + ClaimEntity retrieveClaimEntity(PcsCaseEntity pcsCaseEntity) { List claimEntities = pcsCaseEntity.getClaims(); - + if (CollectionUtils.isEmpty(claimEntities)) { + return null; + } // Assuming 1 claim per PcsCase return claimEntities.getFirst(); } @@ -60,15 +73,44 @@ public void saveAndClearDraftData(long caseReference, EnforcementOrder enforceme } private void createEnforcementOrder(long caseReference, EnforcementOrder enforcementOrder) { + ClaimEntity claimEntity = getClaimEntity(caseReference); + EnforcementOrderEntity orderEntity = enforcementOrderRepository + .save(mapToEntity(enforcementOrder, claimEntity)); + strategyFactory.getStrategy(getSelectEnforcementTypeFromName( + enforcementOrder.getChooseEnforcementType().getValueCode())) + .process(orderEntity, enforcementOrder); + } + + private ClaimEntity getClaimEntity(long caseReference) { PcsCaseEntity pcsCaseEntity = pcsCaseService.loadCase(caseReference); + List claimEntities = pcsCaseEntity.getClaims(); + if (CollectionUtils.isEmpty(claimEntities)) { + throw new IllegalStateException("Cannot create enforcement order because no claim entity exists for " + + "caseReference=" + caseReference); + } + // Assuming 1 claim per PcsCase + return claimEntities.getFirst(); + } - ClaimEntity claimEntity = retrieveClaimEntity(pcsCaseEntity); + public void confirmEviction(long caseReference) { + EvictionEntity confirmEviction = mapToConfirmEvictionEntity(caseReference); + evictionRepository.save(confirmEviction); + } - EnforcementOrderEntity orderEntity = enforcementOrderRepository - .save(mapToEntity(enforcementOrder, claimEntity)); - strategyFactory.getStrategy(SelectEnforcementType.getSelectEnforcementTypeFromName( - enforcementOrder.getChooseEnforcementType().getValueCode())) - .process(orderEntity, enforcementOrder); + private EvictionEntity mapToConfirmEvictionEntity(long caseReference) { + EvictionEntity confirmEviction = new EvictionEntity(); + EnforcementOrderEntity enforcementOrderEntity = retrieveEnforcementOrderEntity(caseReference); + confirmEviction.setEnforcementOrder(enforcementOrderEntity); + + return confirmEviction; + } + + private EnforcementOrderEntity retrieveEnforcementOrderEntity(long caseReference) { + Set enforcementOrders = getEnforcementOrderEntities(caseReference); + if (enforcementOrders.isEmpty()) { + return null; + } + return enforcementOrders.stream().findFirst().orElse(null); } private EnforcementOrderEntity mapToEntity(EnforcementOrder enforcementOrder, ClaimEntity claimEntity) { diff --git a/src/main/resources/db/migration/V075__enforcement_confirm_eviction.sql b/src/main/resources/db/migration/V075__enforcement_confirm_eviction.sql new file mode 100644 index 0000000000..33e1555df3 --- /dev/null +++ b/src/main/resources/db/migration/V075__enforcement_confirm_eviction.sql @@ -0,0 +1,49 @@ +CREATE TABLE enf_eviction( + id UUID PRIMARY KEY, + enf_case_id UUID NOT NULL REFERENCES enf_case (id) ON DELETE CASCADE, + + -- The eviction date + eviction_date_confirmed YES_NO NOT NULL, + + -- Dates when you can not attend an eviction + has_unavailable_dates YES_NO NOT NULL, + + -- separate table for dates unavailable table + + -- Contact for Bailiff + before_eviction_name_or_department VARCHAR(100), + before_eviction_telephone_number VARCHAR(20), + before_eviction_email_address VARCHAR(60), + + after_eviction_name_or_department VARCHAR(100), + after_eviction_telephone_number VARCHAR(20), + after_eviction_email_address VARCHAR(60), + + -- access to the property + difficult_to_access YES_NO, + difficult_to_access_details VARCHAR(6800), + + -- Anything else that could help with the eviction + anything_else YES_NO, + anything_else_details VARCHAR(6800), + + -- Gaining access to and securing the property after the eviction + confirm_arrangement_for_access YES_NO, + + language_used VARCHAR(30), + created TIMESTAMP WITHOUT TIME ZONE NOT NULL, + + CONSTRAINT unique_confirm_eviction_per_enforcement UNIQUE(enf_case_id) +); + +ALTER TABLE enf_risk_profile + ADD COLUMN physical_description_of_risk_defendant YES_NO; + +ALTER TABLE enf_risk_profile + ADD COLUMN physical_description_of_risk_defendant_details VARCHAR(6800); + +CREATE TABLE enf_unavailable_date ( + id UUID PRIMARY KEY, + enf_eviction_id UUID NOT NULL REFERENCES enf_eviction (id) ON DELETE CASCADE, + unavailable_date DATE NOT NULL +); diff --git a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/enforcetheorder/EnforcementOrderServiceTest.java b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/enforcetheorder/EnforcementOrderServiceTest.java index 5b7635b31c..b11f20c2ad 100644 --- a/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/enforcetheorder/EnforcementOrderServiceTest.java +++ b/src/test/java/uk/gov/hmcts/reform/pcs/ccd/service/enforcetheorder/EnforcementOrderServiceTest.java @@ -10,8 +10,10 @@ 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.confirmeviction.EvictionEntity; import uk.gov.hmcts.reform.pcs.ccd.entity.enforcetheorder.EnforcementOrderEntity; import uk.gov.hmcts.reform.pcs.ccd.event.EventId; +import uk.gov.hmcts.reform.pcs.ccd.repository.enforcetheorder.EvictionRepository; import uk.gov.hmcts.reform.pcs.ccd.repository.enforcetheorder.EnforcementOrderRepository; import uk.gov.hmcts.reform.pcs.ccd.service.DraftCaseDataService; import uk.gov.hmcts.reform.pcs.ccd.service.PcsCaseService; @@ -23,6 +25,7 @@ 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.ArgumentMatchers.anyLong; import static org.mockito.Mockito.mock; @@ -42,8 +45,10 @@ class EnforcementOrderServiceTest { private PcsCaseService pcsCaseService; @Mock private EnforcementTypeStrategyFactory strategyFactory; + @Mock + private EvictionRepository evictionRepository; @InjectMocks - private EnforcementOrderService enforcementOrderService; + private EnforcementOrderService underTest; @Captor private ArgumentCaptor enforcementOrderEntityCaptor; @@ -66,7 +71,7 @@ void shouldReturnEnforcementOrderIfFoundInDatabase() { claimEntity.setEnforcementOrders(Set.of(enforcementOrderEntity)); when(pcsCaseService.loadCase(CASE_REFERENCE)).thenReturn(pcsCaseEntity); // When - EnforcementOrder retOrder = enforcementOrderService.retrieveEnforcementOrder(CASE_REFERENCE, WARRANT); + EnforcementOrder retOrder = underTest.retrieveEnforcementOrder(CASE_REFERENCE, WARRANT); // Then assertThat(retOrder).isNotNull(); @@ -81,7 +86,7 @@ void shouldReturnNullIfNotFoundInDatabase() { when(pcsCaseService.loadCase(CASE_REFERENCE)).thenReturn(pcsCaseEntity); // When - EnforcementOrder retOrder = enforcementOrderService.retrieveEnforcementOrder(CASE_REFERENCE, WARRANT); + EnforcementOrder retOrder = underTest.retrieveEnforcementOrder(CASE_REFERENCE, WARRANT); // Then assertThat(retOrder).isNull(); @@ -96,12 +101,53 @@ void shouldReturnFirstClaimFromPcsCaseEntity() { pcsCaseEntity.setClaims(List.of(firstClaim, secondClaim)); // When - ClaimEntity result = enforcementOrderService.retrieveClaimEntity(pcsCaseEntity); + ClaimEntity result = underTest.retrieveClaimEntity(pcsCaseEntity); // Then assertThat(result).isSameAs(firstClaim); } + @Test + void shouldReturnNullWhenNoClaimEntitiesPresent() { + // Given + final PcsCaseEntity pcsCaseEntity = new PcsCaseEntity(); + pcsCaseEntity.setClaims(List.of()); + + // When + ClaimEntity result = underTest.retrieveClaimEntity(pcsCaseEntity); + + // Then + assertThat(result).isNull(); + } + + @Test + void shouldReturnNullWhenNoClaimEntityOnRetrieveEnforcementOrder() { + // Given + final PcsCaseEntity pcsCaseEntity = new PcsCaseEntity(); + pcsCaseEntity.setClaims(List.of()); + when(pcsCaseService.loadCase(CASE_REFERENCE)).thenReturn(pcsCaseEntity); + + // When + EnforcementOrder result = underTest.retrieveEnforcementOrder(CASE_REFERENCE, WARRANT); + + // Then + assertThat(result).isNull(); + } + + @Test + void shouldThrowWhenSavingWithNoClaimEntityPresent() { + // Given + final PcsCaseEntity pcsCaseEntity = new PcsCaseEntity(); + pcsCaseEntity.setClaims(List.of()); + when(pcsCaseService.loadCase(CASE_REFERENCE)).thenReturn(pcsCaseEntity); + + // When / Then + assertThatThrownBy( + () -> underTest.saveAndClearDraftData(CASE_REFERENCE, new EnforcementOrder()) + ).isInstanceOf(IllegalStateException.class) + .hasMessageContaining("no claim entity exists"); + } + @Test void shouldSaveNewSubmittedEnforcementData() { // Given @@ -115,7 +161,7 @@ void shouldSaveNewSubmittedEnforcementData() { .thenReturn(mock(EnforcementTypeStrategy.class)); // When - enforcementOrderService.saveAndClearDraftData(CASE_REFERENCE, enforcementOrder); + underTest.saveAndClearDraftData(CASE_REFERENCE, enforcementOrder); // Then verify(enforcementOrderRepository).save(enforcementOrderEntityCaptor.capture()); @@ -124,4 +170,54 @@ void shouldSaveNewSubmittedEnforcementData() { verify(draftCaseDataService).deleteUnsubmittedCaseData(anyLong(), any(EventId.class)); } + @Test + void shouldConfirmEviction() { + // Given + PcsCaseEntity pcsCaseEntity = mock(PcsCaseEntity.class); + when(pcsCaseService.loadCase(anyLong())).thenReturn(pcsCaseEntity); + ClaimEntity claimEntity = mock(ClaimEntity.class); + when(pcsCaseEntity.getClaims()).thenReturn(List.of(claimEntity)); + EnforcementOrderEntity enforcementOrderEntity = mock(EnforcementOrderEntity.class); + when(claimEntity.getEnforcementOrders()).thenReturn(Set.of(enforcementOrderEntity)); + + // When + underTest.confirmEviction(CASE_REFERENCE); + + // Then + verify(evictionRepository).save(any(EvictionEntity.class)); + } + + @Test + void shouldReturnEmptySetWhenNoClaimEntityFound() { + // Given + final PcsCaseEntity pcsCaseEntity = new PcsCaseEntity(); + pcsCaseEntity.setClaims(List.of()); + when(pcsCaseService.loadCase(CASE_REFERENCE)).thenReturn(pcsCaseEntity); + + // When + Set result = underTest.getEnforcementOrderEntities(CASE_REFERENCE); + + // Then + assertThat(result).isEmpty(); + } + + @Test + void shouldReturnEnforcementOrdersFromClaimEntity() { + // Given + final PcsCaseEntity pcsCaseEntity = new PcsCaseEntity(); + ClaimEntity claimEntity = new ClaimEntity(); + EnforcementOrderEntity enforcementOrderEntity1 = new EnforcementOrderEntity(); + EnforcementOrderEntity enforcementOrderEntity2 = new EnforcementOrderEntity(); + Set enforcementOrders = Set.of(enforcementOrderEntity1, enforcementOrderEntity2); + claimEntity.setEnforcementOrders(enforcementOrders); + pcsCaseEntity.setClaims(List.of(claimEntity)); + when(pcsCaseService.loadCase(CASE_REFERENCE)).thenReturn(pcsCaseEntity); + + // When + Set result = underTest.getEnforcementOrderEntities(CASE_REFERENCE); + + // Then + assertThat(result).containsExactlyInAnyOrder(enforcementOrderEntity1, enforcementOrderEntity2); + } + }