Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DMP-3534: Retention Confidence #2382

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
Expand All @@ -13,28 +15,33 @@
import uk.gov.hmcts.darts.common.entity.EventEntity;
import uk.gov.hmcts.darts.common.entity.HearingEntity;
import uk.gov.hmcts.darts.common.entity.MediaEntity;
import uk.gov.hmcts.darts.common.helper.CurrentTimeHelper;
import uk.gov.hmcts.darts.common.util.DateConverterUtil;
import uk.gov.hmcts.darts.retention.enums.CaseRetentionStatus;
import uk.gov.hmcts.darts.retention.enums.RetentionConfidenceCategoryEnum;
import uk.gov.hmcts.darts.retention.enums.RetentionConfidenceReasonEnum;
import uk.gov.hmcts.darts.retention.enums.RetentionConfidenceScoreEnum;
import uk.gov.hmcts.darts.test.common.data.PersistableFactory;
import uk.gov.hmcts.darts.test.common.data.RetentionConfidenceCategoryMapperTestData;
import uk.gov.hmcts.darts.test.common.data.builder.TestRetentionConfidenceCategoryMapperEntity;
import uk.gov.hmcts.darts.testutils.IntegrationBase;
import uk.gov.hmcts.darts.testutils.stubs.DartsPersistence;

import java.time.Clock;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.Optional;
import java.util.UUID;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.lenient;

@Slf4j
@SpringBootTest(properties = "spring.main.allow-bean-definition-overriding=true") // To override Clock bean
class CloseOldCasesProcessorTest extends IntegrationBase {
@Autowired
CloseOldCasesProcessor closeOldCasesProcessor;
Expand All @@ -44,8 +51,16 @@ class CloseOldCasesProcessorTest extends IntegrationBase {
private static final String REQUESTER_EMAIL = "test.user@example.com";
private static final OffsetDateTime CURRENT_DATE_TIME = OffsetDateTime.of(2024, 10, 1, 10, 0, 0, 0, ZoneOffset.UTC);

@MockBean
private CurrentTimeHelper currentTimeHelper;
@Autowired
private DartsPersistence dartsPersistence;

@TestConfiguration
public static class ClockConfig {
@Bean
public Clock clock() {
return Clock.fixed(CURRENT_DATE_TIME.toInstant(), ZoneOffset.UTC);
}
}

@BeforeEach
void beforeEach() {
Expand All @@ -56,12 +71,23 @@ void beforeEach() {
.build();
SecurityContextHolder.getContext().setAuthentication(new JwtAuthenticationToken(jwt));
dartsDatabase.createTestUserAccount();
}

lenient().when(currentTimeHelper.currentOffsetDateTime()).thenReturn(CURRENT_DATE_TIME);
private void createAndSaveRetentionConfidenceCategoryMappings() {
RetentionConfidenceCategoryMapperTestData testData = PersistableFactory.getRetentionConfidenceCategoryMapperTestData();

TestRetentionConfidenceCategoryMapperEntity agedCaseMappingEntity = testData.someMinimalBuilder()
.confidenceCategory(RetentionConfidenceCategoryEnum.AGED_CASE)
.confidenceReason(RetentionConfidenceReasonEnum.AGED_CASE)
.confidenceScore(RetentionConfidenceScoreEnum.CASE_NOT_PERFECTLY_CLOSED)
.build();
dartsPersistence.save(agedCaseMappingEntity.getEntity());
}

@Test
void givenClosedEventsUseDateAsClosedDate() {
createAndSaveRetentionConfidenceCategoryMappings();

HearingEntity hearing = dartsDatabase.createHearing("a_courthouse", "1", "1078", LocalDateTime.now().minusYears(7).plusMonths(3));

OffsetDateTime closeDate = OffsetDateTime.now().minusYears(7);
Expand Down Expand Up @@ -95,8 +121,51 @@ void givenClosedEventsUseDateAsClosedDate() {
assertEquals(RetentionConfidenceCategoryEnum.AGED_CASE, caseRetentionEntity.getConfidenceCategory());
}

@Test
void closeCases_shouldCloseCases_andUseDateAsClosedDate_andSetNullConfidenceReasonAndScore_whenNoConfidenceMappingExists() {
// Given createAndSaveRetentionConfidenceCategoryMappings() is not invoked, so no confidence mappings exist in the DB
jackmaloney marked this conversation as resolved.
Show resolved Hide resolved

// And
HearingEntity hearing = dartsDatabase.createHearing("a_courthouse", "1", "1078", LocalDateTime.now().minusYears(7).plusMonths(3));

OffsetDateTime expectedCloseDate = OffsetDateTime.now().minusYears(7);

Integer someEventHandlerId = dartsPersistence.getEventHandlerRepository().findAll().getFirst().getId();
EventEntity eventEntity = dartsDatabase.getEventStub().createEvent(hearing, someEventHandlerId);
eventEntity.setCreatedDateTime(expectedCloseDate);
dartsDatabase.save(eventEntity);

CourtCaseEntity courtCaseEntity = hearing.getCourtCase();
courtCaseEntity.setCreatedDateTime(expectedCloseDate.minusYears(3));
dartsDatabase.getCaseRepository().save(courtCaseEntity);
assertFalse(courtCaseEntity.getClosed());

// When
closeOldCasesProcessor.closeCases(BATCH_SIZE);

// Then
Optional<CourtCaseEntity> updatedCourtCaseEntityOptional = dartsDatabase.getCaseRepository()
.findById(courtCaseEntity.getId());

assertTrue(updatedCourtCaseEntityOptional.isPresent());
CourtCaseEntity updatedCourtCaseEntity = updatedCourtCaseEntityOptional.get();

assertTrue(updatedCourtCaseEntity.getClosed());
assertEquals(expectedCloseDate.truncatedTo(ChronoUnit.MINUTES),
updatedCourtCaseEntity.getCaseClosedTimestamp().truncatedTo(ChronoUnit.MINUTES));
assertNull(updatedCourtCaseEntity.getRetConfScore());
assertNull(updatedCourtCaseEntity.getRetConfReason());
assertEquals(CURRENT_DATE_TIME, updatedCourtCaseEntity.getRetConfUpdatedTs());

CaseRetentionEntity caseRetentionEntity = dartsDatabase.getCaseRetentionRepository()
.findAll().getFirst();
assertEquals(RetentionConfidenceCategoryEnum.AGED_CASE, caseRetentionEntity.getConfidenceCategory());
}

@Test
void givenEventsUseLatestDateAsClosedDate() {
createAndSaveRetentionConfidenceCategoryMappings();

HearingEntity hearing = dartsDatabase.createHearing("a_courthouse", "1", "1078", LocalDateTime.now().minusYears(7));

OffsetDateTime closeDate = OffsetDateTime.now().minusYears(7);
Expand Down Expand Up @@ -129,6 +198,8 @@ void givenEventsUseLatestDateAsClosedDate() {

@Test
void givenOneEventUseLatestDateAsClosedDate() {
createAndSaveRetentionConfidenceCategoryMappings();

HearingEntity hearing = dartsDatabase.createHearing("a_courthouse", "1", "1078", LocalDateTime.now().minusYears(7));

OffsetDateTime closeDate = OffsetDateTime.now().minusYears(7);
Expand Down Expand Up @@ -159,6 +230,8 @@ void givenOneEventUseLatestDateAsClosedDate() {

@Test
void givenAudioUseDateAsClosedDate() {
createAndSaveRetentionConfidenceCategoryMappings();

OffsetDateTime closeDate = OffsetDateTime.now().minusYears(6).plusDays(2);
MediaEntity mediaEntity1 = dartsDatabase.createMediaEntity("acourthosue", "1",
OffsetDateTime.now().minusYears(7), OffsetDateTime.now().minusYears(7).plusMinutes(20), 1);
Expand Down Expand Up @@ -198,6 +271,8 @@ void givenAudioUseDateAsClosedDate() {

@Test
void givenOnlyHearingUseDateAsClosedDate() {
createAndSaveRetentionConfidenceCategoryMappings();

LocalDateTime closeDate = DateConverterUtil.toLocalDateTime(OffsetDateTime.now().minusYears(7));
dartsDatabase.createHearing("a_courthouse", "1", "1078", closeDate.minusDays(10));
HearingEntity hearing = dartsDatabase.createHearing("a_courthouse", "1", "1078", closeDate);
Expand All @@ -224,6 +299,8 @@ void givenOnlyHearingUseDateAsClosedDate() {

@Test
void givenNoDataUseCreatedDateAsClosedDate() {
createAndSaveRetentionConfidenceCategoryMappings();

OffsetDateTime closeDate = OffsetDateTime.now().minusYears(7);
CourtCaseEntity courtCaseEntity = dartsDatabase.createCase("a_courthouse", "019278");
courtCaseEntity.setCreatedDateTime(closeDate);
Expand All @@ -245,6 +322,8 @@ void givenNoDataUseCreatedDateAsClosedDate() {

@Test
void givenNoDataUseCreatedDateAsClosedDateUseBatchSizeTwo() {
createAndSaveRetentionConfidenceCategoryMappings();

// given
OffsetDateTime closeDate1 = OffsetDateTime.now().minusYears(9);
CourtCaseEntity courtCaseEntity1 = dartsDatabase.createCase("a_courthouse", "019278");
Expand Down Expand Up @@ -290,6 +369,8 @@ void givenNoDataUseCreatedDateAsClosedDateUseBatchSizeTwo() {

@Test
void givenRetentionPolicyDoNotClose() {
createAndSaveRetentionConfidenceCategoryMappings();

CourtCaseEntity courtCaseEntity = dartsDatabase.createCase("a_courthouse", "019278");
courtCaseEntity.setCreatedDateTime(OffsetDateTime.now().minusYears(7));
dartsDatabase.getCaseRepository().save(courtCaseEntity);
Expand All @@ -313,6 +394,8 @@ void givenRetentionPolicyDoNotClose() {

@Test
void givenNotSixYearsOldDoNotClose() {
createAndSaveRetentionConfidenceCategoryMappings();

CourtCaseEntity courtCaseEntity = dartsDatabase.createCase("a_courthouse", "019278");
courtCaseEntity.setCreatedDateTime(OffsetDateTime.now().minusYears(5).minusDays(360));
dartsDatabase.getCaseRepository().save(courtCaseEntity);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
package uk.gov.hmcts.darts.common.repository;

import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.IncorrectResultSizeDataAccessException;
import uk.gov.hmcts.darts.common.entity.RetentionConfidenceCategoryMapperEntity;
import uk.gov.hmcts.darts.retention.enums.RetentionConfidenceCategoryEnum;
import uk.gov.hmcts.darts.retention.enums.RetentionConfidenceReasonEnum;
import uk.gov.hmcts.darts.retention.enums.RetentionConfidenceScoreEnum;
import uk.gov.hmcts.darts.test.common.data.PersistableFactory;
import uk.gov.hmcts.darts.test.common.data.RetentionConfidenceCategoryMapperTestData;
import uk.gov.hmcts.darts.test.common.data.builder.TestRetentionConfidenceCategoryMapperEntity;
import uk.gov.hmcts.darts.testutils.PostgresIntegrationBase;

import java.sql.SQLException;
import java.util.Optional;
import javax.sql.DataSource;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;

public class RetentionConfidenceCategoryMapperRepositoryTest extends PostgresIntegrationBase {

@Autowired
private RetentionConfidenceCategoryMapperRepository repository;

@Autowired
private DataSource dataSource;

private static final RetentionConfidenceCategoryMapperTestData CATEGORY_MAPPER_TEST_DATA =
PersistableFactory.getRetentionConfidenceCategoryMapperTestData();


@Nested
class SaveTest {

@Test
@SuppressWarnings("PMD.CheckResultSet")
void shouldSaveEntity_withStringValueForReason_andNumericsForCategoryAndScore() throws SQLException {
// Given
TestRetentionConfidenceCategoryMapperEntity mapperTestEntity = CATEGORY_MAPPER_TEST_DATA.someMinimalBuilder()
.confidenceCategory(RetentionConfidenceCategoryEnum.MANUAL_OVERRIDE)
.confidenceReason(RetentionConfidenceReasonEnum.MANUAL_OVERRIDE)
.confidenceScore(RetentionConfidenceScoreEnum.CASE_PERFECTLY_CLOSED)
.build();

// When
var preparedEntity = dartsPersistence.save(mapperTestEntity.getEntity());

// Then
String query = "SELECT confidence_category, ret_conf_reason, ret_conf_score FROM retention_confidence_category_mapper WHERE rcc_id = ?";
try (var connection = dataSource.getConnection();
var preparedStatement = connection.prepareStatement(query)) {
preparedStatement.setInt(1, preparedEntity.getId());
try (var resultSet = preparedStatement.executeQuery()) {
assertTrue(resultSet.next());

assertEquals(RetentionConfidenceReasonEnum.MANUAL_OVERRIDE.name(), resultSet.getString("ret_conf_reason"));
assertEquals(RetentionConfidenceCategoryEnum.MANUAL_OVERRIDE.getId(), resultSet.getInt("confidence_category"));
assertEquals(RetentionConfidenceScoreEnum.CASE_PERFECTLY_CLOSED.getId(), resultSet.getInt("ret_conf_score"));
}
}
}

}

@Nested
class FindByConfidenceCategoryTest {

@Test
void shouldReturnSingleResult_whenSingleMatchExists() {
// Given
RetentionConfidenceCategoryEnum category = RetentionConfidenceCategoryEnum.CASE_CLOSED;

TestRetentionConfidenceCategoryMapperEntity mapperTestEntity = CATEGORY_MAPPER_TEST_DATA.someMinimalBuilder()
.confidenceCategory(category)
.build();

var preparedEntity = dartsPersistence.save(mapperTestEntity.getEntity());

// When
Optional<RetentionConfidenceCategoryMapperEntity> returnedEntity = repository.findByConfidenceCategory(category);

// Then
assertTrue(returnedEntity.isPresent());
var result = returnedEntity.get();
assertEquals(preparedEntity.getId(), result.getId());
}

@Test
void shouldThrowException_whenMultipleMatchesExist() {
// Given
RetentionConfidenceCategoryEnum category = RetentionConfidenceCategoryEnum.CASE_CLOSED;

TestRetentionConfidenceCategoryMapperEntity mapperTestEntity1 = CATEGORY_MAPPER_TEST_DATA.someMinimalBuilder()
.confidenceCategory(category)
.build();
dartsPersistence.save(mapperTestEntity1.getEntity());

TestRetentionConfidenceCategoryMapperEntity mapperTestEntity2 = CATEGORY_MAPPER_TEST_DATA.someMinimalBuilder()
.confidenceCategory(category)
.build();
dartsPersistence.save(mapperTestEntity2.getEntity());

// When
IncorrectResultSizeDataAccessException exception = assertThrows(IncorrectResultSizeDataAccessException.class, () ->
repository.findByConfidenceCategory(category));
assertEquals("Query did not return a unique result: 2 results were returned", exception.getMessage());
}

@Test
void shouldReturnEmptyOptional_whenNoMatchExists() {
Optional<RetentionConfidenceCategoryMapperEntity> result = repository.findByConfidenceCategory(RetentionConfidenceCategoryEnum.CASE_CLOSED);

assertFalse(result.isPresent());
}

@Test
void shouldReturnEmptyOptional_whenProvidedWithNullParam() {
Optional<RetentionConfidenceCategoryMapperEntity> result = repository.findByConfidenceCategory(null);

assertFalse(result.isPresent());
}

}

}
Loading
Loading