diff --git a/crime-evidence/build.gradle b/crime-evidence/build.gradle index a1aa446..0710a37 100644 --- a/crime-evidence/build.gradle +++ b/crime-evidence/build.gradle @@ -15,7 +15,7 @@ jacoco { def versions = [ pitest : "1.16.0", - crimeCommonsClasses : "3.28.0", + crimeCommonsClasses : "3.29.3", commonsModSchemas : "1.8.0", commonsRestClient : "3.4.0", wmStubRunnerVersion : "4.1.2", diff --git a/crime-evidence/src/main/java/uk/gov/justice/laa/crime/evidence/dto/EvidenceDTO.java b/crime-evidence/src/main/java/uk/gov/justice/laa/crime/evidence/dto/EvidenceDTO.java new file mode 100644 index 0000000..592f900 --- /dev/null +++ b/crime-evidence/src/main/java/uk/gov/justice/laa/crime/evidence/dto/EvidenceDTO.java @@ -0,0 +1,23 @@ +package uk.gov.justice.laa.crime.evidence.dto; + +import lombok.Builder; +import lombok.Data; + +import java.time.LocalDateTime; + +@Data +@Builder +public class EvidenceDTO { + /** + * This is a basic DTO with the required fields for validation. When we migrate the remaining logic + * we can update this DTO with any additional fields we need + */ + private LocalDateTime incomeEvidenceReceivedDate; + private LocalDateTime applicationReceivedDate; + private String incomeExtraEvidence; + private String incomeExtraEvidenceText; + private LocalDateTime evidenceDueDate; + private LocalDateTime firstReminderDate; + private LocalDateTime secondReminderDate; + private LocalDateTime existingEvidenceDueDate; +} diff --git a/crime-evidence/src/main/java/uk/gov/justice/laa/crime/evidence/service/IncomeEvidenceValidationService.java b/crime-evidence/src/main/java/uk/gov/justice/laa/crime/evidence/service/IncomeEvidenceValidationService.java new file mode 100644 index 0000000..7077637 --- /dev/null +++ b/crime-evidence/src/main/java/uk/gov/justice/laa/crime/evidence/service/IncomeEvidenceValidationService.java @@ -0,0 +1,61 @@ +package uk.gov.justice.laa.crime.evidence.service; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; +import uk.gov.justice.laa.crime.evidence.dto.EvidenceDTO; +import uk.gov.justice.laa.crime.evidence.staticdata.enums.OtherEvidenceTypes; +import uk.gov.justice.laa.crime.util.DateUtil; + +import java.util.Date; + +@Slf4j +@Service +@RequiredArgsConstructor +public class IncomeEvidenceValidationService { + + public void validate(EvidenceDTO evidenceDTO){ + checkExtraEvidenceDescription(evidenceDTO.getIncomeExtraEvidence(), + evidenceDTO.getIncomeExtraEvidenceText()); + checkEvidenceReceivedDate(DateUtil.toDate(evidenceDTO.getIncomeEvidenceReceivedDate()), + DateUtil.toDate(evidenceDTO.getApplicationReceivedDate())); + checkEvidenceDueDates(DateUtil.toDate(evidenceDTO.getEvidenceDueDate()), + DateUtil.toDate(evidenceDTO.getFirstReminderDate()), + DateUtil.toDate(evidenceDTO.getSecondReminderDate()), + DateUtil.toDate(evidenceDTO.getExistingEvidenceDueDate())); + } + + public void checkEvidenceReceivedDate(Date incomeEvidenceReceivedDate, Date applicationReceivedDate) { + Date currentDate = DateUtil.getCurrentDate(); + if (incomeEvidenceReceivedDate != null && incomeEvidenceReceivedDate.after(currentDate)) { + throw new IllegalArgumentException("Income evidence received date cannot be in the future"); + } + + if (incomeEvidenceReceivedDate != null && incomeEvidenceReceivedDate.before(applicationReceivedDate)) { + throw new IllegalArgumentException("Income evidence received date cannot be before application date received"); + } + } + + + public void checkExtraEvidenceDescription(String incomeExtraEvidence, String incomeExtraEvidenceText) { + if (OtherEvidenceTypes.getFrom(incomeExtraEvidence) != null && StringUtils.isBlank(incomeExtraEvidenceText)) { + throw new IllegalArgumentException("When other evidence is requested, you must provide descriptive text."); + } + } + + + public void checkEvidenceDueDates(Date evidenceDueDate, Date firstReminderDate, Date secondReminderDate, + Date existingEvidenceDueDate) { + Date currentDate = DateUtil.getCurrentDate(); + if ((evidenceDueDate == null && existingEvidenceDueDate != null) && ( + firstReminderDate != null || secondReminderDate != null)) { + throw new IllegalArgumentException("Evidence due date cannot be null"); + } + + if (evidenceDueDate != null && evidenceDueDate.before(currentDate) + && (!evidenceDueDate.equals(existingEvidenceDueDate))) { + throw new IllegalArgumentException("Cannot set due date in the past."); + } + } +} diff --git a/crime-evidence/src/main/java/uk/gov/justice/laa/crime/evidence/staticdata/enums/OtherEvidenceTypes.java b/crime-evidence/src/main/java/uk/gov/justice/laa/crime/evidence/staticdata/enums/OtherEvidenceTypes.java new file mode 100644 index 0000000..ee74599 --- /dev/null +++ b/crime-evidence/src/main/java/uk/gov/justice/laa/crime/evidence/staticdata/enums/OtherEvidenceTypes.java @@ -0,0 +1,26 @@ +package uk.gov.justice.laa.crime.evidence.staticdata.enums; + +import lombok.Getter; +import lombok.AllArgsConstructor; +import org.apache.commons.lang3.StringUtils; + +import java.util.stream.Stream; + +@Getter +@AllArgsConstructor +public enum OtherEvidenceTypes { + OTHER("OTHER"), + OTHER_BUSINESS("OTHER BUSINESS"), + OTHER_ADHOC("OTHER_ADHOC"); + + private final String evidence; + + public static OtherEvidenceTypes getFrom(String type) { + if (StringUtils.isBlank(type)) return null; + + return Stream.of(OtherEvidenceTypes.values()) + .filter(ie -> ie.evidence.equals(type)) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException(String.format("Evidence Type: %s does not exist.", type))); + } +} diff --git a/crime-evidence/src/test/java/uk/gov/justice/laa/crime/evidence/service/IncomeEvidenceValidationServiceTest.java b/crime-evidence/src/test/java/uk/gov/justice/laa/crime/evidence/service/IncomeEvidenceValidationServiceTest.java new file mode 100644 index 0000000..f70a750 --- /dev/null +++ b/crime-evidence/src/test/java/uk/gov/justice/laa/crime/evidence/service/IncomeEvidenceValidationServiceTest.java @@ -0,0 +1,233 @@ +package uk.gov.justice.laa.crime.evidence.service; + +import org.assertj.core.api.SoftAssertions; +import org.assertj.core.api.junit.jupiter.InjectSoftAssertions; +import org.assertj.core.api.junit.jupiter.SoftAssertionsExtension; +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.justice.laa.crime.evidence.dto.EvidenceDTO; +import uk.gov.justice.laa.crime.util.DateUtil; + +import java.time.LocalDate; +import java.util.Date; + +import static org.junit.jupiter.api.Assertions.assertThrows; + +@ExtendWith(MockitoExtension.class) +@ExtendWith(SoftAssertionsExtension.class) +class IncomeEvidenceValidationServiceTest { + + @Mock + private MaatCourtDataService maatCourtDataService; + + @InjectMocks + private IncomeEvidenceValidationService incomeEvidenceValidationService; + + @InjectSoftAssertions + private SoftAssertions softly; + + @Test + void givenValidDates_whenCheckEvidenceReceivedDateIsInvoked_noExceptionIsThrown() { + incomeEvidenceValidationService.checkEvidenceReceivedDate(new Date(), new Date()); + } + + @Test + void givenValidDates_whenCheckEvidenceReceivedDateIsInvokedWithIncomeEvidenceReceivedDateNull_noExceptionIsThrown() { + incomeEvidenceValidationService.checkEvidenceReceivedDate(null, new Date()); + } + + @Test + void givenValidDates_whenCheckEvidenceReceivedDateIsInvokedWithIncomeEvidenceReceivedDateAfterCurrentDate_thenExceptionIsThrown() { + LocalDate futureDate = LocalDate.now().plusMonths(2); + Date convertedFutureDate = DateUtil.asDate(futureDate); + Date currentDate = new Date(); + assertThrows(IllegalArgumentException.class, () -> + incomeEvidenceValidationService.checkEvidenceReceivedDate(convertedFutureDate, currentDate) + ); + } + + @Test + void givenValidDates_whenCheckEvidenceReceivedDateIsInvokedWithIncomeEvidenceReceivedDateBeforeCurrentDate_ExceptionIsThrown() { + LocalDate pastDate = LocalDate.now().minusMonths(2); + Date pastDateConverted = DateUtil.asDate(pastDate); + Date currentDate = new Date(); + assertThrows(IllegalArgumentException.class, () -> + incomeEvidenceValidationService.checkEvidenceReceivedDate(pastDateConverted, currentDate) + ); + } + + @Test + void givenIncomeExtraEvidenceReceivedDate_whenCheckExtraEvidenceDescriptionIsInvoked_thenNoExceptionIsThrown() { + incomeEvidenceValidationService.checkExtraEvidenceDescription("OTHER", "Some text"); + } + + @Test + void givenIncomeExtraEvidenceReceivedDate_whenCheckExtraEvidenceDescriptionIsInvokedWithIncomeExtraEvidenceTextNull_thenExceptionIsThrown() { + assertThrows(IllegalArgumentException.class, () -> { + incomeEvidenceValidationService.checkExtraEvidenceDescription("OTHER", null); + }); + } + + @Test + void givenIncomeExtraEvidenceReceivedDate_whenCheckExtraEvidenceDescriptionIsInvokedWithIncomeExtraEvidenceTextEmpty_thenExceptionIsThrown() { + assertThrows(IllegalArgumentException.class, () -> { + incomeEvidenceValidationService.checkExtraEvidenceDescription("OTHER", ""); + }); + } + + @Test + void givenIncomeExtraEvidenceReceivedDate_whenCheckExtraEvidenceDescriptionIsInvokedWithIncomeExtraEvidenceTextBlank_thenExceptionIsThrown() { + assertThrows(IllegalArgumentException.class, () -> { + incomeEvidenceValidationService.checkExtraEvidenceDescription("OTHER", " "); + }); + } + + @Test + void givenIncomeExtraEvidenceReceivedDate_whenCheckExtraEvidenceDescriptionIsInvokedWithIncomeExtraEvidenceNull_thenNoExceptionIsThrown() { + incomeEvidenceValidationService.checkExtraEvidenceDescription(null, "Some text"); + } + + @Test + void givenIncomeExtraEvidenceReceivedDate_whenCheckExtraEvidenceDescriptionIsInvokedWithIncomeExtraEvidenceEmpty_thenNoExceptionIsThrown() { + incomeEvidenceValidationService.checkExtraEvidenceDescription("", "Some text"); + } + + @Test + void givenIncomeExtraEvidenceReceivedDate_whenCheckExtraEvidenceDescriptionIsInvokedWithIncomeExtraEvidenceBlank_thenNoExceptionIsThrown() { + incomeEvidenceValidationService.checkExtraEvidenceDescription(" ", "Some text"); + } + + @Test + void givenValidDates_whenCheckEvidenceDueDatesIsInvoked_thenNoExceptionIsThrown() { + incomeEvidenceValidationService.checkEvidenceDueDates(new Date(), new Date(), new Date(), new Date()); + } + + @Test + void givenValidDates_whenCheckEvidenceDueDatesIsInvokedWithEvidenceDueDateNull_thenExceptionIsThrown() { + Date currentDate = new Date(); + assertThrows(IllegalArgumentException.class, () -> + incomeEvidenceValidationService.checkEvidenceDueDates(null, currentDate, currentDate, currentDate) + ); + } + + @Test + void givenValidDates_whenCheckEvidenceDueDatesIsInvokedWithEvidenceDueDateAfterCurrentDate_thenNoExceptionIsThrown() { + LocalDate futureDate = LocalDate.now().plusMonths(2); + Date futureDateConverted = DateUtil.asDate(futureDate); + Date currentDate = new Date(); + incomeEvidenceValidationService.checkEvidenceDueDates(futureDateConverted, currentDate, currentDate, currentDate); + } + + @Test + void givenValidDates_whenCheckEvidenceDueDatesIsInvokedWithEvidenceDueDateBeforeCurrentDate_thenExceptionIsThrown() { + LocalDate pastDate = LocalDate.now().minusMonths(2); + Date pastDateConverted = DateUtil.asDate(pastDate); + Date currentDate1 = new Date(); + Date currentDate2 = new Date(); + Date currentDate3 = new Date(); + assertThrows(IllegalArgumentException.class, () -> + incomeEvidenceValidationService.checkEvidenceDueDates(pastDateConverted, currentDate1, currentDate2, currentDate3) + ); + } + + @Test + void givenValidDates_whenCheckEvidenceDueDatesIsInvokedWithFirstReminderDateNull_thenNoExceptionIsThrown() { + incomeEvidenceValidationService.checkEvidenceDueDates(new Date(), null, new Date(), new Date()); + } + + @Test + void givenValidDates_whenCheckEvidenceDueDatesIsInvokedWithFirstReminderDateAfterCurrentDate_thenNoExceptionIsThrown() { + LocalDate futureDate = LocalDate.now().plusMonths(2); + Date currentDate1 = new Date(); + Date futureDateConverted = DateUtil.asDate(futureDate); + Date currentDate2 = new Date(); + Date currentDate3 = new Date(); + incomeEvidenceValidationService.checkEvidenceDueDates(currentDate1, futureDateConverted, currentDate2, currentDate3); + } + + @Test + void givenValidDates_whenCheckEvidenceDueDatesIsInvokedWithFirstReminderDateBeforeCurrentDate_thenNoExceptionIsThrown() { + LocalDate pastDate = LocalDate.now().minusMonths(2); + Date currentDate1 = new Date(); + Date pastDateConverted = DateUtil.asDate(pastDate); + Date currentDate2 = new Date(); + Date currentDate3 = new Date(); + incomeEvidenceValidationService.checkEvidenceDueDates(currentDate1, pastDateConverted, currentDate2, currentDate3); + } + + @Test + void givenValidDates_whenCheckEvidenceDueDatesIsInvokedWithSecondReminderDateNull_thenExceptionIsThrown() { + incomeEvidenceValidationService.checkEvidenceDueDates(new Date(), new Date(), null, new Date()); + } + + @Test + void givenValidDates_whenCheckEvidenceDueDatesIsInvokedWithExistingEvidenceDueDateAsNullAndEvidenceDueDateBeforeDate_thenExceptionIsThrown() { + LocalDate pastDate = LocalDate.now().minusMonths(2); + Date pastDateConverted = DateUtil.asDate(pastDate); + Date currentDate1 = new Date(); + Date currentDate2 = new Date(); + assertThrows(IllegalArgumentException.class, () -> + incomeEvidenceValidationService.checkEvidenceDueDates(pastDateConverted, currentDate1, currentDate2, null) + ); + } + + @Test + void givenValidDates_whenCheckEvidenceDueDatesIsInvokedWithExistingEvidenceDueDateAsNullAndEvidenceDueDateAfterDate_thenNoExceptionIsThrown() { + LocalDate futureDate = LocalDate.now().plusMonths(2); + Date futureDateConverted = DateUtil.asDate(futureDate); + Date currentDate1 = new Date(); + Date currentDate2 = new Date(); + incomeEvidenceValidationService.checkEvidenceDueDates(futureDateConverted, currentDate1, currentDate2, null); + } + + @Test + void givenValidDates_whenCheckEvidenceDueDatesIsInvokedWithExistingEvidenceDueDateAsNullAndEvidenceDueDateAsNull_thenNoExceptionIsThrown() { + Date currentDate1 = new Date(); + Date currentDate2 = new Date(); + incomeEvidenceValidationService.checkEvidenceDueDates(null, currentDate1, currentDate2, null); + } + + @Test + void givenValidDates_whenCheckEvidenceDueDatesIsInvokedWithSecondReminderDateAfterCurrentDate_thenNoExceptionIsThrown() { + LocalDate futureDate = LocalDate.now().plusMonths(2); + Date currentDate1 = new Date(); + Date currentDate2 = new Date(); + Date futureDateConverted = DateUtil.asDate(futureDate); + incomeEvidenceValidationService.checkEvidenceDueDates(currentDate1, currentDate2, futureDateConverted, currentDate2); + } + + @Test + void givenValidDates_whenCheckEvidenceDueDatesIsInvokedWithSecondReminderDateBeforeCurrentDate_thenNoExceptionIsThrown() { + LocalDate pastDate = LocalDate.now().minusMonths(2); + Date currentDate1 = new Date(); + Date currentDate2 = new Date(); + Date pastDateConverted = DateUtil.asDate(pastDate); + incomeEvidenceValidationService.checkEvidenceDueDates(currentDate1, currentDate2, pastDateConverted, currentDate2); + } + + @Test + void givenValidDates_whenCheckEvidenceDueDatesIsInvokedWithExistingEvidenceDueDateBeforeCurrentDate_thenNoExceptionIsThrown() { + LocalDate pastDate = LocalDate.now().minusMonths(2); + Date currentDate1 = new Date(); + Date currentDate2 = new Date(); + Date pastDateConverted = DateUtil.asDate(pastDate); + incomeEvidenceValidationService.checkEvidenceDueDates(currentDate1, currentDate2, currentDate2, pastDateConverted); + } + + @Test + void givenValidDates_whenValidateIsInvoked_thenNoExceptionIsThrown() { + EvidenceDTO evidenceDTO = EvidenceDTO.builder().evidenceDueDate(DateUtil.convertDateToDateTime(LocalDate.now().plusMonths(2))) + .firstReminderDate(DateUtil.convertDateToDateTime(LocalDate.now().plusMonths(1))) + .secondReminderDate(DateUtil.convertDateToDateTime(LocalDate.now().plusMonths(1))) + .existingEvidenceDueDate(DateUtil.convertDateToDateTime(LocalDate.now().minusMonths(1))) + .incomeExtraEvidence("OTHER") + .incomeExtraEvidenceText("Some text") + .incomeEvidenceReceivedDate(DateUtil.convertDateToDateTime(LocalDate.now().minusMonths(1))) + .applicationReceivedDate(DateUtil.convertDateToDateTime(LocalDate.now().minusMonths(2))) + .build(); + incomeEvidenceValidationService.validate(evidenceDTO); + } +} \ No newline at end of file