From dda2dba0d47a1e98714db7dfc6eb9471a09ebba0 Mon Sep 17 00:00:00 2001 From: Marcus Aspin Date: Tue, 23 Jan 2024 16:59:29 +0000 Subject: [PATCH] PI-1826 Return most recent release date (#3108) The overview endpoint previously returned null if there were multiple active events. This change looks at all active custodial events and returns the most recent release/recall dates. --- .../hmpps/data/generator/EventGenerator.kt | 42 ++++++------- .../delius/casesummary/Release.kt | 10 +--- .../hmpps/service/CaseSummaryService.kt | 38 ++---------- .../hmpps/service/CaseSummaryServiceTest.kt | 60 ++++++++----------- 4 files changed, 49 insertions(+), 101 deletions(-) diff --git a/projects/make-recall-decisions-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/EventGenerator.kt b/projects/make-recall-decisions-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/EventGenerator.kt index f10a7c33e5..ab7b96fbfa 100644 --- a/projects/make-recall-decisions-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/EventGenerator.kt +++ b/projects/make-recall-decisions-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/EventGenerator.kt @@ -1,18 +1,6 @@ package uk.gov.justice.digital.hmpps.data.generator -import uk.gov.justice.digital.hmpps.integrations.delius.casesummary.AdditionalOffence -import uk.gov.justice.digital.hmpps.integrations.delius.casesummary.Custody -import uk.gov.justice.digital.hmpps.integrations.delius.casesummary.Disposal -import uk.gov.justice.digital.hmpps.integrations.delius.casesummary.DisposalType -import uk.gov.justice.digital.hmpps.integrations.delius.casesummary.Event -import uk.gov.justice.digital.hmpps.integrations.delius.casesummary.Institution -import uk.gov.justice.digital.hmpps.integrations.delius.casesummary.KeyDate -import uk.gov.justice.digital.hmpps.integrations.delius.casesummary.LicenceCondition -import uk.gov.justice.digital.hmpps.integrations.delius.casesummary.LicenceConditionMainCategory -import uk.gov.justice.digital.hmpps.integrations.delius.casesummary.MainOffence -import uk.gov.justice.digital.hmpps.integrations.delius.casesummary.Offence -import uk.gov.justice.digital.hmpps.integrations.delius.casesummary.Recall -import uk.gov.justice.digital.hmpps.integrations.delius.casesummary.Release +import uk.gov.justice.digital.hmpps.integrations.delius.casesummary.* import uk.gov.justice.digital.hmpps.integrations.delius.referencedata.entity.ReferenceData import uk.gov.justice.digital.hmpps.set import java.time.LocalDate @@ -21,6 +9,20 @@ object EventGenerator { val CASE_SUMMARY = custodialEvent(PersonGenerator.CASE_SUMMARY.id) fun custodialEvent(personId: Long): Event { + val event = nonCustodialEvent(personId) + val disposal = event.disposal!! + val custody = Custody( + id = IdGenerator.getAndIncrement(), + disposal = disposal, + status = ReferenceData(IdGenerator.getAndIncrement(), "B", "Released on licence") + ) + custody.set(Custody::sentenceExpiryDate, custody.keyDate("SED", LocalDate.of(2023, 1, 1))) + custody.set(Custody::licenceExpiryDate, custody.keyDate("LED", LocalDate.of(2024, 1, 1))) + disposal.set(Disposal::custody, custody) + return event + } + + fun nonCustodialEvent(personId: Long): Event { val event = Event( id = IdGenerator.getAndIncrement(), personId = personId, @@ -38,14 +40,6 @@ object EventGenerator { secondEntryLength = 2, secondEntryLengthUnit = ReferenceData(IdGenerator.getAndIncrement(), "Y", "Years") ) - val custody = Custody( - id = IdGenerator.getAndIncrement(), - disposal = disposal, - status = ReferenceData(IdGenerator.getAndIncrement(), "B", "Released on licence") - ) - custody.set(Custody::sentenceExpiryDate, custody.keyDate("SED", LocalDate.of(2023, 1, 1))) - custody.set(Custody::licenceExpiryDate, custody.keyDate("LED", LocalDate.of(2024, 1, 1))) - disposal.set(Disposal::custody, custody) disposal.set(Disposal::licenceConditions, listOf(disposal.licenceCondition("TEST", "Freedom of movement"))) event.set(Event::disposal, disposal) event.set(Event::mainOffence, mainOffence(event)) @@ -76,11 +70,13 @@ object EventGenerator { ) ) - fun Custody.release(): Release { + fun Custody.release( + date: LocalDate = LocalDate.now().minusMonths(6), + ): Release { val release = Release( id = IdGenerator.getAndIncrement(), custodyId = id, - date = LocalDate.now().minusMonths(6), + date = date, institution = Institution(IdGenerator.getAndIncrement(), "Test institution", "Description of institution") ) release.set( diff --git a/projects/make-recall-decisions-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/casesummary/Release.kt b/projects/make-recall-decisions-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/casesummary/Release.kt index 1920bb5b6b..a3662c9216 100644 --- a/projects/make-recall-decisions-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/casesummary/Release.kt +++ b/projects/make-recall-decisions-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/casesummary/Release.kt @@ -1,12 +1,6 @@ package uk.gov.justice.digital.hmpps.integrations.delius.casesummary -import jakarta.persistence.Column -import jakarta.persistence.Entity -import jakarta.persistence.Id -import jakarta.persistence.JoinColumn -import jakarta.persistence.ManyToOne -import jakarta.persistence.OneToOne -import jakarta.persistence.Table +import jakarta.persistence.* import org.hibernate.annotations.Immutable import org.hibernate.annotations.SQLRestriction import org.springframework.data.jpa.repository.EntityGraph @@ -76,5 +70,5 @@ class Institution( interface CaseSummaryReleaseRepository : JpaRepository { @EntityGraph(attributePaths = ["recall", "institution"]) - fun findFirstByCustodyIdOrderByDateDesc(custodyId: Long): Release? + fun findFirstByCustodyIdInOrderByDateDesc(custodyIds: List): Release? } diff --git a/projects/make-recall-decisions-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/CaseSummaryService.kt b/projects/make-recall-decisions-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/CaseSummaryService.kt index 18b16ad23d..d733cc882c 100644 --- a/projects/make-recall-decisions-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/CaseSummaryService.kt +++ b/projects/make-recall-decisions-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/CaseSummaryService.kt @@ -1,39 +1,9 @@ package uk.gov.justice.digital.hmpps.service import org.springframework.stereotype.Service -import uk.gov.justice.digital.hmpps.api.model.ContactHistory -import uk.gov.justice.digital.hmpps.api.model.LicenceConditions -import uk.gov.justice.digital.hmpps.api.model.MappaAndRoshHistory -import uk.gov.justice.digital.hmpps.api.model.Overview -import uk.gov.justice.digital.hmpps.api.model.PersonalDetails -import uk.gov.justice.digital.hmpps.api.model.PersonalDetailsOverview -import uk.gov.justice.digital.hmpps.api.model.RecommendationModel +import uk.gov.justice.digital.hmpps.api.model.* import uk.gov.justice.digital.hmpps.api.model.RecommendationModel.Institution -import uk.gov.justice.digital.hmpps.api.model.dates -import uk.gov.justice.digital.hmpps.api.model.identifiers -import uk.gov.justice.digital.hmpps.api.model.name -import uk.gov.justice.digital.hmpps.api.model.toAddress -import uk.gov.justice.digital.hmpps.api.model.toContact -import uk.gov.justice.digital.hmpps.api.model.toConviction -import uk.gov.justice.digital.hmpps.api.model.toConvictionDetails -import uk.gov.justice.digital.hmpps.api.model.toConvictionWithLicenceConditions -import uk.gov.justice.digital.hmpps.api.model.toManager -import uk.gov.justice.digital.hmpps.api.model.toMappa -import uk.gov.justice.digital.hmpps.api.model.toRosh -import uk.gov.justice.digital.hmpps.integrations.delius.casesummary.CaseSummaryAddressRepository -import uk.gov.justice.digital.hmpps.integrations.delius.casesummary.CaseSummaryContactRepository -import uk.gov.justice.digital.hmpps.integrations.delius.casesummary.CaseSummaryEventRepository -import uk.gov.justice.digital.hmpps.integrations.delius.casesummary.CaseSummaryPersonManagerRepository -import uk.gov.justice.digital.hmpps.integrations.delius.casesummary.CaseSummaryPersonRepository -import uk.gov.justice.digital.hmpps.integrations.delius.casesummary.CaseSummaryRegistrationRepository -import uk.gov.justice.digital.hmpps.integrations.delius.casesummary.CaseSummaryReleaseRepository -import uk.gov.justice.digital.hmpps.integrations.delius.casesummary.Event -import uk.gov.justice.digital.hmpps.integrations.delius.casesummary.Person -import uk.gov.justice.digital.hmpps.integrations.delius.casesummary.findMainAddress -import uk.gov.justice.digital.hmpps.integrations.delius.casesummary.findMappa -import uk.gov.justice.digital.hmpps.integrations.delius.casesummary.findRoshHistory -import uk.gov.justice.digital.hmpps.integrations.delius.casesummary.getPerson -import uk.gov.justice.digital.hmpps.integrations.delius.casesummary.searchContacts +import uk.gov.justice.digital.hmpps.integrations.delius.casesummary.* import java.time.LocalDate @Service @@ -143,8 +113,8 @@ class CaseSummaryService( ) } - private fun List.lastRelease() = map { it.disposal?.custody }.singleOrNull() - ?.let { releaseRepository.findFirstByCustodyIdOrderByDateDesc(it.id) } + private fun List.lastRelease() = mapNotNull { it.disposal?.custody?.id } + .let { releaseRepository.findFirstByCustodyIdInOrderByDateDesc(it) } private fun List.custodial() = filter { it.disposal?.custody != null } } diff --git a/projects/make-recall-decisions-and-delius/src/test/kotlin/uk/gov/justice/digital/hmpps/service/CaseSummaryServiceTest.kt b/projects/make-recall-decisions-and-delius/src/test/kotlin/uk/gov/justice/digital/hmpps/service/CaseSummaryServiceTest.kt index e84b3b4496..4792d71235 100644 --- a/projects/make-recall-decisions-and-delius/src/test/kotlin/uk/gov/justice/digital/hmpps/service/CaseSummaryServiceTest.kt +++ b/projects/make-recall-decisions-and-delius/src/test/kotlin/uk/gov/justice/digital/hmpps/service/CaseSummaryServiceTest.kt @@ -1,10 +1,7 @@ package uk.gov.justice.digital.hmpps.service import org.hamcrest.MatcherAssert.assertThat -import org.hamcrest.Matchers.empty -import org.hamcrest.Matchers.equalTo -import org.hamcrest.Matchers.hasSize -import org.hamcrest.Matchers.nullValue +import org.hamcrest.Matchers.* import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertThrows import org.junit.jupiter.api.extension.ExtendWith @@ -13,26 +10,12 @@ import org.mockito.Mock import org.mockito.junit.jupiter.MockitoExtension import org.mockito.kotlin.whenever import uk.gov.justice.digital.hmpps.api.model.ContactTypeSummary -import uk.gov.justice.digital.hmpps.data.generator.AddressGenerator -import uk.gov.justice.digital.hmpps.data.generator.ContactGenerator -import uk.gov.justice.digital.hmpps.data.generator.EventGenerator +import uk.gov.justice.digital.hmpps.data.generator.* +import uk.gov.justice.digital.hmpps.data.generator.EventGenerator.custodialEvent +import uk.gov.justice.digital.hmpps.data.generator.EventGenerator.nonCustodialEvent import uk.gov.justice.digital.hmpps.data.generator.EventGenerator.release -import uk.gov.justice.digital.hmpps.data.generator.PersonGenerator -import uk.gov.justice.digital.hmpps.data.generator.PersonManagerGenerator -import uk.gov.justice.digital.hmpps.data.generator.RegistrationGenerator import uk.gov.justice.digital.hmpps.datetime.EuropeLondon -import uk.gov.justice.digital.hmpps.integrations.delius.casesummary.CaseSummaryAddressRepository -import uk.gov.justice.digital.hmpps.integrations.delius.casesummary.CaseSummaryContactRepository -import uk.gov.justice.digital.hmpps.integrations.delius.casesummary.CaseSummaryEventRepository -import uk.gov.justice.digital.hmpps.integrations.delius.casesummary.CaseSummaryPersonManagerRepository -import uk.gov.justice.digital.hmpps.integrations.delius.casesummary.CaseSummaryPersonRepository -import uk.gov.justice.digital.hmpps.integrations.delius.casesummary.CaseSummaryRegistrationRepository -import uk.gov.justice.digital.hmpps.integrations.delius.casesummary.CaseSummaryReleaseRepository -import uk.gov.justice.digital.hmpps.integrations.delius.casesummary.Event -import uk.gov.justice.digital.hmpps.integrations.delius.casesummary.RegisterType -import uk.gov.justice.digital.hmpps.integrations.delius.casesummary.Registration -import uk.gov.justice.digital.hmpps.integrations.delius.casesummary.Release -import uk.gov.justice.digital.hmpps.integrations.delius.casesummary.findMainAddress +import uk.gov.justice.digital.hmpps.integrations.delius.casesummary.* import java.time.LocalDate import java.time.ZonedDateTime @@ -112,20 +95,25 @@ internal class CaseSummaryServiceTest { } @Test - fun `get overview ignores multiple custodial events`() { + fun `get overview returns most recent release date from any active custodial event`() { + val events = listOf(custodialEvent(person.id), custodialEvent(person.id), nonCustodialEvent(person.id)) + val release1 = events[0].disposal!!.custody!!.release(LocalDate.of(2020, 1, 1)) + val release2 = events[1].disposal!!.custody!!.release(LocalDate.of(2020, 1, 2)) + givenPersonalDetails() - givenCustodialEvents(List(3) { EventGenerator.custodialEvent(person.id) }) + givenEvents(events) + givenReleases(listOf(release1, release2)) val overview = caseSummaryService.getOverview(person.crn) assertThat(overview.activeConvictions, hasSize(3)) - assertThat(overview.lastRelease, nullValue()) + assertThat(overview.lastRelease?.releaseDate, equalTo(LocalDate.of(2020, 1, 2))) } @Test - fun `get overview throws when no custodial events`() { + fun `get overview handles no custodial events`() { givenPersonalDetails() - givenCustodialEvents(emptyList()) + givenEvents(emptyList()) val overview = caseSummaryService.getOverview(person.crn) @@ -257,21 +245,21 @@ internal class CaseSummaryServiceTest { .thenReturn(rosh) } - private fun givenCustodialEvents(events: List): List { + private fun givenEvents(events: List): List { whenever(eventRepository.findByPersonId(person.id)).thenReturn(events) return events } private fun givenACustodialEvent(event: Event = EventGenerator.CASE_SUMMARY) = - givenCustodialEvents(listOf(event))[0] + givenEvents(listOf(event))[0] - private fun givenARelease(): Release { - val event = givenACustodialEvent() - val release = event.disposal!!.custody!!.release() - whenever(releaseRepository.findFirstByCustodyIdOrderByDateDesc(event.disposal!!.custody!!.id)).thenReturn( - release - ) - return release + private fun givenARelease(release: Release = givenACustodialEvent().disposal!!.custody!!.release()) = + givenReleases(listOf(release))[0] + + private fun givenReleases(releases: List = listOf(givenACustodialEvent().disposal!!.custody!!.release())): List { + whenever(releaseRepository.findFirstByCustodyIdInOrderByDateDesc(releases.map { it.custodyId })) + .thenReturn(releases.maxBy { it.date }) + return releases } private fun givenContacts() {