From 740e603cddd05daaf3f97d9b83e989fd5c9637f4 Mon Sep 17 00:00:00 2001 From: achimber-moj <161360519+achimber-moj@users.noreply.github.com> Date: Fri, 17 May 2024 11:00:50 +0100 Subject: [PATCH 01/10] Bug/pi 2204 approved premises and delius booking cancellation (#3805) * PI-2204 delete approved_premises_preferred record if one exists Signed-off-by: Amardeep Chimber * PI-2204 update integration test Signed-off-by: Amardeep Chimber * PI-2204 update integration test Signed-off-by: Amardeep Chimber * Formatting changes * Empty-Commit --------- Signed-off-by: Amardeep Chimber Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .../digital/hmpps/MessagingIntegrationTest.kt | 10 ++++ .../referral/entity/PreferredResidence.kt | 24 +++++++++ .../digital/hmpps/service/ReferralService.kt | 5 ++ .../service/ApprovedPremisesServiceTest.kt | 51 +++---------------- 4 files changed, 47 insertions(+), 43 deletions(-) create mode 100644 projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/approvedpremises/referral/entity/PreferredResidence.kt diff --git a/projects/approved-premises-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/MessagingIntegrationTest.kt b/projects/approved-premises-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/MessagingIntegrationTest.kt index 1070442507..47eb8c553a 100644 --- a/projects/approved-premises-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/MessagingIntegrationTest.kt +++ b/projects/approved-premises-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/MessagingIntegrationTest.kt @@ -22,6 +22,8 @@ import uk.gov.justice.digital.hmpps.datetime.EuropeLondon import uk.gov.justice.digital.hmpps.integrations.approvedpremises.EventDetails import uk.gov.justice.digital.hmpps.integrations.approvedpremises.PersonArrived import uk.gov.justice.digital.hmpps.integrations.approvedpremises.PersonDeparted +import uk.gov.justice.digital.hmpps.integrations.delius.approvedpremises.referral.entity.PreferredResidence +import uk.gov.justice.digital.hmpps.integrations.delius.approvedpremises.referral.entity.PreferredResidenceRepository import uk.gov.justice.digital.hmpps.integrations.delius.approvedpremises.referral.entity.ReferralRepository import uk.gov.justice.digital.hmpps.integrations.delius.approvedpremises.referral.entity.ResidenceRepository import uk.gov.justice.digital.hmpps.integrations.delius.contact.ContactRepository @@ -73,6 +75,9 @@ internal class MessagingIntegrationTest { @Autowired private lateinit var residenceRepository: ResidenceRepository + @Autowired + private lateinit var preferredResidenceRepository: PreferredResidenceRepository + @Autowired private lateinit var staffRepository: StaffRepository @@ -442,6 +447,9 @@ internal class MessagingIntegrationTest { residenceRepository.findByReferralId(ref.id)?.also(residenceRepository::delete) + preferredResidenceRepository.save(PreferredResidence(0, ref.id)) + assertTrue(preferredResidenceRepository.existsByApprovedPremisesResidenceId(ref.id)) + channelManager.getChannel(queueName).publishAndWait(event) verify(telemetryService).trackEvent("BookingCancelled", event.message.telemetryProperties()) @@ -468,5 +476,7 @@ internal class MessagingIntegrationTest { it.personId == contact.person.id && it.eventId == contact.eventId } assertNull(referral) + + assertFalse(preferredResidenceRepository.existsByApprovedPremisesResidenceId(ref.id)) } } diff --git a/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/approvedpremises/referral/entity/PreferredResidence.kt b/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/approvedpremises/referral/entity/PreferredResidence.kt new file mode 100644 index 0000000000..9e8515ac19 --- /dev/null +++ b/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/approvedpremises/referral/entity/PreferredResidence.kt @@ -0,0 +1,24 @@ +package uk.gov.justice.digital.hmpps.integrations.delius.approvedpremises.referral.entity + +import jakarta.persistence.* +import org.springframework.data.jpa.domain.support.AuditingEntityListener +import org.springframework.data.jpa.repository.JpaRepository + +@Entity +@Table(name = "approved_premises_preferred") +@EntityListeners(AuditingEntityListener::class) +@SequenceGenerator(name = "ap_preferred_id_seq", sequenceName = "ap_preferred_id_seq", allocationSize = 1) +class PreferredResidence( + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "ap_preferred_id_seq") + @Column(name = "approved_premises_preferred_id") + val id: Long = 0, + + val approvedPremisesResidenceId: Long +) + +interface PreferredResidenceRepository : JpaRepository { + fun existsByApprovedPremisesResidenceId(approvedPremisesResidenceId: Long): Boolean + + fun deleteByApprovedPremisesResidenceId(approvedPremisesResidenceId: Long) +} \ No newline at end of file diff --git a/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/ReferralService.kt b/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/ReferralService.kt index 61c50a2922..f741041fbb 100644 --- a/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/ReferralService.kt +++ b/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/ReferralService.kt @@ -42,6 +42,7 @@ class ReferralService( private val staffRepository: StaffRepository, private val referralRepository: ReferralRepository, private val residenceRepository: ResidenceRepository, + private val preferredResidenceRepository: PreferredResidenceRepository, private val personRepository: PersonRepository, private val eventRepository: EventRepository, private val registrationRepository: RegistrationRepository, @@ -119,6 +120,10 @@ class ReferralService( val person = personRepository.getByCrn(crn) val externalReference = Nsi.EXT_REF_BOOKING_PREFIX + details.bookingId val referral = findReferral(person, externalReference)?.also { + if (preferredResidenceRepository.existsByApprovedPremisesResidenceId(it.id)) { + preferredResidenceRepository.deleteByApprovedPremisesResidenceId(it.id) + } + val residence = residenceRepository.findByReferralId(it.id) if (residence == null) referralRepository.delete(it) else throw IgnorableMessageException( diff --git a/projects/approved-premises-and-delius/src/test/kotlin/uk/gov/justice/digital/hmpps/service/ApprovedPremisesServiceTest.kt b/projects/approved-premises-and-delius/src/test/kotlin/uk/gov/justice/digital/hmpps/service/ApprovedPremisesServiceTest.kt index 144d544af4..a0cbddb468 100644 --- a/projects/approved-premises-and-delius/src/test/kotlin/uk/gov/justice/digital/hmpps/service/ApprovedPremisesServiceTest.kt +++ b/projects/approved-premises-and-delius/src/test/kotlin/uk/gov/justice/digital/hmpps/service/ApprovedPremisesServiceTest.kt @@ -13,58 +13,19 @@ import org.mockito.junit.jupiter.MockitoExtension import org.mockito.kotlin.check import org.mockito.kotlin.whenever import org.springframework.boot.context.event.ApplicationStartedEvent -import uk.gov.justice.digital.hmpps.data.generator.ApprovedPremisesGenerator -import uk.gov.justice.digital.hmpps.data.generator.AssessedByGenerator -import uk.gov.justice.digital.hmpps.data.generator.BookedByGenerator -import uk.gov.justice.digital.hmpps.data.generator.ContactTypeGenerator -import uk.gov.justice.digital.hmpps.data.generator.EventDetailsGenerator -import uk.gov.justice.digital.hmpps.data.generator.IdGenerator -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.ProbationAreaGenerator -import uk.gov.justice.digital.hmpps.data.generator.ReferenceDataGenerator -import uk.gov.justice.digital.hmpps.data.generator.StaffGenerator -import uk.gov.justice.digital.hmpps.data.generator.StaffMemberGenerator -import uk.gov.justice.digital.hmpps.data.generator.SubmittedByGenerator -import uk.gov.justice.digital.hmpps.data.generator.TeamGenerator -import uk.gov.justice.digital.hmpps.data.generator.UserGenerator +import uk.gov.justice.digital.hmpps.data.generator.* import uk.gov.justice.digital.hmpps.exception.NotFoundException -import uk.gov.justice.digital.hmpps.integrations.approvedpremises.ApplicationAssessed -import uk.gov.justice.digital.hmpps.integrations.approvedpremises.ApplicationSubmitted -import uk.gov.justice.digital.hmpps.integrations.approvedpremises.ApprovedPremisesApiClient -import uk.gov.justice.digital.hmpps.integrations.approvedpremises.AssessedBy -import uk.gov.justice.digital.hmpps.integrations.approvedpremises.BookedBy -import uk.gov.justice.digital.hmpps.integrations.approvedpremises.BookingMade -import uk.gov.justice.digital.hmpps.integrations.approvedpremises.EventDetails -import uk.gov.justice.digital.hmpps.integrations.approvedpremises.PersonArrived -import uk.gov.justice.digital.hmpps.integrations.approvedpremises.PersonNotArrived -import uk.gov.justice.digital.hmpps.integrations.approvedpremises.SubmittedBy +import uk.gov.justice.digital.hmpps.integrations.approvedpremises.* import uk.gov.justice.digital.hmpps.integrations.delius.approvedpremises.ApprovedPremisesRepository import uk.gov.justice.digital.hmpps.integrations.delius.approvedpremises.entity.ApprovedPremises -import uk.gov.justice.digital.hmpps.integrations.delius.approvedpremises.referral.entity.Event -import uk.gov.justice.digital.hmpps.integrations.delius.approvedpremises.referral.entity.EventRepository -import uk.gov.justice.digital.hmpps.integrations.delius.approvedpremises.referral.entity.MoveOnCategoryRepository -import uk.gov.justice.digital.hmpps.integrations.delius.approvedpremises.referral.entity.Referral -import uk.gov.justice.digital.hmpps.integrations.delius.approvedpremises.referral.entity.ReferralRepository -import uk.gov.justice.digital.hmpps.integrations.delius.approvedpremises.referral.entity.ReferralSourceRepository -import uk.gov.justice.digital.hmpps.integrations.delius.approvedpremises.referral.entity.ResidenceRepository +import uk.gov.justice.digital.hmpps.integrations.delius.approvedpremises.referral.entity.* import uk.gov.justice.digital.hmpps.integrations.delius.contact.ContactRepository import uk.gov.justice.digital.hmpps.integrations.delius.contact.alert.ContactAlertRepository import uk.gov.justice.digital.hmpps.integrations.delius.contact.outcome.ContactOutcomeRepository import uk.gov.justice.digital.hmpps.integrations.delius.contact.type.ContactTypeCode import uk.gov.justice.digital.hmpps.integrations.delius.contact.type.ContactTypeRepository import uk.gov.justice.digital.hmpps.integrations.delius.location.OfficeLocationRepository -import uk.gov.justice.digital.hmpps.integrations.delius.nonstatutoryintervention.entity.Nsi -import uk.gov.justice.digital.hmpps.integrations.delius.nonstatutoryintervention.entity.NsiManagerRepository -import uk.gov.justice.digital.hmpps.integrations.delius.nonstatutoryintervention.entity.NsiRepository -import uk.gov.justice.digital.hmpps.integrations.delius.nonstatutoryintervention.entity.NsiStatus -import uk.gov.justice.digital.hmpps.integrations.delius.nonstatutoryintervention.entity.NsiStatusCode -import uk.gov.justice.digital.hmpps.integrations.delius.nonstatutoryintervention.entity.NsiStatusRepository -import uk.gov.justice.digital.hmpps.integrations.delius.nonstatutoryintervention.entity.NsiType -import uk.gov.justice.digital.hmpps.integrations.delius.nonstatutoryintervention.entity.NsiTypeCode -import uk.gov.justice.digital.hmpps.integrations.delius.nonstatutoryintervention.entity.NsiTypeRepository -import uk.gov.justice.digital.hmpps.integrations.delius.nonstatutoryintervention.entity.TransferReason -import uk.gov.justice.digital.hmpps.integrations.delius.nonstatutoryintervention.entity.TransferReasonRepository +import uk.gov.justice.digital.hmpps.integrations.delius.nonstatutoryintervention.entity.* import uk.gov.justice.digital.hmpps.integrations.delius.person.Person import uk.gov.justice.digital.hmpps.integrations.delius.person.PersonRepository import uk.gov.justice.digital.hmpps.integrations.delius.person.address.PersonAddressRepository @@ -155,6 +116,9 @@ internal class ApprovedPremisesServiceTest { @Mock lateinit var residenceRepository: ResidenceRepository + @Mock + lateinit var preferredResidenceRepository: PreferredResidenceRepository + @Mock lateinit var eventRepository: EventRepository @@ -199,6 +163,7 @@ internal class ApprovedPremisesServiceTest { staffRepository, referralRepository, residenceRepository, + preferredResidenceRepository, personRepository, eventRepository, registrationRepository, From eee39391c725e249ce623766cb7ca7b7734c0ef4 Mon Sep 17 00:00:00 2001 From: achimber-moj <161360519+achimber-moj@users.noreply.github.com> Date: Fri, 17 May 2024 12:10:30 +0100 Subject: [PATCH 02/10] =?UTF-8?q?PI-2204=20correct=20column=20name=20in=20?= =?UTF-8?q?approved=5Fpremises=5Fpreferred,=20to=20fix=20fa=E2=80=A6=20(#3?= =?UTF-8?q?807)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PI-2204 correct column name in approved_premises_preferred, to fix failed deployment of pod Signed-off-by: Amardeep Chimber --- .../gov/justice/digital/hmpps/MessagingIntegrationTest.kt | 4 ++-- .../approvedpremises/referral/entity/PreferredResidence.kt | 6 +++--- .../uk/gov/justice/digital/hmpps/service/ReferralService.kt | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/projects/approved-premises-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/MessagingIntegrationTest.kt b/projects/approved-premises-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/MessagingIntegrationTest.kt index 47eb8c553a..92023075f3 100644 --- a/projects/approved-premises-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/MessagingIntegrationTest.kt +++ b/projects/approved-premises-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/MessagingIntegrationTest.kt @@ -448,7 +448,7 @@ internal class MessagingIntegrationTest { residenceRepository.findByReferralId(ref.id)?.also(residenceRepository::delete) preferredResidenceRepository.save(PreferredResidence(0, ref.id)) - assertTrue(preferredResidenceRepository.existsByApprovedPremisesResidenceId(ref.id)) + assertTrue(preferredResidenceRepository.existsByApprovedPremisesReferralId(ref.id)) channelManager.getChannel(queueName).publishAndWait(event) @@ -477,6 +477,6 @@ internal class MessagingIntegrationTest { } assertNull(referral) - assertFalse(preferredResidenceRepository.existsByApprovedPremisesResidenceId(ref.id)) + assertFalse(preferredResidenceRepository.existsByApprovedPremisesReferralId(ref.id)) } } diff --git a/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/approvedpremises/referral/entity/PreferredResidence.kt b/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/approvedpremises/referral/entity/PreferredResidence.kt index 9e8515ac19..a33ced1460 100644 --- a/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/approvedpremises/referral/entity/PreferredResidence.kt +++ b/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/approvedpremises/referral/entity/PreferredResidence.kt @@ -14,11 +14,11 @@ class PreferredResidence( @Column(name = "approved_premises_preferred_id") val id: Long = 0, - val approvedPremisesResidenceId: Long + val approvedPremisesReferralId: Long ) interface PreferredResidenceRepository : JpaRepository { - fun existsByApprovedPremisesResidenceId(approvedPremisesResidenceId: Long): Boolean + fun existsByApprovedPremisesReferralId(approvedPremisesReferralId: Long): Boolean - fun deleteByApprovedPremisesResidenceId(approvedPremisesResidenceId: Long) + fun deleteByApprovedPremisesReferralId(approvedPremisesReferralId: Long) } \ No newline at end of file diff --git a/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/ReferralService.kt b/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/ReferralService.kt index f741041fbb..edf3356325 100644 --- a/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/ReferralService.kt +++ b/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/ReferralService.kt @@ -120,8 +120,8 @@ class ReferralService( val person = personRepository.getByCrn(crn) val externalReference = Nsi.EXT_REF_BOOKING_PREFIX + details.bookingId val referral = findReferral(person, externalReference)?.also { - if (preferredResidenceRepository.existsByApprovedPremisesResidenceId(it.id)) { - preferredResidenceRepository.deleteByApprovedPremisesResidenceId(it.id) + if (preferredResidenceRepository.existsByApprovedPremisesReferralId(it.id)) { + preferredResidenceRepository.deleteByApprovedPremisesReferralId(it.id) } val residence = residenceRepository.findByReferralId(it.id) From 145e1af83ba8bf9f58b5037651fde3e3c0ba2d79 Mon Sep 17 00:00:00 2001 From: achimber-moj <161360519+achimber-moj@users.noreply.github.com> Date: Fri, 17 May 2024 14:05:54 +0100 Subject: [PATCH 03/10] PI-2204 add missing sequence (#3808) Signed-off-by: Amardeep Chimber --- projects/approved-premises-and-delius/deploy/database/access.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/projects/approved-premises-and-delius/deploy/database/access.yml b/projects/approved-premises-and-delius/deploy/database/access.yml index b3f3219220..0516424044 100644 --- a/projects/approved-premises-and-delius/deploy/database/access.yml +++ b/projects/approved-premises-and-delius/deploy/database/access.yml @@ -14,6 +14,7 @@ database: sequences: - ap_referral_id_seq - ap_residence_id_seq + - ap_preferred_id_seq audit: username: ApprovedPremisesAndDelius From 648ddfb5e6993529b15d072aecd95bbaa46af808 Mon Sep 17 00:00:00 2001 From: pmcphee77 <150798161+pmcphee77@users.noreply.github.com> Date: Mon, 20 May 2024 09:51:59 +0100 Subject: [PATCH 04/10] PI-2194: Added new event for recall consideration (#3804) * PI-2194: Added new event for recall consideration --- .../README.md | 1 + .../justice/digital/hmpps/data/DataLoader.kt | 1 + .../hmpps/data/generator/ContactGenerator.kt | 2 + .../dev/resources/messages/consideration.json | 21 +++++++++ .../__files/consideration-detail.json | 4 ++ .../mappings/make-recall-decisions-api.json | 13 ++++++ .../hmpps/RecommendationIntegrationTest.kt | 21 +++++++++ .../recommendation/contact/entity/Contact.kt | 1 + .../digital/hmpps/messaging/Handler.kt | 7 +++ .../hmpps/service/RecommendationService.kt | 43 +++++++++++++++---- 10 files changed, 105 insertions(+), 9 deletions(-) create mode 100644 projects/make-recall-decisions-and-delius/src/dev/resources/messages/consideration.json create mode 100644 projects/make-recall-decisions-and-delius/src/dev/resources/simulations/__files/consideration-detail.json diff --git a/projects/make-recall-decisions-and-delius/README.md b/projects/make-recall-decisions-and-delius/README.md index 5c3e5b743e..4808c31348 100644 --- a/projects/make-recall-decisions-and-delius/README.md +++ b/projects/make-recall-decisions-and-delius/README.md @@ -38,6 +38,7 @@ separate events. |--------------------------------|--------------------|-----------------------------------------------------| | Recommendation Process Started | HMPPS Domain Event | "prison-recall.recommendation.started" | | Management Oversight of Recall | HMPPS Domain Event | "prison-recall.recommendation.management-oversight" | +| Recall being considered | HMPPS Domain Event | "prison-recall.recommendation.consideration" | ## Authorisation diff --git a/projects/make-recall-decisions-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/DataLoader.kt b/projects/make-recall-decisions-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/DataLoader.kt index 747156898f..ea1e91fb13 100644 --- a/projects/make-recall-decisions-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/DataLoader.kt +++ b/projects/make-recall-decisions-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/DataLoader.kt @@ -81,6 +81,7 @@ class DataLoader( persist(ContactGenerator.DEFAULT_TYPE) persist(ContactGenerator.SYSTEM_GENERATED_TYPE) persist(ContactGenerator.AP_RESIDENCE_PLAN_PREPARED) + persist(ContactGenerator.CONSIDERATION) persist(ContactGenerator.DEFAULT) persist(ContactGenerator.SYSTEM_GENERATED) persist(ContactGenerator.FUTURE) diff --git a/projects/make-recall-decisions-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/ContactGenerator.kt b/projects/make-recall-decisions-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/ContactGenerator.kt index 0d51f5a6cb..39c1a009d9 100644 --- a/projects/make-recall-decisions-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/ContactGenerator.kt +++ b/projects/make-recall-decisions-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/ContactGenerator.kt @@ -17,6 +17,8 @@ object ContactGenerator { val SYSTEM_GENERATED_TYPE = ContactType(IdGenerator.getAndIncrement(), "SG", "System-generated contact type", true) val AP_RESIDENCE_PLAN_PREPARED = ContactType(IdGenerator.getAndIncrement(), "APRAP5", "AP Residence Plan Prepared", false) + val CONSIDERATION = + ContactType(IdGenerator.getAndIncrement(), "C519", "Recall being considered - CaR", false) val DEFAULT = generate(notes = "default") val SYSTEM_GENERATED = diff --git a/projects/make-recall-decisions-and-delius/src/dev/resources/messages/consideration.json b/projects/make-recall-decisions-and-delius/src/dev/resources/messages/consideration.json new file mode 100644 index 0000000000..9193055a66 --- /dev/null +++ b/projects/make-recall-decisions-and-delius/src/dev/resources/messages/consideration.json @@ -0,0 +1,21 @@ +{ + "eventType": "prison-recall.recommendation.consideration", + "version": 1, + "description": "Recall being considered", + "occurredAt": "2022-11-21T06:27:57.028Z", + "detailUrl": "http://localhost:{wiremock.port}/mrd/recallConsideration/1", + "additionalInformation": { + "recommendationUrl": "http://mrd.case.crn/overview", + "bookedBy": { + "username": "WithStaff" + } + }, + "personReference": { + "identifiers": [ + { + "type": "CRN", + "value": "X000001" + } + ] + } +} \ No newline at end of file diff --git a/projects/make-recall-decisions-and-delius/src/dev/resources/simulations/__files/consideration-detail.json b/projects/make-recall-decisions-and-delius/src/dev/resources/simulations/__files/consideration-detail.json new file mode 100644 index 0000000000..75e88389b4 --- /dev/null +++ b/projects/make-recall-decisions-and-delius/src/dev/resources/simulations/__files/consideration-detail.json @@ -0,0 +1,4 @@ +{ + "notes": "I am considering recalling Mr Z because he bridges the licence conditions xyz………", + "sensitive": true +} \ No newline at end of file diff --git a/projects/make-recall-decisions-and-delius/src/dev/resources/simulations/mappings/make-recall-decisions-api.json b/projects/make-recall-decisions-and-delius/src/dev/resources/simulations/mappings/make-recall-decisions-api.json index a018589dfc..bf75af91c8 100644 --- a/projects/make-recall-decisions-and-delius/src/dev/resources/simulations/mappings/make-recall-decisions-api.json +++ b/projects/make-recall-decisions-and-delius/src/dev/resources/simulations/mappings/make-recall-decisions-api.json @@ -25,6 +25,19 @@ "status": 200, "bodyFileName": "deletion.json" } + }, + { + "request": { + "method": "GET", + "urlPath": "/mrd/recallConsideration/1" + }, + "response": { + "headers": { + "Content-Type": "application/json" + }, + "status": 200, + "bodyFileName": "consideration-detail.json" + } } ] } \ No newline at end of file diff --git a/projects/make-recall-decisions-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/RecommendationIntegrationTest.kt b/projects/make-recall-decisions-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/RecommendationIntegrationTest.kt index b2483fddd7..87dd7a0eb3 100644 --- a/projects/make-recall-decisions-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/RecommendationIntegrationTest.kt +++ b/projects/make-recall-decisions-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/RecommendationIntegrationTest.kt @@ -74,6 +74,27 @@ internal class RecommendationIntegrationTest { verify(telemetryService, atLeastOnce()).notificationReceived(notification) } + @Test + fun `considering a recall`() { + val notification = prepEvent("consideration", wireMockServer.port()) + channelManager.getChannel(queueName).publishAndWait(notification) + + val person = PersonGenerator.RECOMMENDATION_STARTED + val contact = getContact(person.id) + assertNotNull(contact!!) + assertThat(contact.providerId, equalTo(PersonGenerator.DEFAULT_PROVIDER.id)) + assertThat(contact.teamId, equalTo(PersonGenerator.DEFAULT_TEAM.id)) + assertThat(contact.staffId, equalTo(UserGenerator.WITH_STAFF.staff!!.id)) + assertThat( + contact.notes, + equalTo("I am considering recalling Mr Z because he bridges the licence conditions xyz………") + ) + assertThat(contact.isSensitive, equalTo(true)) + assertThat(contact.type.code, equalTo("C519")) + assertThat(contact.outcome, equalTo(null)) + verify(telemetryService, atLeastOnce()).notificationReceived(notification) + } + @Test fun `recommendation deleted`() { val notification = prepEvent("recommendation-deleted", wireMockServer.port()) diff --git a/projects/make-recall-decisions-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/recommendation/contact/entity/Contact.kt b/projects/make-recall-decisions-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/recommendation/contact/entity/Contact.kt index 7c8a7f5ed3..c5e0f2fabd 100644 --- a/projects/make-recall-decisions-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/recommendation/contact/entity/Contact.kt +++ b/projects/make-recall-decisions-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/recommendation/contact/entity/Contact.kt @@ -97,6 +97,7 @@ class ContactType( const val MANAGEMENT_OVERSIGHT_RECALL = "MO5" const val RECOMMENDATION_DELETED = "C517" const val AP_RESIDENCE_PLAN_PREPARED = "APRAP5" + const val CONSIDERATION = "C519" } } diff --git a/projects/make-recall-decisions-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/messaging/Handler.kt b/projects/make-recall-decisions-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/messaging/Handler.kt index 7fefca0074..67229fe58c 100644 --- a/projects/make-recall-decisions-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/messaging/Handler.kt +++ b/projects/make-recall-decisions-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/messaging/Handler.kt @@ -37,6 +37,13 @@ class Handler( occurredAt = notification.message.occurredAt ) + "prison-recall.recommendation.consideration" -> recommendationService.consideration( + crn = crn, + details = notification.details(), + username = notification.bookedByUsername(), + occurredAt = notification.message.occurredAt + ) + else -> throw NotImplementedError("Unhandled message type received: ${notification.eventType}") } } diff --git a/projects/make-recall-decisions-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/RecommendationService.kt b/projects/make-recall-decisions-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/RecommendationService.kt index 78449486fd..5cd7f26dc1 100644 --- a/projects/make-recall-decisions-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/RecommendationService.kt +++ b/projects/make-recall-decisions-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/RecommendationService.kt @@ -36,13 +36,7 @@ class RecommendationService( username: String, occurredAt: ZonedDateTime ) { - val contact = personRepository.getPerson(crn).addContact( - details, - date = occurredAt, - staff = staffRepository.getStaff(username), - type = contactTypeRepository.getByCode(ContactType.MANAGEMENT_OVERSIGHT_RECALL), - outcome = contactOutcomeRepository.getByCode(decision.code) - ) + val contact = addContact(crn, decision, details, username, occurredAt, ContactType.MANAGEMENT_OVERSIGHT_RECALL) contactRepository.save(contact) telemetryService.trackEvent( "ManagementOversightCreated", @@ -50,13 +44,44 @@ class RecommendationService( ) } + fun consideration( + crn: String, + details: RecommendationDetails, + username: String, + occurredAt: ZonedDateTime + ) { + val contact = addContact(crn, null, details, username, occurredAt, ContactType.CONSIDERATION) + contactRepository.save(contact) + telemetryService.trackEvent( + "ConsiderationCreated", + mapOf("CRN" to crn, "username" to username) + ) + } + + private fun addContact( + crn: String, + decision: ManagementDecision? = null, + details: RecommendationDetails, + username: String, + occurredAt: ZonedDateTime, + contactType: String + ): Contact { + return personRepository.getPerson(crn).getContact( + details, + date = occurredAt, + staff = staffRepository.getStaff(username), + type = contactTypeRepository.getByCode(contactType), + outcome = decision?.let { contactOutcomeRepository.getByCode(it.code) } + ) + } + fun deletion( crn: String, details: RecommendationDetails, username: String, occurredAt: ZonedDateTime ) { - val contact = personRepository.getPerson(crn).addContact( + val contact = personRepository.getPerson(crn).getContact( details, date = occurredAt, staff = staffRepository.findStaffByUsername(username), @@ -66,7 +91,7 @@ class RecommendationService( telemetryService.trackEvent("RecommendationDeletionCreated", mapOf("CRN" to crn, "username" to username)) } - private fun Person.addContact( + private fun Person.getContact( details: RecommendationDetails, staff: Staff?, date: ZonedDateTime, From cb04acac8ba115440fb61661b4b403feb7021ca5 Mon Sep 17 00:00:00 2001 From: pmcphee77 <150798161+pmcphee77@users.noreply.github.com> Date: Mon, 20 May 2024 10:40:20 +0100 Subject: [PATCH 05/10] PI-2207: Removed inactive check on event and added inactive event tests (#3810) * PI-2207: Removed inactive check on event and added inactive event tests --- .../justice/digital/hmpps/data/DataLoader.kt | 58 ++-- .../hmpps/data/generator/AddressGenerator.kt | 9 + .../hmpps/data/generator/PersonGenerator.kt | 3 +- .../application-assessed-inactive.json | 18 + .../application-submitted-inactive.json | 18 + .../messages/booking-made-inactive.json | 18 + .../messages/person-arrived-inactive.json | 18 + .../messages/person-departed-inactive.json | 18 + ...remises-application-assessed-inactive.json | 33 ++ ...emises-application-submitted-inactive.json | 50 +++ ...proved-premises-booking-made-inactive.json | 46 +++ ...oved-premises-person-arrived-inactive.json | 31 ++ ...ved-premises-person-departed-inactive.json | 48 +++ .../mappings/approved-premises-api.json | 65 ++++ .../hmpps/MessagingIntegrationInactiveTest.kt | 311 ++++++++++++++++++ .../referral/entity/Referral.kt | 6 - .../hmpps/service/ApprovedPremisesService.kt | 9 +- .../digital/hmpps/service/NsiService.kt | 18 +- .../digital/hmpps/service/ReferralService.kt | 2 +- .../service/ApprovedPremisesServiceTest.kt | 11 +- .../hmpps/data/generator/EventGenerator.kt | 2 +- 21 files changed, 737 insertions(+), 55 deletions(-) create mode 100644 projects/approved-premises-and-delius/src/dev/resources/messages/application-assessed-inactive.json create mode 100644 projects/approved-premises-and-delius/src/dev/resources/messages/application-submitted-inactive.json create mode 100644 projects/approved-premises-and-delius/src/dev/resources/messages/booking-made-inactive.json create mode 100644 projects/approved-premises-and-delius/src/dev/resources/messages/person-arrived-inactive.json create mode 100644 projects/approved-premises-and-delius/src/dev/resources/messages/person-departed-inactive.json create mode 100644 projects/approved-premises-and-delius/src/dev/resources/simulations/__files/approved-premises-application-assessed-inactive.json create mode 100644 projects/approved-premises-and-delius/src/dev/resources/simulations/__files/approved-premises-application-submitted-inactive.json create mode 100644 projects/approved-premises-and-delius/src/dev/resources/simulations/__files/approved-premises-booking-made-inactive.json create mode 100644 projects/approved-premises-and-delius/src/dev/resources/simulations/__files/approved-premises-person-arrived-inactive.json create mode 100644 projects/approved-premises-and-delius/src/dev/resources/simulations/__files/approved-premises-person-departed-inactive.json create mode 100644 projects/approved-premises-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/MessagingIntegrationInactiveTest.kt diff --git a/projects/approved-premises-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/DataLoader.kt b/projects/approved-premises-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/DataLoader.kt index d0a29894e4..f12ea6fb71 100644 --- a/projects/approved-premises-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/DataLoader.kt +++ b/projects/approved-premises-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/DataLoader.kt @@ -6,26 +6,8 @@ import org.springframework.boot.context.event.ApplicationReadyEvent import org.springframework.context.ApplicationListener import org.springframework.data.jpa.repository.JpaRepository import org.springframework.stereotype.Component -import uk.gov.justice.digital.hmpps.data.generator.AddressGenerator -import uk.gov.justice.digital.hmpps.data.generator.ApprovedPremisesGenerator -import uk.gov.justice.digital.hmpps.data.generator.CaseloadGenerator -import uk.gov.justice.digital.hmpps.data.generator.ContactOutcomeGenerator -import uk.gov.justice.digital.hmpps.data.generator.ContactTypeGenerator -import uk.gov.justice.digital.hmpps.data.generator.DatasetGenerator -import uk.gov.justice.digital.hmpps.data.generator.DocumentGenerator -import uk.gov.justice.digital.hmpps.data.generator.NsiStatusGenerator -import uk.gov.justice.digital.hmpps.data.generator.NsiTypeGenerator -import uk.gov.justice.digital.hmpps.data.generator.OfficeLocationGenerator -import uk.gov.justice.digital.hmpps.data.generator.PersonGenerator +import uk.gov.justice.digital.hmpps.data.generator.* import uk.gov.justice.digital.hmpps.data.generator.PersonGenerator.ANOTHER_EVENT -import uk.gov.justice.digital.hmpps.data.generator.PersonManagerGenerator -import uk.gov.justice.digital.hmpps.data.generator.ProbationAreaGenerator -import uk.gov.justice.digital.hmpps.data.generator.ReferenceDataGenerator -import uk.gov.justice.digital.hmpps.data.generator.ReferralGenerator -import uk.gov.justice.digital.hmpps.data.generator.StaffGenerator -import uk.gov.justice.digital.hmpps.data.generator.TeamGenerator -import uk.gov.justice.digital.hmpps.data.generator.TransferReasonGenerator -import uk.gov.justice.digital.hmpps.data.generator.UserGenerator import uk.gov.justice.digital.hmpps.integrations.delius.approvedpremises.ApprovedPremisesRepository import uk.gov.justice.digital.hmpps.integrations.delius.approvedpremises.entity.Address import uk.gov.justice.digital.hmpps.integrations.delius.approvedpremises.referral.entity.EventRepository @@ -38,11 +20,7 @@ import uk.gov.justice.digital.hmpps.integrations.delius.contact.type.ContactType import uk.gov.justice.digital.hmpps.integrations.delius.contact.type.ContactTypeRepository import uk.gov.justice.digital.hmpps.integrations.delius.document.DocumentRepository import uk.gov.justice.digital.hmpps.integrations.delius.location.OfficeLocationRepository -import uk.gov.justice.digital.hmpps.integrations.delius.nonstatutoryintervention.entity.NsiStatusCode -import uk.gov.justice.digital.hmpps.integrations.delius.nonstatutoryintervention.entity.NsiStatusRepository -import uk.gov.justice.digital.hmpps.integrations.delius.nonstatutoryintervention.entity.NsiTypeCode -import uk.gov.justice.digital.hmpps.integrations.delius.nonstatutoryintervention.entity.NsiTypeRepository -import uk.gov.justice.digital.hmpps.integrations.delius.nonstatutoryintervention.entity.TransferReasonRepository +import uk.gov.justice.digital.hmpps.integrations.delius.nonstatutoryintervention.entity.* import uk.gov.justice.digital.hmpps.integrations.delius.person.PersonRepository import uk.gov.justice.digital.hmpps.integrations.delius.person.address.PersonAddressRepository import uk.gov.justice.digital.hmpps.integrations.delius.person.manager.probation.PersonManagerRepository @@ -168,6 +146,7 @@ class DataLoader( staffRepository.save(personManagerStaff) val person = PersonGenerator.DEFAULT personRepository.save(person) + personRepository.save(PersonGenerator.PERSON_INACTIVE_EVENT) personManagerRepository.save( PersonManagerGenerator.generate( person, @@ -175,8 +154,20 @@ class DataLoader( team = TeamGenerator.NON_APPROVED_PREMISES_TEAM ) ) + + personManagerRepository.save( + PersonManagerGenerator.generate( + PersonGenerator.PERSON_INACTIVE_EVENT, + staff = personManagerStaff, + team = TeamGenerator.NON_APPROVED_PREMISES_TEAM + ) + ) + AddressGenerator.PERSON_ADDRESS = personAddressRepository.save(AddressGenerator.PERSON_ADDRESS) + AddressGenerator.INACTIVE_PERSON_ADDRESS = + personAddressRepository.save(AddressGenerator.INACTIVE_PERSON_ADDRESS) eventRepository.save(PersonGenerator.EVENT) + eventRepository.save(PersonGenerator.INACTIVE_EVENT) registrationRepository.save( PersonGenerator.generateRegistration( person, @@ -200,6 +191,25 @@ class DataLoader( caseloadRepository.save(CaseloadGenerator.generate(person, TeamGenerator.APPROVED_PREMISES_TEAM)) caseloadRepository.save(CaseloadGenerator.generate(person, TeamGenerator.UNALLOCATED)) + caseloadRepository.save( + CaseloadGenerator.generate( + PersonGenerator.PERSON_INACTIVE_EVENT, + TeamGenerator.NON_APPROVED_PREMISES_TEAM + ) + ) + caseloadRepository.save( + CaseloadGenerator.generate( + PersonGenerator.PERSON_INACTIVE_EVENT, + TeamGenerator.APPROVED_PREMISES_TEAM + ) + ) + caseloadRepository.save( + CaseloadGenerator.generate( + PersonGenerator.PERSON_INACTIVE_EVENT, + TeamGenerator.UNALLOCATED + ) + ) + eventRepository.save(ANOTHER_EVENT) referralRepository.save(ReferralGenerator.EXISTING_REFERRAL) diff --git a/projects/approved-premises-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/AddressGenerator.kt b/projects/approved-premises-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/AddressGenerator.kt index ce123b8aaa..6b71624423 100644 --- a/projects/approved-premises-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/AddressGenerator.kt +++ b/projects/approved-premises-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/AddressGenerator.kt @@ -12,6 +12,15 @@ object AddressGenerator { town = "Some Place", postcode = "MB01 3TD" ) + + var INACTIVE_PERSON_ADDRESS = generatePersonAddress( + personId = PersonGenerator.PERSON_INACTIVE_EVENT.id, + addressNumber = "12", + streetName = "Tulip Drive", + town = "Some Place", + postcode = "MB01 3TD" + ) + val Q001 = generateAddress("", "1", "Promise Street", "", "Make Believe", "", "MB01 1PS", "01234567890") val Q002 = generateAddress("", "2", "Future Street", "", "Make Believe", "", "MB02 2PS", "01234567891") diff --git a/projects/approved-premises-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/PersonGenerator.kt b/projects/approved-premises-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/PersonGenerator.kt index 771cc19896..9800053cee 100644 --- a/projects/approved-premises-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/PersonGenerator.kt +++ b/projects/approved-premises-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/PersonGenerator.kt @@ -13,9 +13,10 @@ import java.time.ZonedDateTime object PersonGenerator { val DEFAULT = generate(crn = "A000001") + val PERSON_INACTIVE_EVENT = generate(crn = "A000002") val EVENT = generateEvent("7", DEFAULT.id) val ANOTHER_EVENT = generateEvent("8", DEFAULT.id) - + val INACTIVE_EVENT = generateEvent("6", PERSON_INACTIVE_EVENT.id, active = false) val PERSON_WITH_BOOKING = generate(crn = "B000001") fun generate( diff --git a/projects/approved-premises-and-delius/src/dev/resources/messages/application-assessed-inactive.json b/projects/approved-premises-and-delius/src/dev/resources/messages/application-assessed-inactive.json new file mode 100644 index 0000000000..673bfabd3a --- /dev/null +++ b/projects/approved-premises-and-delius/src/dev/resources/messages/application-assessed-inactive.json @@ -0,0 +1,18 @@ +{ + "eventType": "approved-premises.application.assessed", + "version": 1, + "description": "An Approved Premises application has been assessed", + "detailUrl": "http://localhost:{wiremock.port}/approved-premises-api/events/application-assessed/484b8b5e-6c3b-4400-b200-425bbe410713-inactive", + "occurredAt": "2022-12-04T10:42:43+00:00", + "additionalInformation": { + "applicationId": "484b8b5e-6c3b-4400-b200-425bbe410713" + }, + "personReference": { + "identifiers": [ + { + "type": "CRN", + "value": "A000002" + } + ] + } +} \ No newline at end of file diff --git a/projects/approved-premises-and-delius/src/dev/resources/messages/application-submitted-inactive.json b/projects/approved-premises-and-delius/src/dev/resources/messages/application-submitted-inactive.json new file mode 100644 index 0000000000..624427f1c5 --- /dev/null +++ b/projects/approved-premises-and-delius/src/dev/resources/messages/application-submitted-inactive.json @@ -0,0 +1,18 @@ +{ + "eventType": "approved-premises.application.submitted", + "version": 1, + "description": "An Approved Premises application has been submitted", + "detailUrl": "http://localhost:{wiremock.port}/approved-premises-api/events/application-submitted/68df9f6c-3fcb-4ec6-8fcf-96551cd9b080-inactive", + "occurredAt": "2022-12-04T10:42:43+00:00", + "additionalInformation": { + "applicationId": "68df9f6c-3fcb-4ec6-8fcf-96551cd9b080" + }, + "personReference": { + "identifiers": [ + { + "type": "CRN", + "value": "A000002" + } + ] + } +} \ No newline at end of file diff --git a/projects/approved-premises-and-delius/src/dev/resources/messages/booking-made-inactive.json b/projects/approved-premises-and-delius/src/dev/resources/messages/booking-made-inactive.json new file mode 100644 index 0000000000..fa7931ca2a --- /dev/null +++ b/projects/approved-premises-and-delius/src/dev/resources/messages/booking-made-inactive.json @@ -0,0 +1,18 @@ +{ + "eventType": "approved-premises.booking.made", + "version": 1, + "description": "An Approved Premises booking has been made", + "detailUrl": "http://localhost:{wiremock.port}/approved-premises-api/events/booking-made/364145f9-0af8-488e-9901-b4c46cd9ba37-inactive", + "occurredAt": "2022-12-04T10:42:43+00:00", + "additionalInformation": { + "applicationId": "364145f9-0af8-488e-9901-b4c46cd9ba37" + }, + "personReference": { + "identifiers": [ + { + "type": "CRN", + "value": "A000002" + } + ] + } +} \ No newline at end of file diff --git a/projects/approved-premises-and-delius/src/dev/resources/messages/person-arrived-inactive.json b/projects/approved-premises-and-delius/src/dev/resources/messages/person-arrived-inactive.json new file mode 100644 index 0000000000..cde0fc08bc --- /dev/null +++ b/projects/approved-premises-and-delius/src/dev/resources/messages/person-arrived-inactive.json @@ -0,0 +1,18 @@ +{ + "eventType": "approved-premises.person.arrived", + "version": 1, + "description": "A person arrived to the Approved Premises", + "detailUrl": "http://localhost:{wiremock.port}/approved-premises-api/events/person-arrived/364145f9-0af8-488e-9901-b4c46cd9ba37-inactive", + "occurredAt": "2022-12-04T10:42:43+00:00", + "additionalInformation": { + "applicationId": "364145f9-0af8-488e-9901-b4c46cd9ba37" + }, + "personReference": { + "identifiers": [ + { + "type": "CRN", + "value": "A000002" + } + ] + } +} \ No newline at end of file diff --git a/projects/approved-premises-and-delius/src/dev/resources/messages/person-departed-inactive.json b/projects/approved-premises-and-delius/src/dev/resources/messages/person-departed-inactive.json new file mode 100644 index 0000000000..591d2eb91c --- /dev/null +++ b/projects/approved-premises-and-delius/src/dev/resources/messages/person-departed-inactive.json @@ -0,0 +1,18 @@ +{ + "eventType": "approved-premises.person.departed", + "version": 1, + "description": "A person departed frm the Approved Premises", + "detailUrl": "http://localhost:{wiremock.port}/approved-premises-api/events/person-departed/364145f9-0af8-488e-9901-b4c46cd9ba37-inactive", + "occurredAt": "2022-12-04T10:42:43+00:00", + "additionalInformation": { + "applicationId": "364145f9-0af8-488e-9901-b4c46cd9ba37" + }, + "personReference": { + "identifiers": [ + { + "type": "CRN", + "value": "A000002" + } + ] + } +} \ No newline at end of file diff --git a/projects/approved-premises-and-delius/src/dev/resources/simulations/__files/approved-premises-application-assessed-inactive.json b/projects/approved-premises-and-delius/src/dev/resources/simulations/__files/approved-premises-application-assessed-inactive.json new file mode 100644 index 0000000000..25f9bd0dfe --- /dev/null +++ b/projects/approved-premises-and-delius/src/dev/resources/simulations/__files/approved-premises-application-assessed-inactive.json @@ -0,0 +1,33 @@ +{ + "id": "364145f9-0af8-488e-9901-b4c46cd9ba37-inactive", + "timestamp": "2022-11-30T14:53:44", + "eventType": "approved-premises.application.assessed", + "eventDetails": { + "applicationId": "484b8b5e-6c3b-4400-b200-425bbe410713", + "applicationUrl": "https://approved-premises-dev.hmpps.service.justice.gov.uk/applications/484b8b5e-6c3b-4400-b200-425bbe410713", + "personReference": { + "crn": "A000002", + "noms": "A0002AA" + }, + "deliusEventNumber": "6", + "assessedAt": "2022-11-30T14:51:30", + "assessedBy": { + "staffMember": { + "staffCode": "N54A001", + "forenames": "John", + "surname": "Smith", + "username": "JohnSmithNPS" + }, + "probationArea": { + "code": "N54", + "name": "North East Region" + }, + "cru": { + "code": "N02", + "name": "NPS North East" + } + }, + "decision": "REJECTED", + "decisionRationale": "Risk too low" + } +} \ No newline at end of file diff --git a/projects/approved-premises-and-delius/src/dev/resources/simulations/__files/approved-premises-application-submitted-inactive.json b/projects/approved-premises-and-delius/src/dev/resources/simulations/__files/approved-premises-application-submitted-inactive.json new file mode 100644 index 0000000000..28d2f243a1 --- /dev/null +++ b/projects/approved-premises-and-delius/src/dev/resources/simulations/__files/approved-premises-application-submitted-inactive.json @@ -0,0 +1,50 @@ +{ + "id": "364145f9-0af8-488e-9901-b4c46cd9ba37-inactive", + "timestamp": "2022-11-30T14:53:44", + "eventType": "approved-premises.application.submitted", + "eventDetails": { + "applicationId": "68df9f6c-3fcb-4ec6-8fcf-96551cd9b080", + "applicationUrl": "https://approved-premises-dev.hmpps.service.justice.gov.uk/application/68df9f6c-3fcb-4ec6-8fcf-96551cd9b080", + "personReference": { + "crn": "A000002", + "noms": "A0002AA" + }, + "deliusEventNumber": "6", + "mappaCategories": "M2", + "sentenceLengthInMonths": 57, + "offenceDescription": "Wounding or inflicting grievous bodily harm (inflicting bodily injury with or without weapon) (S20) - 00801", + "releaseType": "Release on Temporary Licence (ROTL)", + "age": 43, + "gender": "Male", + "targetLocation": "LS2", + "submittedAt": "2022-11-30T14:51:30", + "submittedBy": { + "staffMember": { + "staffCode": "N54A001", + "forenames": "John", + "surname": "Smith", + "username": "JohnSmithNPS" + }, + "probationArea": { + "code": "N54", + "name": "North East Region" + }, + "cru": { + "code": "N02", + "name": "NPS North East" + }, + "team": { + "code": "N54NGH", + "name": "Gateshead 1" + }, + "ldu": { + "code": "N54PPU", + "name": "Public Protection NE" + }, + "region": { + "code": "NE", + "name": "North East" + } + } + } +} \ No newline at end of file diff --git a/projects/approved-premises-and-delius/src/dev/resources/simulations/__files/approved-premises-booking-made-inactive.json b/projects/approved-premises-and-delius/src/dev/resources/simulations/__files/approved-premises-booking-made-inactive.json new file mode 100644 index 0000000000..75bcaac8f4 --- /dev/null +++ b/projects/approved-premises-and-delius/src/dev/resources/simulations/__files/approved-premises-booking-made-inactive.json @@ -0,0 +1,46 @@ +{ + "id": "364145f9-0af8-488e-9901-b4c46cd9ba37-inactive", + "timestamp": "2022-11-30T14:53:44", + "eventType": "approved-premises.booking.made", + "eventDetails": { + "applicationId": "484b8b5e-6c3b-4400-b200-425bbe410713", + "applicationUrl": "https://approved-premises-dev.hmpps.service.justice.gov.uk/applications/484b8b5e-6c3b-4400-b200-425bbe410713", + "bookingId": "14c80733-4b6d-4f35-b724-66955aac320c", + "personReference": { + "crn": "A000002", + "noms": "A0002AA" + }, + "deliusEventNumber": "6", + "createdAt": "2022-11-30T14:51:30.438714078Z", + "bookedBy": { + "staffMember": { + "staffCode": "N54A001", + "forenames": "John", + "surname": "Smith", + "username": "JohnSmithNPS" + }, + "cru": { + "code": "N02", + "name": "NPS North East" + } + }, + "premises": { + "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", + "name": "Hope House", + "apCode": "NEHOPE1", + "legacyApCode": "Q001" + }, + "arrivalOn": "2023-01-30", + "departureOn": "2023-04-30", + "keyWorker": { + "staffCode": "N54A002", + "staffIdentifier": 1501234568, + "forenames": "Key", + "surname": "Worker", + "username": "KeyWorkerNPS" + }, + "applicationSubmittedOn": "2022-11-28T14:51:30", + "sentenceType": "nonStatutory", + "releaseType": "not_applicable" + } +} \ No newline at end of file diff --git a/projects/approved-premises-and-delius/src/dev/resources/simulations/__files/approved-premises-person-arrived-inactive.json b/projects/approved-premises-and-delius/src/dev/resources/simulations/__files/approved-premises-person-arrived-inactive.json new file mode 100644 index 0000000000..aeeb8dbe45 --- /dev/null +++ b/projects/approved-premises-and-delius/src/dev/resources/simulations/__files/approved-premises-person-arrived-inactive.json @@ -0,0 +1,31 @@ +{ + "id": "364145f9-0af8-488e-9901-b4c46cd9ba37-inactive", + "timestamp": "2022-11-30T14:53:44", + "eventType": "approved-premises.person.arrived", + "eventDetails": { + "personReference": { + "crn": "A000002", + "noms": "A0002AA" + }, + "deliusEventNumber": "6", + "applicationId": "484b8b5e-6c3b-4400-b200-425bbe410713", + "applicationUrl": "https://approved-premises-dev.hmpps.service.justice.gov.uk/applications/484b8b5e-6c3b-4400-b200-425bbe410713", + "bookingId": "14c80733-4b6d-4f35-b724-66955aac320c", + "premises": { + "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", + "name": "Hope House", + "apCode": "NEHOPE1", + "legacyApCode": "Q001" + }, + "keyWorker": { + "staffCode": "N54A001", + "forenames": "John", + "surname": "Smith", + "username": "JohnSmithNPS" + }, + "applicationSubmittedOn": "2022-11-29", + "arrivedAt": "2022-11-30T14:51:30", + "expectedDepartureOn": "2023-02-28", + "notes": "Arrived a day late due to rail strike. Informed in advance by COM." + } +} \ No newline at end of file diff --git a/projects/approved-premises-and-delius/src/dev/resources/simulations/__files/approved-premises-person-departed-inactive.json b/projects/approved-premises-and-delius/src/dev/resources/simulations/__files/approved-premises-person-departed-inactive.json new file mode 100644 index 0000000000..6788790fa5 --- /dev/null +++ b/projects/approved-premises-and-delius/src/dev/resources/simulations/__files/approved-premises-person-departed-inactive.json @@ -0,0 +1,48 @@ +{ + "id": "364145f9-0af8-488e-9901-b4c46cd9ba37-inactive", + "timestamp": "2022-11-30T14:53:44", + "eventType": "approved-premises.person.departed", + "eventDetails": { + "personReference": { + "crn": "A000002", + "noms": "A0002AA" + }, + "deliusEventNumber": "6", + "applicationId": "484b8b5e-6c3b-4400-b200-425bbe410713", + "applicationUrl": "https://approved-premises-dev.hmpps.service.justice.gov.uk/applications/484b8b5e-6c3b-4400-b200-425bbe410713", + "bookingId": "14c80733-4b6d-4f35-b724-66955aac320c", + "premises": { + "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", + "name": "Hope House", + "apCode": "NEHOPE1", + "legacyApCode": "Q001" + }, + "departedAt": "2023-01-16T17:21:30", + "reason": "Absconded, still at large", + "legacyReasonCode": "N", + "destination": { + "premises": { + "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", + "name": "Hope House", + "apCode": "NEHOPE1", + "legacyApCode": "Q061" + }, + "moveOnCategory": { + "description": "B&B / Temp / Short-Term Housing", + "legacyMoveOnCategoryCode": "MC05", + "code": "ABC123" + }, + "destinationProvider": { + "description": "Ext - North East Region", + "code": "XYZ456" + } + }, + "keyWorker": { + "staffCode": "N54A001", + "staffIdentifier": 1501234567, + "forenames": "John", + "surname": "Smith", + "username": "JohnSmithNPS" + } + } +} \ No newline at end of file diff --git a/projects/approved-premises-and-delius/src/dev/resources/simulations/mappings/approved-premises-api.json b/projects/approved-premises-and-delius/src/dev/resources/simulations/mappings/approved-premises-api.json index 91bf81f144..8b832b0332 100644 --- a/projects/approved-premises-and-delius/src/dev/resources/simulations/mappings/approved-premises-api.json +++ b/projects/approved-premises-and-delius/src/dev/resources/simulations/mappings/approved-premises-api.json @@ -13,6 +13,19 @@ "bodyFileName": "approved-premises-application-submitted.json" } }, + { + "request": { + "method": "GET", + "urlPath": "/approved-premises-api/events/application-submitted/68df9f6c-3fcb-4ec6-8fcf-96551cd9b080-inactive" + }, + "response": { + "headers": { + "Content-Type": "application/json" + }, + "status": 200, + "bodyFileName": "approved-premises-application-submitted-inactive.json" + } + }, { "request": { "method": "GET", @@ -26,6 +39,19 @@ "bodyFileName": "approved-premises-application-assessed.json" } }, + { + "request": { + "method": "GET", + "urlPath": "/approved-premises-api/events/application-assessed/484b8b5e-6c3b-4400-b200-425bbe410713-inactive" + }, + "response": { + "headers": { + "Content-Type": "application/json" + }, + "status": 200, + "bodyFileName": "approved-premises-application-assessed-inactive.json" + } + }, { "request": { "method": "GET", @@ -52,6 +78,19 @@ "bodyFileName": "approved-premises-booking-made.json" } }, + { + "request": { + "method": "GET", + "urlPath": "/approved-premises-api/events/booking-made/364145f9-0af8-488e-9901-b4c46cd9ba37-inactive" + }, + "response": { + "headers": { + "Content-Type": "application/json" + }, + "status": 200, + "bodyFileName": "approved-premises-booking-made-inactive.json" + } + }, { "request": { "method": "GET", @@ -104,6 +143,19 @@ "bodyFileName": "approved-premises-person-arrived.json" } }, + { + "request": { + "method": "GET", + "urlPath": "/approved-premises-api/events/person-arrived/364145f9-0af8-488e-9901-b4c46cd9ba37-inactive" + }, + "response": { + "headers": { + "Content-Type": "application/json" + }, + "status": 200, + "bodyFileName": "approved-premises-person-arrived-inactive.json" + } + }, { "request": { "method": "GET", @@ -116,6 +168,19 @@ "status": 200, "bodyFileName": "approved-premises-person-departed.json" } + }, + { + "request": { + "method": "GET", + "urlPath": "/approved-premises-api/events/person-departed/364145f9-0af8-488e-9901-b4c46cd9ba37-inactive" + }, + "response": { + "headers": { + "Content-Type": "application/json" + }, + "status": 200, + "bodyFileName": "approved-premises-person-departed-inactive.json" + } } ] } \ No newline at end of file diff --git a/projects/approved-premises-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/MessagingIntegrationInactiveTest.kt b/projects/approved-premises-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/MessagingIntegrationInactiveTest.kt new file mode 100644 index 0000000000..0f8ad4c6f2 --- /dev/null +++ b/projects/approved-premises-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/MessagingIntegrationInactiveTest.kt @@ -0,0 +1,311 @@ +package uk.gov.justice.digital.hmpps + +import com.github.tomakehurst.wiremock.WireMockServer +import org.hamcrest.MatcherAssert.assertThat +import org.hamcrest.Matchers.containsString +import org.hamcrest.Matchers.equalTo +import org.junit.jupiter.api.Assertions.* +import org.junit.jupiter.api.MethodOrderer.OrderAnnotation +import org.junit.jupiter.api.Order +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.TestMethodOrder +import org.mockito.Mockito.verify +import org.mockito.kotlin.times +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.beans.factory.annotation.Value +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc +import org.springframework.boot.test.context.SpringBootTest +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT +import org.springframework.boot.test.mock.mockito.MockBean +import uk.gov.justice.digital.hmpps.data.generator.* +import uk.gov.justice.digital.hmpps.datetime.EuropeLondon +import uk.gov.justice.digital.hmpps.integrations.approvedpremises.EventDetails +import uk.gov.justice.digital.hmpps.integrations.approvedpremises.PersonArrived +import uk.gov.justice.digital.hmpps.integrations.approvedpremises.PersonDeparted +import uk.gov.justice.digital.hmpps.integrations.delius.approvedpremises.referral.entity.PreferredResidence +import uk.gov.justice.digital.hmpps.integrations.delius.approvedpremises.referral.entity.PreferredResidenceRepository +import uk.gov.justice.digital.hmpps.integrations.delius.approvedpremises.referral.entity.ReferralRepository +import uk.gov.justice.digital.hmpps.integrations.delius.approvedpremises.referral.entity.ResidenceRepository +import uk.gov.justice.digital.hmpps.integrations.delius.contact.ContactRepository +import uk.gov.justice.digital.hmpps.integrations.delius.contact.outcome.ContactOutcome +import uk.gov.justice.digital.hmpps.integrations.delius.contact.type.ContactTypeCode +import uk.gov.justice.digital.hmpps.integrations.delius.nonstatutoryintervention.entity.Nsi.Companion.EXT_REF_BOOKING_PREFIX +import uk.gov.justice.digital.hmpps.integrations.delius.nonstatutoryintervention.entity.NsiRepository +import uk.gov.justice.digital.hmpps.integrations.delius.nonstatutoryintervention.entity.NsiTypeCode +import uk.gov.justice.digital.hmpps.integrations.delius.person.address.PersonAddressRepository +import uk.gov.justice.digital.hmpps.integrations.delius.referencedata.ApprovedPremisesCategoryCode +import uk.gov.justice.digital.hmpps.integrations.delius.staff.StaffRepository +import uk.gov.justice.digital.hmpps.integrations.delius.staff.getByCode +import uk.gov.justice.digital.hmpps.messaging.HmppsChannelManager +import uk.gov.justice.digital.hmpps.messaging.crn +import uk.gov.justice.digital.hmpps.messaging.telemetryProperties +import uk.gov.justice.digital.hmpps.resourceloader.ResourceLoader +import uk.gov.justice.digital.hmpps.telemetry.TelemetryService +import uk.gov.justice.digital.hmpps.test.CustomMatchers.isCloseTo +import java.time.LocalDate + +@AutoConfigureMockMvc +@SpringBootTest(webEnvironment = RANDOM_PORT) +@TestMethodOrder(OrderAnnotation::class) +internal class MessagingIntegrationInactiveTest { + @Value("\${messaging.consumer.queue}") + lateinit var queueName: String + + @Autowired + lateinit var channelManager: HmppsChannelManager + + @Autowired + lateinit var wireMockServer: WireMockServer + + @Autowired + lateinit var contactRepository: ContactRepository + + @Autowired + lateinit var nsiRepository: NsiRepository + + @Autowired + lateinit var personAddressRepository: PersonAddressRepository + + @MockBean + lateinit var telemetryService: TelemetryService + + @Autowired + private lateinit var referralRepository: ReferralRepository + + @Autowired + private lateinit var residenceRepository: ResidenceRepository + + @Autowired + private lateinit var preferredResidenceRepository: PreferredResidenceRepository + + @Autowired + private lateinit var staffRepository: StaffRepository + + @Test + fun `application submission with an inactive event creates an alert contact`() { + // Given an application-submitted event + val event = prepEvent("application-submitted-inactive", wireMockServer.port()) + + // When it is received + channelManager.getChannel(queueName).publishAndWait(event) + + // Then it is logged to telemetry + verify(telemetryService).trackEvent("ApplicationSubmitted", event.message.telemetryProperties()) + + // And a contact alert is created + val contact = contactRepository.findAll() + .single { it.person.crn == event.message.crn() && it.type.code == ContactTypeCode.APPLICATION_SUBMITTED.code } + assertThat(contact.alert, equalTo(true)) + assertThat(contact.eventId, equalTo(PersonGenerator.INACTIVE_EVENT.id)) + } + + @Test + fun `application assessed with inactive event creates an alert contact`() { + // Given an application-assessed event + val event = prepEvent("application-assessed-inactive", wireMockServer.port()) + + // When it is received + channelManager.getChannel(queueName).publishAndWait(event) + + // Then it is logged to telemetry + verify(telemetryService).trackEvent("ApplicationAssessed", event.message.telemetryProperties()) + + // And a contact alert is created + val contact = contactRepository.findAll() + .single { it.person.crn == event.message.crn() && it.type.code == ContactTypeCode.APPLICATION_ASSESSED.code } + assertThat(contact.alert, equalTo(true)) + assertThat(contact.description, equalTo("Approved Premises Application Rejected")) + assertThat( + contact.notes, + containsString( + """ + |The application for a placement in an Approved Premises has been assessed for suitability and has been rejected. + |Risk too low + |Details of the application can be found here: + """.trimMargin() + ) + ) + assertThat(contact.eventId, equalTo(PersonGenerator.INACTIVE_EVENT.id)) + } + + @Test + @Order(1) + fun `booking made with inactive event creates referral and contact`() { + // Given a booking-made event + val event = prepEvent("booking-made-inactive", wireMockServer.port()) + + // When it is receivedz + channelManager.getChannel(queueName).publishAndWait(event) + + // Send twice to verify we only create one referral + channelManager.getChannel(queueName).publishAndWait(event) + + // Then it is logged to telemetry + verify(telemetryService, times(2)).trackEvent("BookingMade", event.message.telemetryProperties()) + + // And a contact alert is created + val contact = contactRepository.findAll() + .single { it.person.crn == event.message.crn() && it.type.code == ContactTypeCode.BOOKING_MADE.code } + assertThat(contact.alert, equalTo(true)) + assertThat(contact.description, equalTo("Approved Premises Booking for Hope House")) + assertThat( + contact.notes, + equalTo("To view details of the Approved Premises booking, click here: https://approved-premises-dev.hmpps.service.justice.gov.uk/applications/484b8b5e-6c3b-4400-b200-425bbe410713") + ) + assertThat(contact.locationId, equalTo(OfficeLocationGenerator.DEFAULT.id)) + assertThat(contact.eventId, equalTo(PersonGenerator.INACTIVE_EVENT.id)) + + val referrals = referralRepository.findAll() + .filter { it.personId == contact.person.id && it.createdByUserId == UserGenerator.AUDIT_USER.id && it.eventId == contact.eventId } + assertThat(referrals.size, equalTo(1)) + val referral = referrals.first() + assertThat( + referral.categoryId, + equalTo(ReferenceDataGenerator.REFERRAL_CATEGORIES[ApprovedPremisesCategoryCode.VOLUNTARY_MAPPA.value]?.id) + ) + assertThat(referral.referralGroupId, equalTo(ReferenceDataGenerator.REFERRAL_GROUP.id)) + assertThat(referral.referralDate, equalTo(LocalDate.parse("2022-11-28"))) + assertThat(referral.activeArsonRiskId, equalTo(ReferenceDataGenerator.YN_UNKNOWN.id)) + assertThat(referral.disabilityIssuesId, equalTo(ReferenceDataGenerator.YN_UNKNOWN.id)) + assertThat(referral.singleRoomId, equalTo(ReferenceDataGenerator.YN_UNKNOWN.id)) + assertThat(referral.rohChildrenId, equalTo(ReferenceDataGenerator.RISK_UNKNOWN.id)) + assertThat(referral.rohOthersId, equalTo(ReferenceDataGenerator.RISK_UNKNOWN.id)) + assertThat(referral.rohKnownPersonId, equalTo(ReferenceDataGenerator.RISK_UNKNOWN.id)) + assertThat(referral.rohSelfId, equalTo(ReferenceDataGenerator.RISK_UNKNOWN.id)) + assertThat(referral.rohPublicId, equalTo(ReferenceDataGenerator.RISK_UNKNOWN.id)) + assertThat(referral.rohStaffId, equalTo(ReferenceDataGenerator.RISK_UNKNOWN.id)) + assertThat(referral.rohResidentsId, equalTo(ReferenceDataGenerator.RISK_UNKNOWN.id)) + assertFalse(referral.gangAffiliated) + assertFalse(referral.sexOffender) + } + + @Test + @Order(2) + fun `person arrived with an inactive event creates an alert contact and nsi`() { + // Given a person-arrived event + val event = prepEvent("person-arrived-inactive", wireMockServer.port()) + val arrival = ResourceLoader.file>("approved-premises-person-arrived-inactive") + val details = arrival.eventDetails + + // When it is received + channelManager.getChannel(queueName).publishAndWait(event) + + // Then it is logged to telemetry + verify(telemetryService).trackEvent("PersonArrived", event.message.telemetryProperties()) + + // And a contact alert is created + val contact = contactRepository.findAll() + .single { it.person.crn == event.message.crn() && it.type.code == ContactTypeCode.ARRIVED.code } + assertThat(contact.alert, equalTo(true)) + assertThat( + contact.notes, + equalTo( + """ + Arrived a day late due to rail strike. Informed in advance by COM. + + For more details, click here: https://approved-premises-dev.hmpps.service.justice.gov.uk/applications/484b8b5e-6c3b-4400-b200-425bbe410713 + """.trimIndent() + ) + ) + assertThat(contact.locationId, equalTo(OfficeLocationGenerator.DEFAULT.id)) + assertThat(contact.eventId, equalTo(PersonGenerator.INACTIVE_EVENT.id)) + + // And a residence NSI is created + val nsi = nsiRepository.findAll() + .single { it.person.crn == event.message.crn() && it.type.code == NsiTypeCode.APPROVED_PREMISES_RESIDENCE.code } + assertThat( + nsi.notes, + equalTo( + """ + Arrived a day late due to rail strike. Informed in advance by COM. + + For more details, click here: https://approved-premises-dev.hmpps.service.justice.gov.uk/applications/484b8b5e-6c3b-4400-b200-425bbe410713 + """.trimIndent() + ) + ) + assertThat(nsi.externalReference, equalTo(EXT_REF_BOOKING_PREFIX + details.bookingId)) + assertThat(nsi.referralDate, equalTo(details.applicationSubmittedOn)) + assertNotNull(nsi.actualStartDate) + assertThat( + nsi.actualStartDate!!.withZoneSameInstant(EuropeLondon), + equalTo(details.arrivedAt.withZoneSameInstant(EuropeLondon)) + ) + + // And the main address is updated to be that of the approved premises - consequently any existing main address is made previous + val addresses = + personAddressRepository.findAll().filter { it.personId == PersonGenerator.PERSON_INACTIVE_EVENT.id } + .associateBy { it.id == AddressGenerator.INACTIVE_PERSON_ADDRESS.id } + assertThat(addresses.size, equalTo(2)) + val previous = addresses[true]!! + assertThat(previous.endDate, equalTo(details.arrivedAt.toLocalDate())) + assertThat(previous.status.code, equalTo("P")) + + val main = addresses[false]!! + val ap = AddressGenerator.Q001 + assertThat(main.status.code, equalTo("M")) + assertNull(main.endDate) + assertThat(main.startDate, equalTo(details.arrivedAt.toLocalDate())) + assertThat(main.buildingName, equalTo(details.premises.name)) + assertThat(main.addressNumber, equalTo(ap.addressNumber)) + assertThat(main.streetName, equalTo(ap.streetName)) + assertThat(main.town, equalTo(ap.town)) + assertThat(main.postcode, equalTo(ap.postcode)) + assertThat(main.telephoneNumber, equalTo(ap.telephoneNumber)) + + val keyWorker = staffRepository.getByCode("N54A001") + val residences = residenceRepository.findAll().filter { it.personId == contact.person.id } + assertThat(residences.size, equalTo(1)) + val residence = residences.first() + assertThat(residence.arrivalDate, equalTo(nsi.actualStartDate)) + assertThat(residence.keyWorkerStaffId, equalTo(keyWorker.id)) + } + + @Test + @Order(3) + fun `person departed with inactive event creates a contact and closes nsi`() { + val event = prepEvent("person-departed-inactive", wireMockServer.port()) + val departure = ResourceLoader.file>("approved-premises-person-departed") + val details = departure.eventDetails + + channelManager.getChannel(queueName).publishAndWait(event) + + verify(telemetryService).trackEvent("PersonDeparted", event.message.telemetryProperties()) + + val contact = contactRepository.findAll() + .single { it.person.crn == event.message.crn() && it.type.code == ContactTypeCode.DEPARTED.code } + assertThat(contact.alert, equalTo(false)) + assertThat( + contact.notes, + equalTo("For details, see the referral on the AP Service: ${details.applicationUrl}") + ) + assertThat(contact.locationId, equalTo(OfficeLocationGenerator.DEFAULT.id)) + assertThat(contact.outcome?.code, equalTo("AP_N")) + assertThat(contact.eventId, equalTo(PersonGenerator.INACTIVE_EVENT.id)) + assertThat(contact.description, equalTo("Departed from Hope House")) + + val nsi = nsiRepository.findByPersonIdAndExternalReference( + contact.person.id, + EXT_REF_BOOKING_PREFIX + details.bookingId + ) + assertNotNull(nsi) + assertNotNull(nsi!!.actualEndDate) + assertThat(nsi.actualEndDate!!, isCloseTo(details.departedAt)) + assertThat(nsi.active, equalTo(false)) + assertThat(nsi.outcome!!.code, equalTo("APRC")) + + val addresses = + personAddressRepository.findAll().filter { it.personId == PersonGenerator.PERSON_INACTIVE_EVENT.id } + assertThat(addresses.size, equalTo(2)) + addresses.forEach { + assertNotNull(it.endDate) + assertThat(it.status.code, equalTo("P")) + } + + assertNull(personAddressRepository.findMainAddress(PersonGenerator.PERSON_INACTIVE_EVENT.id)) + + val residence = residenceRepository.findAll().first { it.personId == contact.person.id } + assertThat(residence.departureDate, equalTo(nsi.actualEndDate)) + assertThat(residence.departureReasonId, equalTo(ReferenceDataGenerator.ORDER_EXPIRED.id)) + assertThat(residence.moveOnCategoryId, equalTo(ReferenceDataGenerator.MC05.id)) + } +} diff --git a/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/approvedpremises/referral/entity/Referral.kt b/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/approvedpremises/referral/entity/Referral.kt index 655a11b384..3c195f2d15 100644 --- a/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/approvedpremises/referral/entity/Referral.kt +++ b/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/approvedpremises/referral/entity/Referral.kt @@ -209,16 +209,10 @@ fun ReferralSourceRepository.getByCode(code: String) = findByCode(code) interface EventRepository : JpaRepository { fun findByPersonIdAndNumber(personId: Long, number: String): Event? - @Query("select e from Event e where e.personId = :personId and e.number = :number and e.active = true") - fun findActiveByPersonIdAndNumber(personId: Long, number: String): Event? - @Lock(LockModeType.PESSIMISTIC_READ) @Query("select e.id from Event e where e.id = :id") fun findForUpdate(id: Long): Long } -fun EventRepository.getActiveEvent(personId: Long, number: String) = findActiveByPersonIdAndNumber(personId, number) - ?: throw IgnorableMessageException("Active Event Not Found", mapOf("eventNumber" to number)) - fun EventRepository.getEvent(personId: Long, number: String) = findByPersonIdAndNumber(personId, number) ?: throw IgnorableMessageException("Event Not Found", mapOf("eventNumber" to number)) diff --git a/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/ApprovedPremisesService.kt b/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/ApprovedPremisesService.kt index c055fc43d2..a266e33093 100644 --- a/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/ApprovedPremisesService.kt +++ b/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/ApprovedPremisesService.kt @@ -5,11 +5,8 @@ import uk.gov.justice.digital.hmpps.integrations.approvedpremises.ApprovedPremis import uk.gov.justice.digital.hmpps.integrations.delius.approvedpremises.ApprovedPremisesRepository import uk.gov.justice.digital.hmpps.integrations.delius.approvedpremises.getApprovedPremises import uk.gov.justice.digital.hmpps.integrations.delius.approvedpremises.referral.entity.EventRepository -import uk.gov.justice.digital.hmpps.integrations.delius.approvedpremises.referral.entity.getActiveEvent import uk.gov.justice.digital.hmpps.integrations.delius.approvedpremises.referral.entity.getEvent -import uk.gov.justice.digital.hmpps.integrations.delius.contact.type.ContactTypeCode.APPLICATION_ASSESSED -import uk.gov.justice.digital.hmpps.integrations.delius.contact.type.ContactTypeCode.APPLICATION_SUBMITTED -import uk.gov.justice.digital.hmpps.integrations.delius.contact.type.ContactTypeCode.APPLICATION_WITHDRAWN +import uk.gov.justice.digital.hmpps.integrations.delius.contact.type.ContactTypeCode.* import uk.gov.justice.digital.hmpps.integrations.delius.person.PersonRepository import uk.gov.justice.digital.hmpps.integrations.delius.person.getByCrn import uk.gov.justice.digital.hmpps.integrations.delius.staff.StaffRepository @@ -32,7 +29,7 @@ class ApprovedPremisesService( fun applicationSubmitted(event: HmppsDomainEvent) { val details = approvedPremisesApiClient.getApplicationSubmittedDetails(event.url()).eventDetails val person = personRepository.getByCrn(event.crn()) - val dEvent = eventRepository.getActiveEvent(person.id, details.eventNumber) + val dEvent = eventRepository.getEvent(person.id, details.eventNumber) contactService.createContact( ContactDetails( date = details.submittedAt, @@ -50,7 +47,7 @@ class ApprovedPremisesService( fun applicationAssessed(event: HmppsDomainEvent) { val details = approvedPremisesApiClient.getApplicationAssessedDetails(event.url()).eventDetails val person = personRepository.getByCrn(event.crn()) - val dEvent = eventRepository.getActiveEvent(person.id, details.eventNumber) + val dEvent = eventRepository.getEvent(person.id, details.eventNumber) contactService.createContact( ContactDetails( date = details.assessedAt, diff --git a/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/NsiService.kt b/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/NsiService.kt index 484d1d94ab..b4a82e68b8 100644 --- a/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/NsiService.kt +++ b/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/NsiService.kt @@ -6,20 +6,10 @@ import uk.gov.justice.digital.hmpps.integrations.approvedpremises.PersonArrived import uk.gov.justice.digital.hmpps.integrations.approvedpremises.PersonDeparted import uk.gov.justice.digital.hmpps.integrations.delius.approvedpremises.entity.ApprovedPremises import uk.gov.justice.digital.hmpps.integrations.delius.approvedpremises.referral.entity.EventRepository -import uk.gov.justice.digital.hmpps.integrations.delius.approvedpremises.referral.entity.getActiveEvent +import uk.gov.justice.digital.hmpps.integrations.delius.approvedpremises.referral.entity.getEvent import uk.gov.justice.digital.hmpps.integrations.delius.contact.outcome.ContactOutcome import uk.gov.justice.digital.hmpps.integrations.delius.contact.type.ContactTypeCode -import uk.gov.justice.digital.hmpps.integrations.delius.nonstatutoryintervention.entity.Nsi -import uk.gov.justice.digital.hmpps.integrations.delius.nonstatutoryintervention.entity.NsiManager -import uk.gov.justice.digital.hmpps.integrations.delius.nonstatutoryintervention.entity.NsiManagerRepository -import uk.gov.justice.digital.hmpps.integrations.delius.nonstatutoryintervention.entity.NsiRepository -import uk.gov.justice.digital.hmpps.integrations.delius.nonstatutoryintervention.entity.NsiStatusCode -import uk.gov.justice.digital.hmpps.integrations.delius.nonstatutoryintervention.entity.NsiStatusRepository -import uk.gov.justice.digital.hmpps.integrations.delius.nonstatutoryintervention.entity.NsiTypeCode -import uk.gov.justice.digital.hmpps.integrations.delius.nonstatutoryintervention.entity.NsiTypeRepository -import uk.gov.justice.digital.hmpps.integrations.delius.nonstatutoryintervention.entity.TransferReasonRepository -import uk.gov.justice.digital.hmpps.integrations.delius.nonstatutoryintervention.entity.getByCode -import uk.gov.justice.digital.hmpps.integrations.delius.nonstatutoryintervention.entity.getNsiTransferReason +import uk.gov.justice.digital.hmpps.integrations.delius.nonstatutoryintervention.entity.* import uk.gov.justice.digital.hmpps.integrations.delius.person.Person import uk.gov.justice.digital.hmpps.integrations.delius.referencedata.ReferenceDataRepository import uk.gov.justice.digital.hmpps.integrations.delius.referencedata.referralCompleted @@ -92,7 +82,7 @@ class NsiService( ).joinToString(System.lineSeparator() + System.lineSeparator()) ), person = person, - eventId = eventRepository.getActiveEvent(person.id, details.eventNumber).id, + eventId = eventRepository.getEvent(person.id, details.eventNumber).id, staff = staff, team = team, probationAreaCode = ap.probationArea.code @@ -118,7 +108,7 @@ class NsiService( createAlert = false ), person = person, - eventId = eventRepository.getActiveEvent(person.id, details.eventNumber).id, + eventId = eventRepository.getEvent(person.id, details.eventNumber).id, team = teamRepository.getApprovedPremisesTeam(details.premises.legacyApCode), staff = staffRepository.getByCode(details.keyWorker.staffCode), probationAreaCode = ap.probationArea.code diff --git a/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/ReferralService.kt b/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/ReferralService.kt index edf3356325..5a2bda9e33 100644 --- a/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/ReferralService.kt +++ b/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/ReferralService.kt @@ -50,7 +50,7 @@ class ReferralService( ) { fun bookingMade(crn: String, details: BookingMade, ap: ApprovedPremises) { val person = personRepository.getByCrn(crn) - val event = eventRepository.getActiveEvent(person.id, details.eventNumber) + val event = eventRepository.getEvent(person.id, details.eventNumber) val apTeam = teamRepository.getApprovedPremisesTeam(ap.code.code) val apStaff = staffRepository.getUnallocated(apTeam.code) val rTeam = teamRepository.getUnallocatedTeam(ap.probationArea.code) diff --git a/projects/approved-premises-and-delius/src/test/kotlin/uk/gov/justice/digital/hmpps/service/ApprovedPremisesServiceTest.kt b/projects/approved-premises-and-delius/src/test/kotlin/uk/gov/justice/digital/hmpps/service/ApprovedPremisesServiceTest.kt index a0cbddb468..a043d549dc 100644 --- a/projects/approved-premises-and-delius/src/test/kotlin/uk/gov/justice/digital/hmpps/service/ApprovedPremisesServiceTest.kt +++ b/projects/approved-premises-and-delius/src/test/kotlin/uk/gov/justice/digital/hmpps/service/ApprovedPremisesServiceTest.kt @@ -293,7 +293,7 @@ internal class ApprovedPremisesServiceTest { val crn = personArrivedEvent.crn() val person = givenAPerson(crn) val manager = givenAPersonManager(person) - givenAnEvent(person, "11") + givenAnActiveEvent(person, "11") val staff = givenStaff() val approvedPremisesTeam = givenApprovedPremisesTeam() val details = givenPersonArrivedDetails(keyWorker = staff) @@ -422,9 +422,16 @@ internal class ApprovedPremisesServiceTest { return manager } + private fun givenAnActiveEvent(person: Person, eventNumber: String): Event { + val event = PersonGenerator.generateEvent(eventNumber, person.id) + whenever(eventRepository.findByPersonIdAndNumber(person.id, eventNumber)) + .thenReturn(event) + return event + } + private fun givenAnEvent(person: Person, eventNumber: String): Event { val event = PersonGenerator.generateEvent(eventNumber, person.id) - whenever(eventRepository.findActiveByPersonIdAndNumber(person.id, eventNumber)) + whenever(eventRepository.findByPersonIdAndNumber(person.id, eventNumber)) .thenReturn(event) return event } diff --git a/projects/prison-custody-status-to-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/EventGenerator.kt b/projects/prison-custody-status-to-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/EventGenerator.kt index 4de1d1dbf1..6c7f2d9c53 100644 --- a/projects/prison-custody-status-to-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/EventGenerator.kt +++ b/projects/prison-custody-status-to-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/EventGenerator.kt @@ -66,7 +66,7 @@ object EventGenerator { institution: Institution?, custodialStatusCode: CustodialStatusCode = CustodialStatusCode.RELEASED_ON_LICENCE, lengthInDays: Long = 365, - releaseDate: ZonedDateTime = ZonedDateTime.now().minusMonths(6), + releaseDate: ZonedDateTime = NotificationGenerator.PRISONER_RECEIVED.message.occurredAt.minusMonths(6), releaseType: ReleaseTypeCode = ReleaseTypeCode.ADULT_LICENCE ): Event { val event = custodialEvent(person, institution, custodialStatusCode, lengthInDays = lengthInDays) From 22a0d659d0aa95598e5f16405c20b91b1380e276 Mon Sep 17 00:00:00 2001 From: pmcphee77 <150798161+pmcphee77@users.noreply.github.com> Date: Mon, 20 May 2024 11:25:22 +0100 Subject: [PATCH 06/10] PI-2094: Added offender detail all endpoint (#3803) * PI-2094: Added offender detail all endpoint --- .../justice/digital/hmpps/data/DataLoader.kt | 14 +- .../digital/hmpps/data/entity/Entities.kt | 3 - .../hmpps/data/generator/PersonGenerator.kt | 69 ++++- .../data/generator/ReferenceDataGenerator.kt | 24 ++ .../hmpps/data/generator/StaffGenerator.kt | 39 ++- .../digital/hmpps/OffenderIntegrationTest.kt | 146 ++++++++++- .../digital/hmpps/api/model/Offender.kt | 221 ++++++++++++++++ .../hmpps/api/model/OffenderDetailSummary.kt | 103 -------- .../hmpps/api/model/ProbationRecord.kt | 36 --- .../api/resource/ProbationRecordResource.kt | 6 + .../delius/person/entity/Person.kt | 145 ++++++++++- .../delius/person/entity/PersonManager.kt | 105 +++++++- .../delius/provider/entity/ProbationArea.kt | 12 +- .../delius/service/OffenderService.kt | 245 +++++++++++++----- 14 files changed, 916 insertions(+), 252 deletions(-) create mode 100644 projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/model/Offender.kt delete mode 100644 projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/model/OffenderDetailSummary.kt diff --git a/projects/court-case-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/DataLoader.kt b/projects/court-case-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/DataLoader.kt index 4dc264c52b..ce27b61509 100644 --- a/projects/court-case-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/DataLoader.kt +++ b/projects/court-case-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/DataLoader.kt @@ -34,7 +34,8 @@ class DataLoader( DocumentEntityGenerator.INSTITUTIONAL_REPORT_TYPE, DocumentEntityGenerator.INSTITUTIONAL_REPORT, DocumentEntityGenerator.R_INSTITUTION, - + AreaGenerator.PARTITION_AREA, + ProviderEmployeeGenerator.PROVIDER_EMPLOYEE, ProviderGenerator.DEFAULT, LDUGenerator.DEFAULT, BoroughGenerator.DEFAULT, @@ -74,17 +75,22 @@ class DataLoader( ReferenceDataGenerator.SECOND_NATIONALITY, ReferenceDataGenerator.SEXUAL_ORIENTATION, ReferenceDataGenerator.TITLE, - PersonGenerator.PARTITION_AREA, + ReferenceDataGenerator.DEFAULT_ADDRESS_TYPE, + ReferenceDataGenerator.DEFAULT_ADDRESS_STATUS, + ReferenceDataGenerator.DEFAULT_ALLOCATION_REASON, + ReferenceDataGenerator.DEFAULT_TIER, PersonGenerator.NEW_TO_PROBATION, PersonGenerator.CURRENTLY_MANAGED, PersonGenerator.PREVIOUSLY_MANAGED, PersonGenerator.NO_SENTENCE, PersonGenerator.PROVISION_1, PersonGenerator.DISABILITY_1, - PersonGenerator.PREVIOUS_CONVICTION_DOC + PersonGenerator.PREVIOUS_CONVICTION_DOC, + PersonGenerator.ADDRESS, + PersonGenerator.ALIAS ) - em.saveAll(StaffGenerator.ALLOCATED, StaffGenerator.UNALLOCATED) + em.saveAll(StaffGenerator.ALLOCATED, StaffGenerator.UNALLOCATED, StaffGenerator.OFFICER) em.saveAll( PersonGenerator.generatePersonManager(PersonGenerator.NEW_TO_PROBATION), diff --git a/projects/court-case-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/entity/Entities.kt b/projects/court-case-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/entity/Entities.kt index bd5088286b..de503b1b76 100644 --- a/projects/court-case-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/entity/Entities.kt +++ b/projects/court-case-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/entity/Entities.kt @@ -9,9 +9,6 @@ import org.hibernate.annotations.Immutable import org.hibernate.type.YesNoConverter import java.time.LocalDate -@Entity -class AddressAssessment(@Id val addressAssessmentId: Long, val assessmentDate: LocalDate) - @Entity class ApprovedPremisesReferral( @Id val approvedPremisesReferralId: Long, diff --git a/projects/court-case-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/PersonGenerator.kt b/projects/court-case-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/PersonGenerator.kt index a13fd18b41..8af27a30c2 100644 --- a/projects/court-case-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/PersonGenerator.kt +++ b/projects/court-case-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/PersonGenerator.kt @@ -1,6 +1,11 @@ package uk.gov.justice.digital.hmpps.data.generator import uk.gov.justice.digital.hmpps.api.model.DocumentType +import uk.gov.justice.digital.hmpps.data.generator.AreaGenerator.PARTITION_AREA +import uk.gov.justice.digital.hmpps.data.generator.ReferenceDataGenerator.DEFAULT_ADDRESS_STATUS +import uk.gov.justice.digital.hmpps.data.generator.ReferenceDataGenerator.DEFAULT_ADDRESS_TYPE +import uk.gov.justice.digital.hmpps.data.generator.ReferenceDataGenerator.DEFAULT_ALLOCATION_REASON +import uk.gov.justice.digital.hmpps.data.generator.ReferenceDataGenerator.DEFAULT_TIER import uk.gov.justice.digital.hmpps.data.generator.ReferenceDataGenerator.DISABILITY_CONDITION_1 import uk.gov.justice.digital.hmpps.data.generator.ReferenceDataGenerator.DISABILITY_TYPE_1 import uk.gov.justice.digital.hmpps.data.generator.ReferenceDataGenerator.ETHNICITY @@ -20,7 +25,7 @@ import java.time.LocalDate import java.time.ZonedDateTime object PersonGenerator { - val PARTITION_AREA = PartitionArea(IdGenerator.getAndIncrement(), "Partition Area") + val NEW_TO_PROBATION = generate("N123456") val CURRENTLY_MANAGED = generate("C123456", currentDisposal = true) val PREVIOUSLY_MANAGED = generate("P123456") @@ -35,6 +40,9 @@ object PersonGenerator { null ) + val ADDRESS = generateAddress(CURRENTLY_MANAGED.id, false) + val ALIAS = generatePersonAlias(CURRENTLY_MANAGED) + fun generate( crn: String, softDeleted: Boolean = false, @@ -81,17 +89,41 @@ object PersonGenerator { immigrationNumber = "IMA123", mostRecentPrisonerNumber = "PRS123", previousSurname = "Previous", - title = TITLE + title = TITLE, + offenderManagers = emptyList(), + restrictionMessage = "restrictionMessage", + exclusionMessage = "exclusionMessage", + currentTier = DEFAULT_TIER ) fun generatePersonManager(person: Person) = PersonManager( - IdGenerator.getAndIncrement(), - person, - TeamGenerator.DEFAULT, - StaffGenerator.ALLOCATED, - ProviderGenerator.DEFAULT, - ZonedDateTime.now() + id = IdGenerator.getAndIncrement(), + trustProviderFlag = false, + person = person, + team = TeamGenerator.DEFAULT, + staff = StaffGenerator.ALLOCATED, + provider = ProviderGenerator.DEFAULT, + date = ZonedDateTime.now(), + allocationReason = DEFAULT_ALLOCATION_REASON, + officer = StaffGenerator.OFFICER, + partitionArea = PARTITION_AREA, + startDate = LocalDate.now().minusDays(2), + staffEmployeeId = StaffGenerator.ALLOCATED.id, + providerEmployee = ProviderEmployeeGenerator.PROVIDER_EMPLOYEE + ) + + fun generatePersonAlias(person: Person) = + OffenderAlias( + aliasID = IdGenerator.getAndIncrement(), + personId = person.id, + dateOfBirth = LocalDate.of(1968, 1, 1), + firstName = "Bob", + secondName = "Reg", + thirdName = "Xavier", + surname = "Potts", + gender = GENDER_MALE, + softDeleted = false ) fun generateProvision(personId: Long, end: LocalDate?) = Provision( @@ -115,4 +147,25 @@ object PersonGenerator { notes = null, finishDate = end, ) + + fun generateAddress(personId: Long, softDeleted: Boolean) = PersonAddress( + id = IdGenerator.getAndIncrement(), + personId = personId, + type = DEFAULT_ADDRESS_TYPE, + status = DEFAULT_ADDRESS_STATUS, + streetName = "A Street", + town = "A town", + county = "A county", + postcode = "NE209XL", + telephoneNumber = "089876765", + buildingName = "The building", + district = "A District", + addressNumber = "20", + noFixedAbode = false, + typeVerified = true, + startDate = LocalDate.now().minusDays(1), + endDate = null, + softDeleted = false, + createdDatetime = ZonedDateTime.now().minusDays(1), + ) } diff --git a/projects/court-case-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/ReferenceDataGenerator.kt b/projects/court-case-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/ReferenceDataGenerator.kt index 0dbb4898f9..1baf046dda 100644 --- a/projects/court-case-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/ReferenceDataGenerator.kt +++ b/projects/court-case-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/ReferenceDataGenerator.kt @@ -175,4 +175,28 @@ object ReferenceDataGenerator { "Mr", IdGenerator.getAndIncrement() ) + + val DEFAULT_ADDRESS_TYPE = ReferenceData( + "AT", + "Address Type", + IdGenerator.getAndIncrement() + ) + + val DEFAULT_ADDRESS_STATUS = ReferenceData( + "AS", + "Address Status", + IdGenerator.getAndIncrement() + ) + + val DEFAULT_ALLOCATION_REASON = ReferenceData( + "AR", + "Allocation Reason", + IdGenerator.getAndIncrement() + ) + + val DEFAULT_TIER = ReferenceData( + "B2", + "B2", + IdGenerator.getAndIncrement() + ) } diff --git a/projects/court-case-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/StaffGenerator.kt b/projects/court-case-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/StaffGenerator.kt index e3b116013d..41aaa24533 100644 --- a/projects/court-case-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/StaffGenerator.kt +++ b/projects/court-case-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/StaffGenerator.kt @@ -1,21 +1,46 @@ package uk.gov.justice.digital.hmpps.data.generator -import uk.gov.justice.digital.hmpps.integrations.delius.provider.entity.Borough -import uk.gov.justice.digital.hmpps.integrations.delius.provider.entity.District -import uk.gov.justice.digital.hmpps.integrations.delius.provider.entity.LocalDeliveryUnit -import uk.gov.justice.digital.hmpps.integrations.delius.provider.entity.ProbationAreaEntity -import uk.gov.justice.digital.hmpps.integrations.delius.provider.entity.Staff -import uk.gov.justice.digital.hmpps.integrations.delius.provider.entity.Team +import uk.gov.justice.digital.hmpps.integrations.delius.person.entity.Officer +import uk.gov.justice.digital.hmpps.integrations.delius.person.entity.OfficerPk +import uk.gov.justice.digital.hmpps.integrations.delius.person.entity.PartitionArea +import uk.gov.justice.digital.hmpps.integrations.delius.person.entity.ProviderEmployee +import uk.gov.justice.digital.hmpps.integrations.delius.provider.entity.* object StaffGenerator { val UNALLOCATED = generate("N01UATU") val ALLOCATED = generate("N01ABBA") + val OFFICER = generateOfficer() fun generate(code: String, id: Long = IdGenerator.getAndIncrement()) = Staff(code, "Bob", "Micheal", "Smith", id) + + fun generateOfficer() = + Officer( + id = OfficerPk( + trustProviderFlag = 0, + staffEmployeeId = ALLOCATED.id + ), + surname = "OffSurname", + forename = "Off1", + forename2 = "Off2" + ) } object ProviderGenerator { val DEFAULT = generate() - fun generate(id: Long = IdGenerator.getAndIncrement()) = ProbationAreaEntity(true, "London", "LN1", null, id) + fun generate(id: Long = IdGenerator.getAndIncrement()) = ProbationAreaEntity(true, "London", "LN1", null, true, id) +} + +object AreaGenerator { + val PARTITION_AREA = PartitionArea(IdGenerator.getAndIncrement(), "Partition Area") +} + +object ProviderEmployeeGenerator { + val PROVIDER_EMPLOYEE = generateProviderEmployee() + fun generateProviderEmployee() = ProviderEmployee( + providerEmployeeId = IdGenerator.getAndIncrement(), + surname = "ProvEmpSurname", + forename = "ProvEmpForename1", + forename2 = "ProvEmpForename2" + ) } object LDUGenerator { diff --git a/projects/court-case-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/OffenderIntegrationTest.kt b/projects/court-case-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/OffenderIntegrationTest.kt index 1e401d34c8..ea1483d228 100644 --- a/projects/court-case-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/OffenderIntegrationTest.kt +++ b/projects/court-case-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/OffenderIntegrationTest.kt @@ -12,12 +12,17 @@ import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status import software.amazon.awssdk.utils.ImmutableMap import uk.gov.justice.digital.hmpps.api.model.* +import uk.gov.justice.digital.hmpps.data.generator.AreaGenerator.PARTITION_AREA import uk.gov.justice.digital.hmpps.data.generator.PersonGenerator -import uk.gov.justice.digital.hmpps.data.generator.PersonGenerator.PARTITION_AREA +import uk.gov.justice.digital.hmpps.data.generator.PersonGenerator.ADDRESS import uk.gov.justice.digital.hmpps.data.generator.PersonGenerator.PREVIOUS_CONVICTION_DOC +import uk.gov.justice.digital.hmpps.data.generator.ProviderGenerator +import uk.gov.justice.digital.hmpps.data.generator.ReferenceDataGenerator.DEFAULT_ALLOCATION_REASON import uk.gov.justice.digital.hmpps.data.generator.ReferenceDataGenerator.DISABILITY_TYPE_1 import uk.gov.justice.digital.hmpps.data.generator.ReferenceDataGenerator.PROVISION_TYPE_1 import uk.gov.justice.digital.hmpps.data.generator.ReferenceDataGenerator.RELIGION +import uk.gov.justice.digital.hmpps.data.generator.StaffGenerator.ALLOCATED +import uk.gov.justice.digital.hmpps.data.generator.TeamGenerator import uk.gov.justice.digital.hmpps.test.MockMvcExtensions.contentAsJson import uk.gov.justice.digital.hmpps.test.MockMvcExtensions.withToken import java.time.LocalDate @@ -29,7 +34,7 @@ internal class OffenderIntegrationTest { lateinit var mockMvc: MockMvc @Test - fun `API call retuns probation record with active sentence`() { + fun `Summary API call retuns probation record with active sentence`() { val crn = PersonGenerator.CURRENTLY_MANAGED.crn val detailResponse = mockMvc .perform(get("/probation-case/$crn").withToken()) @@ -116,14 +121,14 @@ internal class OffenderIntegrationTest { } @Test - fun `API call probation record not found`() { + fun `Summary API call probation record not found`() { mockMvc .perform(get("/probation-case/A123456").withToken()) .andExpect(status().isNotFound) } @Test - fun `API call retuns probation record with no active sentence`() { + fun `Summary API call retuns probation record with no active sentence`() { val crn = PersonGenerator.NO_SENTENCE.crn val detailResponse = mockMvc .perform(get("/probation-case/$crn").withToken()) @@ -132,4 +137,137 @@ internal class OffenderIntegrationTest { assertThat(detailResponse.currentDisposal, equalTo("0")) assertThat(detailResponse.activeProbationManagedSentence, equalTo(false)) } + + @Test + fun `Detail API call retuns probation record with active sentence`() { + val crn = PersonGenerator.CURRENTLY_MANAGED.crn + val detailResponse = mockMvc + .perform(get("/probation-case/$crn/all").withToken()) + .andExpect(status().is2xxSuccessful) + .andReturn().response.contentAsJson() + assertThat(detailResponse.preferredName, equalTo("Other name")) + assertThat(detailResponse.softDeleted, equalTo(false)) + assertThat(detailResponse.activeProbationManagedSentence, equalTo(true)) + assertThat( + detailResponse.contactDetails.phoneNumbers, equalTo( + listOf( + PhoneNumber( + PersonGenerator.CURRENTLY_MANAGED.telephoneNumber, + PhoneTypes.TELEPHONE.name + ), PhoneNumber( + PersonGenerator.CURRENTLY_MANAGED.mobileNumber, + PhoneTypes.MOBILE.name + ) + ) + ) + ) + assertThat(detailResponse.contactDetails.addresses[0].addressNumber, equalTo(ADDRESS.addressNumber)) + assertThat(detailResponse.contactDetails.addresses[0].county, equalTo(ADDRESS.county)) + assertThat(detailResponse.contactDetails.addresses[0].status, equalTo(ADDRESS.status.keyValueOf())) + assertThat(detailResponse.contactDetails.allowSMS, equalTo(true)) + assertThat(detailResponse.contactDetails.emailAddresses, equalTo(listOf("test@test.none"))) + assertThat(detailResponse.currentDisposal, equalTo("1")) + assertThat(detailResponse.currentExclusion, equalTo(false)) + assertThat(detailResponse.currentRestriction, equalTo(false)) + assertThat(detailResponse.exclusionMessage, equalTo("exclusionMessage")) + assertThat(detailResponse.restrictionMessage, equalTo("restrictionMessage")) + assertThat(detailResponse.dateOfBirth, equalTo(LocalDate.of(1977, 8, 12))) + assertThat(detailResponse.firstName, equalTo("TestForename")) + assertThat(detailResponse.middleNames, equalTo(listOf("MiddleName", "OtherMiddleName"))) + assertThat(detailResponse.offenderId, equalTo(PersonGenerator.CURRENTLY_MANAGED.id)) + assertThat(detailResponse.offenderProfile.genderIdentity, equalTo("Some gender identity")) + assertThat( + detailResponse.offenderProfile.selfDescribedGenderIdentity, + equalTo("Some self described gender identity") + ) + assertThat( + detailResponse.offenderProfile.selfDescribedGenderIdentity, + equalTo("Some self described gender identity") + ) + assertThat( + detailResponse.offenderProfile.disabilities[0].disabilityType.description, + equalTo(DISABILITY_TYPE_1.description) + ) + assertThat(detailResponse.offenderProfile.ethnicity, equalTo("Some ethnicity")) + assertThat(detailResponse.offenderProfile.immigrationStatus, equalTo("Some immigration status")) + assertThat(detailResponse.offenderProfile.nationality, equalTo("British")) + assertThat(detailResponse.offenderProfile.offenderDetails, equalTo("Some details")) + assertThat( + detailResponse.offenderProfile.offenderLanguages, equalTo( + OffenderLanguages( + languageConcerns = "A concern", + primaryLanguage = "English", + requiresInterpreter = false + ) + ) + ) + assertThat( + detailResponse.offenderProfile.previousConviction, equalTo( + PreviousConviction( + convictionDate = PREVIOUS_CONVICTION_DOC.createdAt.toLocalDate(), + detail = ImmutableMap.of("documentName", PREVIOUS_CONVICTION_DOC.name) + ) + ) + ) + assertThat( + detailResponse.offenderProfile.provisions[0].provisionType.description, + equalTo(PROVISION_TYPE_1.description) + ) + + assertThat(detailResponse.offenderAliases[0].dateOfBirth, equalTo(LocalDate.of(1968, 1, 1))) + assertThat(detailResponse.offenderAliases[0].firstName, equalTo("Bob")) + assertThat(detailResponse.offenderAliases[0].middleNames, equalTo(listOf("Reg", "Xavier"))) + + assertThat( + detailResponse.offenderManagers[0].providerEmployee, + equalTo(Human("ProvEmpForename1 ProvEmpForename2", "ProvEmpSurname")) + ) + assertThat(detailResponse.offenderManagers[0].trustOfficer, equalTo(Human("Off1 Off2", "OffSurname"))) + assertThat( + detailResponse.offenderManagers[0].probationArea.description, + equalTo(ProviderGenerator.DEFAULT.description) + ) + assertThat( + detailResponse.offenderManagers[0].staff, + equalTo(StaffHuman(ALLOCATED.code, ALLOCATED.forename, ALLOCATED.surname, false)) + ) + assertThat(detailResponse.offenderManagers[0].allocationReason, equalTo(DEFAULT_ALLOCATION_REASON.keyValueOf())) + assertThat(detailResponse.offenderManagers[0].partitionArea, equalTo(PARTITION_AREA.area)) + assertThat(detailResponse.offenderManagers[0].team.code.trim(), equalTo(TeamGenerator.DEFAULT.code.trim())) + assertThat(detailResponse.offenderManagers[0].team.description, equalTo(TeamGenerator.DEFAULT.description)) + assertThat(detailResponse.offenderProfile.religion, equalTo(RELIGION.description)) + assertThat(detailResponse.offenderProfile.remandStatus, equalTo("Remand Status")) + assertThat(detailResponse.offenderProfile.riskColour, equalTo("RED")) + assertThat(detailResponse.offenderProfile.secondaryNationality, equalTo("French")) + assertThat(detailResponse.offenderProfile.sexualOrientation, equalTo("A sexual orientation")) + assertThat(detailResponse.otherIds.crn, equalTo(crn)) + assertThat(detailResponse.otherIds.niNumber, equalTo("JK002213K")) + assertThat(detailResponse.otherIds.pncNumber, equalTo("1234567890123")) + assertThat(detailResponse.otherIds.nomsNumber, equalTo("NOMS123")) + assertThat(detailResponse.otherIds.croNumber, equalTo("CRO123")) + assertThat(detailResponse.otherIds.immigrationNumber, equalTo("IMA123")) + assertThat(detailResponse.otherIds.mostRecentPrisonerNumber, equalTo("PRS123")) + assertThat(detailResponse.partitionArea, equalTo(PARTITION_AREA.area)) + assertThat(detailResponse.currentTier, equalTo("B2")) + assertThat(detailResponse.previousSurname, equalTo("Previous")) + assertThat(detailResponse.surname, equalTo("TestSurname")) + } + + @Test + fun `Detail API call probation record not found`() { + mockMvc + .perform(get("/probation-case/A123456/all").withToken()) + .andExpect(status().isNotFound) + } + + @Test + fun `Detail API call retuns probation record with no active sentence`() { + val crn = PersonGenerator.NO_SENTENCE.crn + val detailResponse = mockMvc + .perform(get("/probation-case/$crn/all").withToken()) + .andExpect(status().is2xxSuccessful) + .andReturn().response.contentAsJson() + assertThat(detailResponse.currentDisposal, equalTo("0")) + assertThat(detailResponse.activeProbationManagedSentence, equalTo(false)) + } } diff --git a/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/model/Offender.kt b/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/model/Offender.kt new file mode 100644 index 0000000000..f54f24f465 --- /dev/null +++ b/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/model/Offender.kt @@ -0,0 +1,221 @@ +package uk.gov.justice.digital.hmpps.api.model + +import java.time.LocalDate +import java.time.LocalDateTime +import java.time.ZonedDateTime + +data class OffenderDetailSummary( + val preferredName: String?, + val activeProbationManagedSentence: Boolean, + val contactDetails: ContactDetailsSummary, + val currentDisposal: String, + val currentExclusion: Boolean, + val currentRestriction: Boolean, + val dateOfBirth: LocalDate, + val firstName: String, + val gender: String, + val middleNames: List, + val offenderId: Long, + val offenderProfile: OffenderProfile, + val otherIds: OtherIds, + val partitionArea: String, + val previousSurname: String?, + val softDeleted: Boolean, + val surname: String, + val title: String? +) + +data class OffenderDetail( + val preferredName: String?, + val activeProbationManagedSentence: Boolean, + val contactDetails: ContactDetails, + val currentDisposal: String, + val currentExclusion: Boolean, + val exclusionMessage: String?, + val currentRestriction: Boolean, + val restrictionMessage: String?, + val dateOfBirth: LocalDate, + val firstName: String, + val gender: String, + val middleNames: List, + val offenderId: Long, + val offenderProfile: OffenderProfile, + val offenderAliases: List, + val offenderManagers: List, + val otherIds: OtherIds, + val partitionArea: String, + val currentTier: String?, + val previousSurname: String?, + val softDeleted: Boolean, + val surname: String, + val title: String? +) + +data class OffenderAlias( + val id: Long, + val dateOfBirth: LocalDate?, + val firstName: String, + val middleNames: List, + val surname: String, + val gender: String +) + +data class ContactDetailsSummary( + val allowSMS: Boolean?, + val emailAddresses: List, + val phoneNumbers: List, +) + +data class ContactDetails( + val allowSMS: Boolean?, + val emailAddresses: List, + val phoneNumbers: List, + val addresses: List
+) + +data class Human( + val forenames: String, + val surname: String +) + +data class StaffHuman( + val code: String, + val forename: String, + val surname: String, + val isUnallocated: Boolean +) + +data class Institution( + val institutionId: Long? = null, + val isEstablishment: Boolean? = null, + val code: String? = null, + val description: String? = null, + val institutionName: String? = null, + val establishmentType: KeyValue? = null, + val isPrivate: Boolean? = null, + val nomsPrisonInstitutionCode: String? = null +) + +data class ProbationArea( + val probationAreaId: Long, + val code: String, + val description: String, + val nps: Boolean +) + +data class OffenderManager( + val trustOfficer: Human, + val staff: StaffHuman, + val providerEmployee: Human? = null, + val partitionArea: String, + val softDeleted: Boolean, + val team: Team, + val probationArea: ProbationArea, + val fromDate: LocalDate, + val toDate: LocalDate? = null, + val active: Boolean, + val allocationReason: KeyValue? = null +) + +data class Team( + val code: String, + val description: String, + val telephone: String? = null, + val emailAddress: String? = null, + val localDeliveryUnit: KeyValue, + val district: KeyValue, + val borough: KeyValue +) + +data class Address( + val from: LocalDate? = null, + val to: LocalDate? = null, + val noFixedAbode: Boolean? = null, + val notes: String? = null, + val addressNumber: String? = null, + val buildingName: String? = null, + val streetName: String? = null, + val district: String? = null, + val town: String? = null, + val county: String? = null, + val postcode: String? = null, + val telephoneNumber: String? = null, + val status: KeyValue? = null, + val type: KeyValue? = null, + val typeVerified: Boolean? = null, + val latestAssessmentDate: LocalDateTime? = null, + val createdDatetime: ZonedDateTime? = null, + val lastUpdatedDatetime: ZonedDateTime? = null, +) + +data class OtherIds( + val crn: String, + val croNumber: String?, + val immigrationNumber: String?, + val mostRecentPrisonerNumber: String?, + val niNumber: String?, + val nomsNumber: String?, + val pncNumber: String? +) + +data class Disability( + val lastUpdatedDateTime: ZonedDateTime, + val disabilityCondition: KeyValue, + val disabilityId: Long, + val disabilityType: KeyValue, + val endDate: LocalDate?, + val isActive: Boolean, + val notes: String?, + val provisions: List, + val startDate: LocalDate +) + +data class OffenderLanguages( + val languageConcerns: String?, + val otherLanguages: List = emptyList(), + val primaryLanguage: String?, + val requiresInterpreter: Boolean? +) + +data class OffenderProfile( + val genderIdentity: String?, + val selfDescribedGenderIdentity: String?, + val disabilities: List = emptyList(), + val ethnicity: String?, + val immigrationStatus: String?, + val nationality: String?, + val notes: String? = null, + val offenderDetails: String?, + val offenderLanguages: OffenderLanguages, + val previousConviction: PreviousConviction?, + val provisions: List = emptyList(), + val religion: String?, + val remandStatus: String?, + val riskColour: String?, + val secondaryNationality: String?, + val sexualOrientation: String? +) + +data class PhoneNumber( + val number: String?, + val type: String +) + +data class PreviousConviction( + val convictionDate: LocalDate, + val detail: Map +) + +data class Provision( + val category: KeyValue?, + val finishDate: LocalDate?, + val notes: String?, + val provisionId: Long, + val provisionType: KeyValue, + val startDate: LocalDate +) + +enum class PhoneTypes { + TELEPHONE, + MOBILE +} diff --git a/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/model/OffenderDetailSummary.kt b/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/model/OffenderDetailSummary.kt deleted file mode 100644 index e491a933f7..0000000000 --- a/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/model/OffenderDetailSummary.kt +++ /dev/null @@ -1,103 +0,0 @@ -package uk.gov.justice.digital.hmpps.api.model - -import java.time.LocalDate -import java.time.ZonedDateTime - -data class OffenderDetailSummary( - val preferredName: String?, - val activeProbationManagedSentence: Boolean, - val contactDetails: ContactDetails, - val currentDisposal: String, - val currentExclusion: Boolean, - val currentRestriction: Boolean, - val dateOfBirth: LocalDate, - val firstName: String, - val gender: String, - val middleNames: List, - val offenderId: Long, - val offenderProfile: OffenderProfile, - val otherIds: OtherIds, - val partitionArea: String, - val previousSurname: String?, - val softDeleted: Boolean, - val surname: String, - val title: String? -) - -data class ContactDetails( - val allowSMS: Boolean?, - val emailAddresses: List, - val phoneNumbers: List -) - -data class OtherIds( - val crn: String, - val croNumber: String?, - val immigrationNumber: String?, - val mostRecentPrisonerNumber: String?, - val niNumber: String?, - val nomsNumber: String?, - val pncNumber: String? -) - -data class Disability( - val lastUpdatedDateTime: ZonedDateTime, - val disabilityCondition: KeyValue, - val disabilityId: Long, - val disabilityType: KeyValue, - val endDate: LocalDate?, - val isActive: Boolean, - val notes: String?, - val provisions: List, - val startDate: LocalDate -) - -data class OffenderLanguages( - val languageConcerns: String?, - val otherLanguages: List = emptyList(), - val primaryLanguage: String?, - val requiresInterpreter: Boolean? -) - -data class OffenderProfile( - val genderIdentity: String?, - val selfDescribedGenderIdentity: String?, - val disabilities: List = emptyList(), - val ethnicity: String?, - val immigrationStatus: String?, - val nationality: String?, - val notes: String? = null, - val offenderDetails: String?, - val offenderLanguages: OffenderLanguages, - val previousConviction: PreviousConviction?, - val provisions: List = emptyList(), - val religion: String?, - val remandStatus: String?, - val riskColour: String?, - val secondaryNationality: String?, - val sexualOrientation: String? -) - -data class PhoneNumber( - val number: String?, - val type: String -) - -data class PreviousConviction( - val convictionDate: LocalDate, - val detail: Map -) - -data class Provision( - val category: KeyValue?, - val finishDate: LocalDate?, - val notes: String?, - val provisionId: Long, - val provisionType: KeyValue, - val startDate: LocalDate -) - -enum class PhoneTypes { - TELEPHONE, - MOBILE -} diff --git a/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/model/ProbationRecord.kt b/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/model/ProbationRecord.kt index 48f16a7e2c..678775c755 100644 --- a/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/model/ProbationRecord.kt +++ b/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/model/ProbationRecord.kt @@ -4,50 +4,14 @@ import uk.gov.justice.digital.hmpps.integrations.delius.entity.ReferenceData import uk.gov.justice.digital.hmpps.integrations.delius.event.courtappearance.entity.CourtReportType import uk.gov.justice.digital.hmpps.integrations.delius.event.entity.AdRequirementMainCategory import uk.gov.justice.digital.hmpps.integrations.delius.event.entity.RequirementMainCategory -import uk.gov.justice.digital.hmpps.integrations.delius.person.entity.PersonManager import java.time.LocalDate import java.time.ZonedDateTime -data class ProbationRecord( - val crn: String, - val offenderManagers: List, - val convictions: List -) - -data class OffenderManager( - val staff: Staff, - val allocatedDate: LocalDate, - val team: Team, - val provider: String, - val active: Boolean -) - -fun PersonManager.toOffenderManager() = - OffenderManager(staff.toStaff(), date.toLocalDate(), team.toTeam(), provider.description, true) - -fun uk.gov.justice.digital.hmpps.integrations.delius.provider.entity.Staff.toStaff() = - Staff(listOfNotNull(forename, forename2).joinToString(" "), surname) - -fun uk.gov.justice.digital.hmpps.integrations.delius.provider.entity.Team.toTeam() = - Team(description, telephone, ldu.description, district.description) - fun ReferenceData.keyValueOf() = KeyValue(code, description) fun RequirementMainCategory.keyValueOf() = KeyValue(code, description) fun AdRequirementMainCategory.keyValueOf() = KeyValue(code, description) fun CourtReportType.keyValueOf() = KeyValue(code, description) -data class Staff( - val forenames: String, - val surname: String -) - -data class Team( - val description: String, - val telephone: String? = null, - val localDeliveryUnit: String, - val district: String -) - data class Conviction( val active: Boolean = false, val inBreach: Boolean = false, diff --git a/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/resource/ProbationRecordResource.kt b/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/resource/ProbationRecordResource.kt index 0fa57e31f1..b1a14a6a57 100644 --- a/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/resource/ProbationRecordResource.kt +++ b/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/resource/ProbationRecordResource.kt @@ -15,5 +15,11 @@ class ProbationRecordResource(private val offenderService: OffenderService) { @GetMapping fun getOffenderDetailSummary( @PathVariable crn: String + ) = offenderService.getOffenderDetailSummary(crn) + + @PreAuthorize("hasRole('PROBATION_API__COURT_CASE__CASE_DETAIL')") + @GetMapping("/all") + fun getOffenderDetail( + @PathVariable crn: String ) = offenderService.getOffenderDetail(crn) } diff --git a/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/person/entity/Person.kt b/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/person/entity/Person.kt index 57f528f3a4..6aae680e08 100644 --- a/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/person/entity/Person.kt +++ b/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/person/entity/Person.kt @@ -9,6 +9,8 @@ import org.springframework.data.jpa.repository.Query import uk.gov.justice.digital.hmpps.exception.NotFoundException import uk.gov.justice.digital.hmpps.integrations.delius.entity.ReferenceData import java.time.LocalDate +import java.time.LocalDateTime +import java.time.ZonedDateTime @Immutable @Entity @@ -112,10 +114,13 @@ class Person( val currentRemandStatus: String? = null, @OneToMany(mappedBy = "personId") - val disabilities: Set = emptySet(), + val disabilities: List = emptyList(), @OneToMany(mappedBy = "personId") - val provisions: Set = emptySet(), + val offenderAliases: List = emptyList(), + + @OneToMany(mappedBy = "personId") + val provisions: List = emptyList(), @ManyToOne @JoinColumn(name = "ethnicity_id") @@ -133,6 +138,17 @@ class Person( @JoinColumn(name = "immigration_status_id") val immigrationStatus: ReferenceData? = null, + @ManyToOne + @JoinColumn(name = "current_tier") + val currentTier: ReferenceData? = null, + + @OneToMany(mappedBy = "personId", fetch = FetchType.LAZY) + val addresses: List = emptyList(), + + @OneToMany + @JoinColumn(name = "offender_id") + val offenderManagers: List, + @Column(name = "allow_sms") @Convert(converter = YesNoConverter::class) val allowSms: Boolean? = false, @@ -153,11 +169,126 @@ class Person( @JoinColumn(name = "partition_area_id") val partitionArea: PartitionArea, + @Column(name = "exclusion_message") + val exclusionMessage: String? = null, + + @Column(name = "restriction_message") + val restrictionMessage: String? = null, + @Column(columnDefinition = "number") val softDeleted: Boolean = false ) +@Immutable +@Entity +@Table(name = "alias") +@SQLRestriction("soft_deleted = 0") +class OffenderAlias( + + @Id + @Column(name = "alias_id") + val aliasID: Long, + + @Column(name = "offender_id") + val personId: Long, + + @Column(name = "date_of_birth_date") + val dateOfBirth: LocalDate, + + @Column(name = "first_name") + val firstName: String, + + @Column(name = "second_name") + val secondName: String? = null, + + @Column(name = "soft_deleted", columnDefinition = "number") + val softDeleted: Boolean = false, + + val surname: String, + + @Column(name = "third_name") + val thirdName: String? = null, + + @ManyToOne + @JoinColumn(name = "gender_id") + val gender: ReferenceData +) + +@Entity +@Table(name = "offender_address") +@SQLRestriction("soft_deleted = 0") +class PersonAddress( + @Id + @Column(name = "offender_address_id") + val id: Long, + + @Column(name = "offender_id") + val personId: Long, + + @ManyToOne + @JoinColumn(name = "address_type_id") + val type: ReferenceData, + + @ManyToOne + @JoinColumn(name = "address_status_id") + val status: ReferenceData, + + val streetName: String?, + + @Column(name = "town_city") + val town: String?, + + val county: String?, + val postcode: String?, + val telephoneNumber: String? = null, + val buildingName: String? = null, + val district: String? = null, + val addressNumber: String? = null, + + @Convert(converter = YesNoConverter::class) + val noFixedAbode: Boolean? = false, + + @Convert(converter = YesNoConverter::class) + val typeVerified: Boolean? = false, + + @Column(name = "notes", columnDefinition = "clob") + val notes: String? = null, + + val startDate: LocalDate = LocalDate.now(), + val endDate: LocalDate? = null, + + @Column(updatable = false, columnDefinition = "number") + val softDeleted: Boolean = false, + + val createdDatetime: ZonedDateTime = ZonedDateTime.now(), + val createdByUserId: Long = 0, + val lastUpdatedDatetime: ZonedDateTime = ZonedDateTime.now(), + var lastUpdatedUserId: Long = 0, + + @OneToMany(mappedBy = "offenderAddressId") + val addressAssessments: List = emptyList() +) + +@Immutable +@Entity +@Table(name = "address_assessment") +@SQLRestriction("soft_deleted = 0") +class AddressAssessment( + @Id + @Column(name = "address_assessment_id") + val id: Long, + + @Column(name = "offender_address_id") + val offenderAddressId: Long, + + @Column(name = "assessment_date") + val assessmentDate: LocalDateTime, + + @Column(name = "soft_deleted") + val softDeleted: Long +) + @Immutable @Entity @Table(name = "partition_area") @@ -199,26 +330,20 @@ interface PersonRepository : JpaRepository { @Query( """ - select p from Person p + select p from Person p left join fetch p.ethnicity eth left join fetch p.nationality nat left join fetch p.gender gen left join fetch p.language lang left join fetch p.genderIdentity gi left join fetch p.immigrationStatus is - left join fetch p.provisions prov - left join fetch p.disabilities dis left join fetch p.secondNationality sn left join fetch p.sexualOrientation so left join fetch p.religion rel left join fetch p.partitionArea pa left join fetch p.title title - left join fetch prov.category pcat - left join fetch prov.type ptype - left join fetch dis.type dtype - left join fetch dis.condition dcond where p.crn = :crn - and p.softDeleted = false + and p.softDeleted = false """ ) fun findByCrn(crn: String): Person? diff --git a/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/person/entity/PersonManager.kt b/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/person/entity/PersonManager.kt index 579896b265..ebb928b970 100644 --- a/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/person/entity/PersonManager.kt +++ b/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/person/entity/PersonManager.kt @@ -1,18 +1,20 @@ package uk.gov.justice.digital.hmpps.integrations.delius.person.entity -import jakarta.persistence.Column -import jakarta.persistence.Entity -import jakarta.persistence.Id -import jakarta.persistence.JoinColumn -import jakarta.persistence.ManyToOne -import jakarta.persistence.Table +import jakarta.persistence.* +import org.hibernate.annotations.Immutable +import org.hibernate.annotations.SQLRestriction +import uk.gov.justice.digital.hmpps.integrations.delius.entity.ReferenceData import uk.gov.justice.digital.hmpps.integrations.delius.provider.entity.ProbationAreaEntity import uk.gov.justice.digital.hmpps.integrations.delius.provider.entity.Staff import uk.gov.justice.digital.hmpps.integrations.delius.provider.entity.Team +import java.io.Serializable +import java.time.LocalDate import java.time.ZonedDateTime +@Immutable @Entity @Table(name = "offender_manager") +@SQLRestriction("soft_deleted = 0 and active_flag = 1") class PersonManager( @Id @Column(name = "offender_manager_id") @@ -30,17 +32,106 @@ class PersonManager( @JoinColumn(name = "allocation_staff_id") val staff: Staff, + @Column(name = "staff_employee_id") + val staffEmployeeId: Long, + + @Column(name = "trust_provider_flag", columnDefinition = "number") + val trustProviderFlag: Boolean, + + @ManyToOne + @JoinColumns( + JoinColumn( + name = "staff_employee_id", + referencedColumnName = "staff_employee_id", + insertable = false, + updatable = false + ), + JoinColumn( + name = "trust_provider_flag", + referencedColumnName = "trust_provider_flag", + insertable = false, + updatable = false + ) + ) + val officer: Officer, + + @ManyToOne + @JoinColumn(name = "provider_employee_id") + val providerEmployee: ProviderEmployee? = null, + + @ManyToOne + @JoinColumn(name = "partition_area_id") + val partitionArea: PartitionArea, + @ManyToOne @JoinColumn(name = "probation_area_id", nullable = false) val provider: ProbationAreaEntity, + @ManyToOne + @JoinColumn(name = "allocation_reason_id") + val allocationReason: ReferenceData, + @Column(name = "allocation_date") val date: ZonedDateTime, + @Column(name = "start_date") + val startDate: LocalDate, + + @Column(name = "end_date") + val endDate: LocalDate? = null, + @Column(name = "active_flag", columnDefinition = "NUMBER") val active: Boolean = true, - @Column(name = "soft_deleted", columnDefinition = "NUMBER", nullable = false) + @Column(name = "soft_deleted", columnDefinition = "NUMBER") var softDeleted: Boolean = false ) + +@Immutable +@Entity +@Table(name = "officer") +class Officer( + + @EmbeddedId + val id: OfficerPk, + + @Column(name = "surname") + val surname: String, + + @Column(name = "forename") + val forename: String, + + @Column(name = "forename2") + val forename2: String? = null, +) + +@Immutable +@Entity +@Table(name = "provider_employee") +class ProviderEmployee( + @Id + @Column(name = "provider_employee_id") + val providerEmployeeId: Long, + + @Column(name = "surname") + val surname: String, + + @Column(name = "forename") + val forename: String, + + @Column(name = "forename2") + val forename2: String? = null +) + +@Embeddable +class OfficerPk( + @Column(name = "trust_provider_flag") + val trustProviderFlag: Long, + + @Column(name = "staff_employee_id") + val staffEmployeeId: Long +) : Serializable + + + diff --git a/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/provider/entity/ProbationArea.kt b/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/provider/entity/ProbationArea.kt index d7b8d2791c..8e13c76c81 100644 --- a/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/provider/entity/ProbationArea.kt +++ b/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/provider/entity/ProbationArea.kt @@ -1,13 +1,6 @@ package uk.gov.justice.digital.hmpps.integrations.delius.provider.entity -import jakarta.persistence.Column -import jakarta.persistence.Convert -import jakarta.persistence.Entity -import jakarta.persistence.Id -import jakarta.persistence.JoinColumn -import jakarta.persistence.ManyToOne -import jakarta.persistence.OneToMany -import jakarta.persistence.Table +import jakarta.persistence.* import org.hibernate.annotations.Immutable import org.hibernate.type.YesNoConverter @@ -28,6 +21,9 @@ class ProbationAreaEntity( @Column(columnDefinition = "char(1)") val establishment: String?, + @Column(name = "private", columnDefinition = "number") + val privateSector: Boolean, + @Id @Column(name = "probation_area_id") val id: Long, diff --git a/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/service/OffenderService.kt b/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/service/OffenderService.kt index 4d3d8c6ac7..557eb22386 100644 --- a/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/service/OffenderService.kt +++ b/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/service/OffenderService.kt @@ -35,7 +35,13 @@ class OffenderService( private val courtReportRepository: CourtReportRepository ) { - fun getOffenderDetail(crn: String): OffenderDetailSummary { + fun getOffenderDetailSummary(crn: String): OffenderDetailSummary { + val person = personRepository.getPerson(crn) + val previousConviction = documentRepository.getPreviousConviction(person.id) + return person.toOffenderSummary(previousConviction) + } + + fun getOffenderDetail(crn: String): OffenderDetail { val person = personRepository.getPerson(crn) val previousConviction = documentRepository.getPreviousConviction(person.id) return person.toOffenderDetail(previousConviction) @@ -159,10 +165,10 @@ fun DisabilityEntity.isActive(): Boolean { return finishDate == null || finishDate.isAfter(LocalDate.now()) } -fun Person.toOffenderDetail(previousConviction: DocumentEntity?) = OffenderDetailSummary( +fun Person.toOffenderSummary(previousConviction: DocumentEntity?) = OffenderDetailSummary( preferredName = preferredName, activeProbationManagedSentence = currentDisposal, - contactDetails = ContactDetails( + contactDetails = ContactDetailsSummary( allowSMS = allowSms, emailAddresses = listOfNotNull(emailAddress), phoneNumbers = listOf( @@ -179,70 +185,185 @@ fun Person.toOffenderDetail(previousConviction: DocumentEntity?) = OffenderDetai surname = surname, gender = gender.description, offenderId = id, - offenderProfile = OffenderProfile( - genderIdentity = genderIdentity?.description, - selfDescribedGenderIdentity = genderIdentityDescription ?: genderIdentity?.description, - disabilities = disabilities.sortedByDescending { it.startDate }.map { - Disability( - lastUpdatedDateTime = it.lastUpdated, - disabilityCondition = KeyValue(it.condition.code, it.condition.description), - disabilityId = it.id, - disabilityType = KeyValue(it.type.code, it.type.description), - endDate = it.finishDate, - isActive = it.isActive(), - notes = it.notes, - provisions = emptyList(), - startDate = it.startDate - ) - }, - ethnicity = ethnicity?.description, - immigrationStatus = immigrationStatus?.description, - nationality = nationality?.description, - offenderDetails = offenderDetails, - offenderLanguages = OffenderLanguages( - languageConcerns = languageConcerns, - primaryLanguage = language?.description, - requiresInterpreter = requiresInterpreter, - otherLanguages = emptyList() + offenderProfile = toProfile(previousConviction), + otherIds = toOtherIds(), + partitionArea = partitionArea.area, + previousSurname = previousSurname, + softDeleted = softDeleted, + title = title?.description +) + +fun Person.toContactDetails() = ContactDetails( + allowSMS = allowSms, + emailAddresses = listOfNotNull(emailAddress), + phoneNumbers = listOf( + PhoneNumber(telephoneNumber, PhoneTypes.TELEPHONE.name), + PhoneNumber(mobileNumber, PhoneTypes.MOBILE.name) + ), + addresses = addresses.map { it -> + Address( + from = it.startDate, + to = it.endDate, + noFixedAbode = it.noFixedAbode, + notes = it.notes, + addressNumber = it.addressNumber, + buildingName = it.buildingName, + streetName = it.streetName, + district = it.district, + town = it.town, + county = it.county, + postcode = it.postcode, + telephoneNumber = it.telephoneNumber, + status = it.status.keyValueOf(), + type = it.type.keyValueOf(), + typeVerified = it.typeVerified, + latestAssessmentDate = it.addressAssessments.map { it.assessmentDate }.maxByOrNull { it }, + createdDatetime = it.createdDatetime, + lastUpdatedDatetime = it.lastUpdatedDatetime + ) + } +) + +fun Person.toOtherIds() = OtherIds( + crn = crn, + croNumber = croNumber, + immigrationNumber = immigrationNumber, + mostRecentPrisonerNumber = mostRecentPrisonerNumber, + niNumber = niNumber, + nomsNumber = nomsNumber, + pncNumber = pnc +) + +fun Person.toOffenderManagers() = offenderManagers.sortedByDescending { it.date }.map { it -> + OffenderManager( + trustOfficer = Human( + forenames = listOfNotNull(it.officer.forename, it.officer.forename2).joinToString(" "), + surname = it.officer.surname ), - previousConviction = previousConviction?.lastUpdated.let { - previousConviction?.createdAt?.toLocalDate() - ?.let { it1 -> - PreviousConviction( - convictionDate = it1, - detail = ImmutableMap.of("documentName", previousConviction.name) - ) - } - }, - provisions = provisions.sortedByDescending { it.startDate }.map { - Provision( - category = it.category?.let { cat -> KeyValue(cat.code, cat.description) }, - finishDate = it.finishDate, - notes = it.notes, - provisionId = it.id, - provisionType = KeyValue(it.type.code, it.type.description), - startDate = it.startDate - ) + softDeleted = it.softDeleted, + partitionArea = it.partitionArea.area, + staff = StaffHuman( + code = it.staff.code, + forename = it.staff.forename, + surname = it.staff.surname, + isUnallocated = it.staff.isUnallocated() + ), + providerEmployee = it.providerEmployee.let { emp -> + emp?.surname?.let { surname -> + Human( + forenames = listOfNotNull(emp.forename, emp.forename2).joinToString(" "), + surname = surname + ) + } }, - religion = religion?.description, - remandStatus = currentRemandStatus, - riskColour = currentHighestRiskColour, - sexualOrientation = sexualOrientation?.description, - secondaryNationality = secondNationality?.description - ), - otherIds = OtherIds( - crn = crn, - croNumber = croNumber, - immigrationNumber = immigrationNumber, - mostRecentPrisonerNumber = mostRecentPrisonerNumber, - niNumber = niNumber, - nomsNumber = nomsNumber, - pncNumber = pnc - ), + team = Team( + code = it.team.code, + description = it.team.description, + telephone = it.team.telephone, + emailAddress = it.team.emailAddress, + localDeliveryUnit = KeyValue(it.team.ldu.code, it.team.ldu.description), + district = KeyValue(it.team.district.code, it.team.district.description), + borough = KeyValue(it.team.district.borough.code, it.team.district.borough.code) + ), + probationArea = ProbationArea( + probationAreaId = it.provider.id, + code = it.provider.code, + description = it.provider.description, + nps = it.provider.privateSector + ), + active = it.active, + fromDate = it.startDate, + toDate = it.endDate, + allocationReason = it.allocationReason.keyValueOf() + ) +} + +fun Person.toOffenderDetail(previousConviction: DocumentEntity?) = OffenderDetail( + preferredName = preferredName, + activeProbationManagedSentence = currentDisposal, + contactDetails = toContactDetails(), + offenderAliases = offenderAliases.map { + OffenderAlias( + id = it.aliasID, + dateOfBirth = it.dateOfBirth, + firstName = it.firstName, + middleNames = listOfNotNull(it.secondName, it.thirdName), + surname = it.surname, + gender = it.gender.description + ) + }, + currentDisposal = if (currentDisposal) "1" else "0", + currentExclusion = currentExclusion, + exclusionMessage = exclusionMessage, + restrictionMessage = restrictionMessage, + currentRestriction = currentRestriction, + dateOfBirth = dateOfBirth, + firstName = forename, + middleNames = listOfNotNull(secondName, thirdName), + surname = surname, + gender = gender.description, + offenderId = id, + offenderProfile = toProfile(previousConviction), + otherIds = toOtherIds(), + offenderManagers = toOffenderManagers(), partitionArea = partitionArea.area, previousSurname = previousSurname, softDeleted = softDeleted, - title = title?.description + title = title?.description, + currentTier = currentTier?.description +) + +fun Person.toProfile(previousConviction: DocumentEntity?) = OffenderProfile( + genderIdentity = genderIdentity?.description, + selfDescribedGenderIdentity = genderIdentityDescription ?: genderIdentity?.description, + disabilities = disabilities.sortedByDescending { it.startDate }.map { + Disability( + lastUpdatedDateTime = it.lastUpdated, + disabilityCondition = KeyValue(it.condition.code, it.condition.description), + disabilityId = it.id, + disabilityType = KeyValue(it.type.code, it.type.description), + endDate = it.finishDate, + isActive = it.isActive(), + notes = it.notes, + provisions = emptyList(), + startDate = it.startDate + ) + }, + ethnicity = ethnicity?.description, + immigrationStatus = immigrationStatus?.description, + nationality = nationality?.description, + offenderDetails = offenderDetails, + offenderLanguages = OffenderLanguages( + languageConcerns = languageConcerns, + primaryLanguage = language?.description, + requiresInterpreter = requiresInterpreter, + otherLanguages = emptyList() + ), + previousConviction = previousConviction?.lastUpdated.let { + previousConviction?.createdAt?.toLocalDate() + ?.let { it1 -> + PreviousConviction( + convictionDate = it1, + detail = ImmutableMap.of("documentName", previousConviction.name) + ) + } + }, + provisions = provisions.sortedByDescending { it.startDate }.map { + Provision( + category = it.category?.let { cat -> KeyValue(cat.code, cat.description) }, + finishDate = it.finishDate, + notes = it.notes, + provisionId = it.id, + provisionType = KeyValue(it.type.code, it.type.description), + startDate = it.startDate + ) + }, + religion = religion?.description, + remandStatus = currentRemandStatus, + riskColour = currentHighestRiskColour, + sexualOrientation = sexualOrientation?.description, + secondaryNationality = secondNationality?.description + ) fun Disposal.sentenceOf() = Sentence( From 751a9ffc6a0cd6e0ee10157a4e806dc31e1f0bf9 Mon Sep 17 00:00:00 2001 From: achimber-moj <161360519+achimber-moj@users.noreply.github.com> Date: Mon, 20 May 2024 15:47:29 +0100 Subject: [PATCH 07/10] PI-2204 fix ORA-01031: insufficient privileges (#3812) --- projects/approved-premises-and-delius/deploy/database/access.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/projects/approved-premises-and-delius/deploy/database/access.yml b/projects/approved-premises-and-delius/deploy/database/access.yml index 0516424044..30fb1ed69b 100644 --- a/projects/approved-premises-and-delius/deploy/database/access.yml +++ b/projects/approved-premises-and-delius/deploy/database/access.yml @@ -10,6 +10,7 @@ database: - nsi_manager - approved_premises_referral - approved_premises_residence + - approved_premises_preferred sequences: - ap_referral_id_seq From 1627374be80978a39b54413f80865b8e80956d5b Mon Sep 17 00:00:00 2001 From: Marcus Aspin Date: Tue, 21 May 2024 14:30:59 +0100 Subject: [PATCH 08/10] PI-2163 Add dynamic risk and person status registrations (#3817) --- .../justice/digital/hmpps/data/DataLoader.kt | 10 +- .../data/generator/RegistrationGenerator.kt | 14 +- .../justice/digital/hmpps/IntegrationTest.kt | 8 +- .../integration/delius/entity/Registration.kt | 73 ---------- .../delius/entity/RegistrationEntity.kt | 109 +++++++++++++++ .../digital/hmpps/model/MappaDetail.kt | 12 +- .../digital/hmpps/model/Registration.kt | 11 ++ .../hmpps/model/SupervisionResponse.kt | 4 +- .../hmpps/service/CaseDetailsService.kt | 128 ++++++++++-------- 9 files changed, 227 insertions(+), 142 deletions(-) delete mode 100644 projects/external-api-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integration/delius/entity/Registration.kt create mode 100644 projects/external-api-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integration/delius/entity/RegistrationEntity.kt create mode 100644 projects/external-api-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/model/Registration.kt diff --git a/projects/external-api-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/DataLoader.kt b/projects/external-api-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/DataLoader.kt index cfe9de62bd..824caa4de8 100644 --- a/projects/external-api-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/DataLoader.kt +++ b/projects/external-api-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/DataLoader.kt @@ -10,8 +10,8 @@ import org.springframework.stereotype.Component import uk.gov.justice.digital.hmpps.data.generator.DataGenerator import uk.gov.justice.digital.hmpps.data.generator.RegistrationGenerator import uk.gov.justice.digital.hmpps.data.generator.UserGenerator -import uk.gov.justice.digital.hmpps.service.Category -import uk.gov.justice.digital.hmpps.service.Level +import uk.gov.justice.digital.hmpps.model.Category +import uk.gov.justice.digital.hmpps.model.Level import uk.gov.justice.digital.hmpps.user.AuditUserRepository import java.time.LocalDate @@ -47,6 +47,12 @@ class DataLoader( persist(DataGenerator.EVENT.mainOffence) DataGenerator.EVENT.additionalOffences.forEach { persist(it) } DataGenerator.EVENT.courtAppearances.forEach { persist(it) } + persist(RegistrationGenerator.CHILD_CONCERNS_TYPE) + persist(RegistrationGenerator.generate(RegistrationGenerator.CHILD_CONCERNS_TYPE)) + persist(RegistrationGenerator.CHILD_PROTECTION_TYPE) + persist(RegistrationGenerator.generate(RegistrationGenerator.CHILD_PROTECTION_TYPE)) + persist(RegistrationGenerator.SERIOUS_FURTHER_OFFENCE_TYPE) + persist(RegistrationGenerator.generate(RegistrationGenerator.SERIOUS_FURTHER_OFFENCE_TYPE)) persist(RegistrationGenerator.MAPPA_TYPE) RegistrationGenerator.CATEGORIES.values.forEach(::persist) RegistrationGenerator.LEVELS.values.forEach(::persist) diff --git a/projects/external-api-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/RegistrationGenerator.kt b/projects/external-api-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/RegistrationGenerator.kt index d9de852845..e5905abdbe 100644 --- a/projects/external-api-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/RegistrationGenerator.kt +++ b/projects/external-api-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/RegistrationGenerator.kt @@ -3,17 +3,21 @@ package uk.gov.justice.digital.hmpps.data.generator import uk.gov.justice.digital.hmpps.integration.delius.entity.Person import uk.gov.justice.digital.hmpps.integration.delius.entity.ReferenceData import uk.gov.justice.digital.hmpps.integration.delius.entity.RegisterType -import uk.gov.justice.digital.hmpps.integration.delius.entity.Registration -import uk.gov.justice.digital.hmpps.service.Category -import uk.gov.justice.digital.hmpps.service.Level +import uk.gov.justice.digital.hmpps.integration.delius.entity.RegistrationEntity +import uk.gov.justice.digital.hmpps.model.Category +import uk.gov.justice.digital.hmpps.model.Level import java.time.LocalDate object RegistrationGenerator { + val CHILD_CONCERNS_TYPE = generateType(RegisterType.CHILD_CONCERNS_CODE) + val CHILD_PROTECTION_TYPE = generateType(RegisterType.CHILD_PROTECTION_CODE) + val SERIOUS_FURTHER_OFFENCE_TYPE = generateType(RegisterType.SERIOUS_FURTHER_OFFENCE_CODE) val MAPPA_TYPE = generateType(RegisterType.MAPPA_CODE) val CATEGORIES = Category.entries.map { generateReferenceData(it.name) }.associateBy { it.code } val LEVELS = Level.entries.map { generateReferenceData(it.name) }.associateBy { it.code } - fun generateType(code: String, id: Long = IdGenerator.getAndIncrement()) = RegisterType(code, id) + fun generateType(code: String, id: Long = IdGenerator.getAndIncrement()) = + RegisterType(code, "Description for $code", id) fun generate( type: RegisterType = MAPPA_TYPE, @@ -26,7 +30,7 @@ object RegistrationGenerator { deRegistered: Boolean = false, softDeleted: Boolean = false, id: Long = IdGenerator.getAndIncrement() - ) = Registration(person.id, type, category, level, date, reviewDate, notes, deRegistered, softDeleted, id) + ) = RegistrationEntity(person.id, type, category, level, date, reviewDate, notes, deRegistered, softDeleted, id) fun generateReferenceData( code: String, diff --git a/projects/external-api-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/IntegrationTest.kt b/projects/external-api-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/IntegrationTest.kt index 54fe2832f8..07ca4b726f 100644 --- a/projects/external-api-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/IntegrationTest.kt +++ b/projects/external-api-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/IntegrationTest.kt @@ -9,7 +9,6 @@ import org.springframework.test.web.servlet.MockMvc import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get import org.springframework.test.web.servlet.result.MockMvcResultMatchers.content import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status -import uk.gov.justice.digital.hmpps.data.generator.DataGenerator import uk.gov.justice.digital.hmpps.data.generator.DataGenerator.PERSON import uk.gov.justice.digital.hmpps.test.MockMvcExtensions.withToken import java.time.LocalDate @@ -112,7 +111,12 @@ internal class IntegrationTest { } ] } - ] + ], + "dynamicRisks": [ + {"code": "RCCO", "description": "Description for RCCO", "startDate": "$start"}, + {"code": "RCPR", "description": "Description for RCPR", "startDate": "$start"} + ], + "personStatus": [{"code":"ASFO", "description": "Description for ASFO", "startDate": "$start"}] } """.trimIndent() ) diff --git a/projects/external-api-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integration/delius/entity/Registration.kt b/projects/external-api-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integration/delius/entity/Registration.kt deleted file mode 100644 index 87d768dbec..0000000000 --- a/projects/external-api-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integration/delius/entity/Registration.kt +++ /dev/null @@ -1,73 +0,0 @@ -package uk.gov.justice.digital.hmpps.integration.delius.entity - -import jakarta.persistence.* -import org.hibernate.annotations.Immutable -import org.hibernate.annotations.SQLRestriction -import org.springframework.data.jpa.repository.EntityGraph -import org.springframework.data.jpa.repository.JpaRepository -import java.time.LocalDate - -@Immutable -@Entity -@SQLRestriction("soft_deleted = 0 and deregistered = 0") -@Table(name = "registration") -class Registration( - @Column(name = "offender_id") - val personId: Long, - - @ManyToOne - @JoinColumn(name = "register_type_id") - val type: RegisterType, - - @ManyToOne - @JoinColumn(name = "register_category_id") - val category: ReferenceData?, - - @ManyToOne - @JoinColumn(name = "register_level_id") - val level: ReferenceData?, - - @Column(name = "registration_date") - val date: LocalDate, - - @Column(name = "next_review_date") - val reviewDate: LocalDate?, - - @Column(name = "registration_notes", columnDefinition = "clob") - val notes: String?, - - @Column(name = "deregistered", columnDefinition = "number") - val deRegistered: Boolean, - - @Column(name = "soft_deleted", columnDefinition = "number") - val softDeleted: Boolean, - - @Id - @Column(name = "registration_id") - val id: Long -) - -@Entity -@Immutable -@Table(name = "r_register_type") -class RegisterType( - - val code: String, - - @Id - @Column(name = "register_type_id") - val id: Long, -) { - companion object { - const val MAPPA_CODE = "MAPP" - } -} - -interface RegistrationRepository : JpaRepository { - - @EntityGraph(attributePaths = ["type", "category", "level"]) - fun findFirstByPersonIdAndTypeCodeOrderByDateDesc(personId: Long, typeCode: String): Registration? -} - -fun RegistrationRepository.findMappa(personId: Long) = - findFirstByPersonIdAndTypeCodeOrderByDateDesc(personId, RegisterType.MAPPA_CODE) \ No newline at end of file diff --git a/projects/external-api-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integration/delius/entity/RegistrationEntity.kt b/projects/external-api-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integration/delius/entity/RegistrationEntity.kt new file mode 100644 index 0000000000..75cf78abd9 --- /dev/null +++ b/projects/external-api-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integration/delius/entity/RegistrationEntity.kt @@ -0,0 +1,109 @@ +package uk.gov.justice.digital.hmpps.integration.delius.entity + +import jakarta.persistence.* +import org.hibernate.annotations.Immutable +import org.hibernate.annotations.SQLRestriction +import org.springframework.data.jpa.repository.EntityGraph +import org.springframework.data.jpa.repository.JpaRepository +import java.time.LocalDate + +@Immutable +@Entity +@SQLRestriction("soft_deleted = 0 and deregistered = 0") +@Table(name = "registration") +class RegistrationEntity( + @Column(name = "offender_id") + val personId: Long, + + @ManyToOne + @JoinColumn(name = "register_type_id") + val type: RegisterType, + + @ManyToOne + @JoinColumn(name = "register_category_id") + val category: ReferenceData?, + + @ManyToOne + @JoinColumn(name = "register_level_id") + val level: ReferenceData?, + + @Column(name = "registration_date") + val date: LocalDate, + + @Column(name = "next_review_date") + val reviewDate: LocalDate?, + + @Column(name = "registration_notes", columnDefinition = "clob") + val notes: String?, + + @Column(name = "deregistered", columnDefinition = "number") + val deRegistered: Boolean, + + @Column(name = "soft_deleted", columnDefinition = "number") + val softDeleted: Boolean, + + @Id + @Column(name = "registration_id") + val id: Long +) + +@Entity +@Immutable +@Table(name = "r_register_type") +class RegisterType( + val code: String, + val description: String, + + @Id + @Column(name = "register_type_id") + val id: Long, +) { + companion object { + const val MAPPA_CODE = "MAPP" // Multi-Agency Public Protection Arrangements + const val CHILD_CONCERNS_CODE = "RCCO" // Safeguarding concerns where a child is at risk from the offender + const val CHILD_PROTECTION_CODE = "RCPR" // Child is subject to a protection plan/conference + const val RISK_TO_VULNERABLE_ADULT_CODE = "RVAD" // Risk to a vulnerable adult + const val STREET_GANGS_CODE = "STRG" // Involved in serious group offending + const val VISOR_CODE = "AVIS" // Subject has a ViSOR record + const val WEAPONS_CODE = "WEAP" // Known to use/carry weapon + const val LOW_ROSH_CODE = "RLRH" // Low risk of serious harm + const val MED_ROSH_CODE = "RMRH" // Medium risk of serious harm + const val HIGH_ROSH_CODE = "HRSH" // High risk of serious harm + const val VERY_HIGH_ROSH_CODE = "RVRH" // Very high risk of serious harm + const val SERIOUS_FURTHER_OFFENCE_CODE = "ASFO" // Subject to SFO review/investigation + const val WARRANT_SUMMONS_CODE = "WRSM" // Outstanding warrant or summons + } +} + +interface RegistrationRepository : JpaRepository { + @EntityGraph(attributePaths = ["type", "category", "level"]) + fun findFirstByPersonIdAndTypeCodeOrderByDateDesc(personId: Long, typeCode: String): RegistrationEntity? + + @EntityGraph(attributePaths = ["type", "category", "level"]) + fun findByPersonIdAndTypeCodeInOrderByDateDesc(personId: Long, typeCode: List): List +} + +fun RegistrationRepository.findMappa(personId: Long) = + findFirstByPersonIdAndTypeCodeOrderByDateDesc(personId, RegisterType.MAPPA_CODE) + +fun RegistrationRepository.findDynamicRiskRegistrations(personId: Long) = findByPersonIdAndTypeCodeInOrderByDateDesc( + personId, listOf( + RegisterType.CHILD_CONCERNS_CODE, + RegisterType.CHILD_PROTECTION_CODE, + RegisterType.RISK_TO_VULNERABLE_ADULT_CODE, + RegisterType.STREET_GANGS_CODE, + RegisterType.VISOR_CODE, + RegisterType.WEAPONS_CODE, + RegisterType.LOW_ROSH_CODE, + RegisterType.MED_ROSH_CODE, + RegisterType.HIGH_ROSH_CODE, + RegisterType.VERY_HIGH_ROSH_CODE, + ) +) + +fun RegistrationRepository.findPersonStatusRegistrations(personId: Long) = findByPersonIdAndTypeCodeInOrderByDateDesc( + personId, listOf( + RegisterType.SERIOUS_FURTHER_OFFENCE_CODE, + RegisterType.WARRANT_SUMMONS_CODE, + ) +) \ No newline at end of file diff --git a/projects/external-api-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/model/MappaDetail.kt b/projects/external-api-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/model/MappaDetail.kt index f42b584203..b4f47ac28a 100644 --- a/projects/external-api-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/model/MappaDetail.kt +++ b/projects/external-api-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/model/MappaDetail.kt @@ -10,4 +10,14 @@ data class MappaDetail( val startDate: LocalDate, val reviewDate: LocalDate?, val notes: String? -) \ No newline at end of file +) + +enum class Level(val number: Int) { M0(0), M1(1), M2(2), M3(3) } + +enum class Category(val number: Int) { X9(0), M1(1), M2(2), M3(3), M4(4) } + +fun String.toMappaLevel() = Level.entries.find { it.name == this }?.number + ?: throw IllegalStateException("Unexpected MAPPA level: $this") + +fun String.toMappaCategory() = Category.entries.find { it.name == this }?.number + ?: throw IllegalStateException("Unexpected MAPPA category: $this") \ No newline at end of file diff --git a/projects/external-api-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/model/Registration.kt b/projects/external-api-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/model/Registration.kt new file mode 100644 index 0000000000..5f23e62b8f --- /dev/null +++ b/projects/external-api-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/model/Registration.kt @@ -0,0 +1,11 @@ +package uk.gov.justice.digital.hmpps.model + +import java.time.LocalDate + +data class Registration( + val code: String, + val description: String, + val startDate: LocalDate, + val reviewDate: LocalDate?, + val notes: String? +) \ No newline at end of file diff --git a/projects/external-api-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/model/SupervisionResponse.kt b/projects/external-api-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/model/SupervisionResponse.kt index 9ebd9ae834..c6798af99f 100644 --- a/projects/external-api-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/model/SupervisionResponse.kt +++ b/projects/external-api-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/model/SupervisionResponse.kt @@ -3,7 +3,9 @@ package uk.gov.justice.digital.hmpps.model data class SupervisionResponse( val communityManager: Manager, val mappaDetail: MappaDetail?, - val supervisions: List + val supervisions: List, + val dynamicRisks: List, + val personStatus: List ) data class Manager( diff --git a/projects/external-api-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/CaseDetailsService.kt b/projects/external-api-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/CaseDetailsService.kt index 4ff7baa290..1136494a0f 100644 --- a/projects/external-api-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/CaseDetailsService.kt +++ b/projects/external-api-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/CaseDetailsService.kt @@ -19,72 +19,84 @@ class CaseDetailsService( private val ldapTemplate: LdapTemplate ) { fun getSupervisions(crn: String): SupervisionResponse = with(comRepository.getForCrn(crn)) { + return SupervisionResponse( + communityManager = toCommunityManagerResponse(), + mappaDetail = registrationRepository.findMappa(person.id).toMappaResponse(), + supervisions = eventRepository.findByPersonIdOrderByConvictionDateDesc(person.id).toSupervisionResponse(), + dynamicRisks = registrationRepository.findDynamicRiskRegistrations(person.id).toRegistrationResponse(), + personStatus = registrationRepository.findPersonStatusRegistrations(person.id).toRegistrationResponse(), + ) + } + + private fun PersonManager.toCommunityManagerResponse(): Manager { staff.user?.apply { ldapTemplate.findByUsername(username)?.let { email = it.email telephone = it.telephone } } - val supervisions = eventRepository.findByPersonIdOrderByConvictionDateDesc(person.id).map { event -> - Supervision( - number = event.number.toInt(), - active = event.active, - date = event.convictionDate, - sentence = event.disposal?.let { disposal -> - Sentence( - description = disposal.type.description, - date = disposal.date, - length = disposal.length?.toInt(), - lengthUnits = disposal.lengthUnits?.let { LengthUnit.valueOf(it.description) }, - custodial = disposal.type.isCustodial() - ) - }, - mainOffence = event.mainOffence.let { Offence.of(it.date, it.count, it.offence) }, - additionalOffences = event.additionalOffences.map { Offence.of(it.date, it.count, it.offence) }, - courtAppearances = event.courtAppearances.map { - CourtAppearance( - type = it.type.description, - date = it.date, - court = it.court.name, - plea = it.plea?.description - ) - } - ) - } - val mappaDetail = registrationRepository.findMappa(person.id)?.let { - MappaDetail( - it.level?.code?.toMappaLevel(), - it.level?.description, - it.category?.code?.toMappaCategory(), - it.category?.description, - it.date, - it.reviewDate, - it.notes + return Manager( + code = staff.code, + name = staff.name(), + username = staff.user?.username, + email = staff.user?.email, + telephoneNumber = staff.user?.telephone, + team = Team( + code = team.code, + description = team.description, + email = team.emailAddress, + telephoneNumber = team.telephone, + provider = Provider(provider.code, provider.description) ) - } - return SupervisionResponse(asCom(), mappaDetail, supervisions) + ) } -} - -enum class Category(val number: Int) { X9(0), M1(1), M2(2), M3(3), M4(4) } -enum class Level(val number: Int) { M0(0), M1(1), M2(2), M3(3) } -private fun String.toMappaLevel() = Level.entries.find { it.name == this }?.number - ?: throw IllegalStateException("Unexpected MAPPA level: $this") - -private fun String.toMappaCategory() = Category.entries.find { it.name == this }?.number - ?: throw IllegalStateException("Unexpected MAPPA category: $this") - -private fun PersonManager.asCom() = Manager( - staff.code, - staff.name(), - staff.user?.username, - staff.user?.email, - staff.user?.telephone, - team.asModel(provider()) -) + private fun RegistrationEntity?.toMappaResponse() = this?.let { + MappaDetail( + level = it.level?.code?.toMappaLevel(), + levelDescription = it.level?.description, + category = it.category?.code?.toMappaCategory(), + categoryDescription = it.category?.description, + startDate = it.date, + reviewDate = it.reviewDate, + notes = it.notes + ) + } -private fun PersonManager.provider() = Provider(provider.code, provider.description) + private fun List.toRegistrationResponse() = this.map { + Registration( + code = it.type.code, + description = it.type.description, + startDate = it.date, + reviewDate = it.reviewDate, + notes = it.notes + ) + } -private fun uk.gov.justice.digital.hmpps.integration.delius.entity.Team.asModel(provider: Provider) = - Team(code, description, emailAddress, telephone, provider) \ No newline at end of file + private fun List.toSupervisionResponse() = this.map { event -> + Supervision( + number = event.number.toInt(), + active = event.active, + date = event.convictionDate, + sentence = event.disposal?.let { disposal -> + Sentence( + description = disposal.type.description, + date = disposal.date, + length = disposal.length?.toInt(), + lengthUnits = disposal.lengthUnits?.let { LengthUnit.valueOf(it.description) }, + custodial = disposal.type.isCustodial() + ) + }, + mainOffence = event.mainOffence.let { Offence.of(it.date, it.count, it.offence) }, + additionalOffences = event.additionalOffences.map { Offence.of(it.date, it.count, it.offence) }, + courtAppearances = event.courtAppearances.map { + CourtAppearance( + type = it.type.description, + date = it.date, + court = it.court.name, + plea = it.plea?.description + ) + } + ) + } +} \ No newline at end of file From cbe312a2f6366c0a74eb73b70ebb073084901880 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 May 2024 15:38:27 +0100 Subject: [PATCH 09/10] Bump JamesIves/github-pages-deploy-action from 4.6.0 to 4.6.1 (#3815) Bumps [JamesIves/github-pages-deploy-action](https://github.com/jamesives/github-pages-deploy-action) from 4.6.0 to 4.6.1. - [Release notes](https://github.com/jamesives/github-pages-deploy-action/releases) - [Commits](https://github.com/jamesives/github-pages-deploy-action/compare/ec9c88baef04b842ca6f0a132fd61c762aa6c1b0...5c6e9e9f3672ce8fd37b9856193d2a537941e66c) --- updated-dependencies: - dependency-name: JamesIves/github-pages-deploy-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/docs.yml | 4 ++-- .github/workflows/schema-spy.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index ac866e3a91..0d94eed4f8 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -129,14 +129,14 @@ jobs: - name: Deploy main if: github.ref_name == 'main' - uses: JamesIves/github-pages-deploy-action@ec9c88baef04b842ca6f0a132fd61c762aa6c1b0 # v4.6.0 + uses: JamesIves/github-pages-deploy-action@5c6e9e9f3672ce8fd37b9856193d2a537941e66c # v4.6.1 with: folder: tech-docs target-folder: tech-docs - name: Deploy branch if: github.ref_name != 'main' - uses: JamesIves/github-pages-deploy-action@ec9c88baef04b842ca6f0a132fd61c762aa6c1b0 # v4.6.0 + uses: JamesIves/github-pages-deploy-action@5c6e9e9f3672ce8fd37b9856193d2a537941e66c # v4.6.1 with: folder: tech-docs target-folder: tech-docs-drafts/${{ github.ref_name }} diff --git a/.github/workflows/schema-spy.yml b/.github/workflows/schema-spy.yml index 6d911436ce..d6a2e03caf 100644 --- a/.github/workflows/schema-spy.yml +++ b/.github/workflows/schema-spy.yml @@ -34,7 +34,7 @@ jobs: DB_PASSWORD: ${{ secrets.SCHEMA_SPY_PASSWORD }} - name: Publish HTML report - uses: JamesIves/github-pages-deploy-action@ec9c88baef04b842ca6f0a132fd61c762aa6c1b0 # v4.6.0 + uses: JamesIves/github-pages-deploy-action@5c6e9e9f3672ce8fd37b9856193d2a537941e66c # v4.6.1 with: folder: schema-spy-report target-folder: schema-spy-report From 52ab5925a5a12040a2b37da69054f489ab7eb206 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 May 2024 15:38:46 +0100 Subject: [PATCH 10/10] Bump planetscale/ghcommit-action from 0.1.37 to 0.1.39 in /.github/actions/format-code (#3814) Bump planetscale/ghcommit-action in /.github/actions/format-code Bumps [planetscale/ghcommit-action](https://github.com/planetscale/ghcommit-action) from 0.1.37 to 0.1.39. - [Release notes](https://github.com/planetscale/ghcommit-action/releases) - [Commits](https://github.com/planetscale/ghcommit-action/compare/21a8cda29f55e5cc2cdae0cdbdd08e38dd148c25...b662a9d7235a07e80d976152ed5afe41651c4973) --- updated-dependencies: - dependency-name: planetscale/ghcommit-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/actions/format-code/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/format-code/action.yml b/.github/actions/format-code/action.yml index a28e5c3da3..2b12b44f7e 100644 --- a/.github/actions/format-code/action.yml +++ b/.github/actions/format-code/action.yml @@ -60,7 +60,7 @@ runs: env: mask: ${{ inputs.mask }} - - uses: planetscale/ghcommit-action@21a8cda29f55e5cc2cdae0cdbdd08e38dd148c25 # v0.2.9 + - uses: planetscale/ghcommit-action@b662a9d7235a07e80d976152ed5afe41651c4973 # v0.2.9 with: commit_message: ${{ inputs.commit_message }} repo: ${{ github.repository }}