diff --git a/projects/prison-case-notes-to-probation/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/CaseNotesDataLoader.kt b/projects/prison-case-notes-to-probation/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/CaseNotesDataLoader.kt index cf34abefb6..11f063760d 100644 --- a/projects/prison-case-notes-to-probation/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/CaseNotesDataLoader.kt +++ b/projects/prison-case-notes-to-probation/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/CaseNotesDataLoader.kt @@ -66,6 +66,8 @@ class CaseNotesDataLoader( caseNoteTypeRepository.save(CaseNoteTypeGenerator.DEFAULT) caseNoteTypeRepository.save(CaseNoteNomisTypeGenerator.NEG.type) caseNoteNomisTypeRepository.save(CaseNoteNomisTypeGenerator.NEG) + caseNoteTypeRepository.save(CaseNoteNomisTypeGenerator.RESETTLEMENT.type) + caseNoteNomisTypeRepository.save(CaseNoteNomisTypeGenerator.RESETTLEMENT) institutionRepository.save(ProbationAreaGenerator.DEFAULT.institution!!) probationAreaRepository.save(ProbationAreaGenerator.DEFAULT) diff --git a/projects/prison-case-notes-to-probation/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/CaseNoteMessageGenerator.kt b/projects/prison-case-notes-to-probation/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/CaseNoteMessageGenerator.kt index 6c25f43c82..207864c9f4 100644 --- a/projects/prison-case-notes-to-probation/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/CaseNoteMessageGenerator.kt +++ b/projects/prison-case-notes-to-probation/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/CaseNoteMessageGenerator.kt @@ -7,4 +7,5 @@ object CaseNoteMessageGenerator { val EXISTS_IN_DELIUS: HmppsDomainEvent = ResourceLoader.message("case-note-exists-in-delius") val NEW_TO_DELIUS: HmppsDomainEvent = ResourceLoader.message("case-note-new-to-delius") val NOT_FOUND: HmppsDomainEvent = ResourceLoader.message("case-note-not-found") + val RESETTLEMENT_PASSPORT: HmppsDomainEvent = ResourceLoader.message("resettlement-passport-casenote") } diff --git a/projects/prison-case-notes-to-probation/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/CaseNoteNomisTypeGenerator.kt b/projects/prison-case-notes-to-probation/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/CaseNoteNomisTypeGenerator.kt index c9b340c56e..b3707fb776 100644 --- a/projects/prison-case-notes-to-probation/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/CaseNoteNomisTypeGenerator.kt +++ b/projects/prison-case-notes-to-probation/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/CaseNoteNomisTypeGenerator.kt @@ -20,4 +20,12 @@ object CaseNoteNomisTypeGenerator { false ) ) + val RESETTLEMENT = CaseNoteNomisType( + "RESET BCST", + CaseNoteType( + IdGenerator.getAndIncrement(), + "BCSP2", + false + ) + ) } diff --git a/projects/prison-case-notes-to-probation/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/PrisonCaseNoteGenerator.kt b/projects/prison-case-notes-to-probation/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/PrisonCaseNoteGenerator.kt index 238d9e7459..d6945cc25d 100644 --- a/projects/prison-case-notes-to-probation/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/PrisonCaseNoteGenerator.kt +++ b/projects/prison-case-notes-to-probation/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/PrisonCaseNoteGenerator.kt @@ -6,4 +6,5 @@ import uk.gov.justice.digital.hmpps.resourceloader.ResourceLoader object PrisonCaseNoteGenerator { val EXISTING_IN_BOTH = ResourceLoader.file("get-case-note-body-exists-in-delius") val NEW_TO_DELIUS = ResourceLoader.file("get-case-note-body-new-to-delius") + val RESETTLEMENT_PASSPORT = ResourceLoader.file("get-case-note-body-resettlement-passport-new") } diff --git a/projects/prison-case-notes-to-probation/src/dev/resources/messages/resettlement-passport-casenote.json b/projects/prison-case-notes-to-probation/src/dev/resources/messages/resettlement-passport-casenote.json new file mode 100644 index 0000000000..ca967e19f3 --- /dev/null +++ b/projects/prison-case-notes-to-probation/src/dev/resources/messages/resettlement-passport-casenote.json @@ -0,0 +1,17 @@ +{ + "MessageId": "ae06c49e-1f41-4b9f-b2f2-dcca610d02cd", + "Type": "Notification", + "Timestamp": "2019-10-21T14:01:18.500Z", + "Message": "{\"eventType\":\"prison.case-note.published\",\"version\":1,\"description\":\"A prison case note has been created or amended\",\"occurredAt\":\"2022-10-18T08:19:19.451579+01:00\",\"detailUrl\":\"http://localhost:{wiremock.port}/case-notes/AA0001A/5767\",\"additionalInformation\":{\"caseNoteId\":\"5767\",\"caseNoteType\":\"RESET-BCST\"},\"personReference\":{\"identifiers\":[{\"type\":\"NOMS\",\"value\":\"AA0001A\"}]}}", + "TopicArn": "arn:aws:sns:eu-west-1:000000000000:offender_events", + "MessageAttributes": { + "eventType": { + "Type": "String", + "Value": "prison.case-note.published" + }, + "caseNoteType": { + "Type": "String", + "Value": "RESET-BCST" + } + } +} \ No newline at end of file diff --git a/projects/prison-case-notes-to-probation/src/dev/resources/simulations/__files/get-case-note-body-resettlement-passport-new.json b/projects/prison-case-notes-to-probation/src/dev/resources/simulations/__files/get-case-note-body-resettlement-passport-new.json new file mode 100644 index 0000000000..58083c8ecd --- /dev/null +++ b/projects/prison-case-notes-to-probation/src/dev/resources/simulations/__files/get-case-note-body-resettlement-passport-new.json @@ -0,0 +1,13 @@ +{ + "caseNoteId": 5767, + "eventId": 576777, + "offenderIdentifier": "AA0001A", + "type": "RESET", + "subType": "BCST", + "creationDateTime": "2021-04-16T11:22:33+01:00", + "occurrenceDateTime": "2021-03-23T11:22:00+01:00", + "authorName": "Some Name", + "text": "note content", + "locationId": "LEI", + "amendments": [] +} \ No newline at end of file diff --git a/projects/prison-case-notes-to-probation/src/dev/resources/simulations/mappings/get-case-note.json b/projects/prison-case-notes-to-probation/src/dev/resources/simulations/mappings/get-case-note.json index 4e8589e50f..6a9cce1a09 100644 --- a/projects/prison-case-notes-to-probation/src/dev/resources/simulations/mappings/get-case-note.json +++ b/projects/prison-case-notes-to-probation/src/dev/resources/simulations/mappings/get-case-note.json @@ -27,6 +27,20 @@ "bodyFileName": "get-case-note-body-new-to-delius.json" } }, + { + "request": { + "method": "GET", + "url": "/case-notes/AA0001A/5767" + }, + "response": { + "headers": { + "Accept": "application/json", + "Content-Type": "application/json" + }, + "status": 200, + "bodyFileName": "get-case-note-body-resettlement-passport-new.json" + } + }, { "request": { "method": "GET", diff --git a/projects/prison-case-notes-to-probation/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/CaseNotesIntegrationTest.kt b/projects/prison-case-notes-to-probation/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/CaseNotesIntegrationTest.kt index e4c42598fb..24b6e52224 100644 --- a/projects/prison-case-notes-to-probation/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/CaseNotesIntegrationTest.kt +++ b/projects/prison-case-notes-to-probation/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/CaseNotesIntegrationTest.kt @@ -2,35 +2,26 @@ package uk.gov.justice.digital.hmpps import com.github.tomakehurst.wiremock.WireMockServer import org.hamcrest.MatcherAssert.assertThat -import org.hamcrest.Matchers.equalTo -import org.hamcrest.Matchers.greaterThan -import org.hamcrest.Matchers.stringContainsInOrder +import org.hamcrest.Matchers.* import org.junit.jupiter.api.Assertions.assertNotNull import org.junit.jupiter.api.Assertions.assertNull import org.junit.jupiter.api.Test import org.mockito.ArgumentMatchers.any import org.mockito.ArgumentMatchers.anyMap -import org.mockito.kotlin.atLeastOnce -import org.mockito.kotlin.eq -import org.mockito.kotlin.never -import org.mockito.kotlin.verify +import org.mockito.kotlin.* import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.annotation.Value import org.springframework.boot.test.context.SpringBootTest import org.springframework.boot.test.mock.mockito.MockBean import org.springframework.boot.test.mock.mockito.SpyBean import uk.gov.justice.digital.hmpps.audit.repository.AuditedInteractionRepository -import uk.gov.justice.digital.hmpps.data.generator.CaseNoteMessageGenerator -import uk.gov.justice.digital.hmpps.data.generator.CaseNoteNomisTypeGenerator -import uk.gov.justice.digital.hmpps.data.generator.EventGenerator -import uk.gov.justice.digital.hmpps.data.generator.NsiGenerator -import uk.gov.justice.digital.hmpps.data.generator.PrisonCaseNoteGenerator -import uk.gov.justice.digital.hmpps.data.generator.ProbationAreaGenerator -import uk.gov.justice.digital.hmpps.data.generator.UserGenerator +import uk.gov.justice.digital.hmpps.data.generator.* import uk.gov.justice.digital.hmpps.datetime.DeliusDateTimeFormatter +import uk.gov.justice.digital.hmpps.flags.FeatureFlags import uk.gov.justice.digital.hmpps.integrations.delius.repository.CaseNoteRepository import uk.gov.justice.digital.hmpps.integrations.delius.repository.StaffRepository import uk.gov.justice.digital.hmpps.messaging.HmppsChannelManager +import uk.gov.justice.digital.hmpps.messaging.ProcessResettlementPassport import uk.gov.justice.digital.hmpps.telemetry.TelemetryService import uk.gov.justice.digital.hmpps.test.CustomMatchers.isCloseTo import java.time.ZonedDateTime @@ -61,6 +52,9 @@ class CaseNotesIntegrationTest { @SpyBean lateinit var air: AuditedInteractionRepository + @MockBean + lateinit var featureFlags: FeatureFlags + @Test fun `update an existing case note succesfully`() { val nomisCaseNote = PrisonCaseNoteGenerator.EXISTING_IN_BOTH @@ -144,4 +138,47 @@ class CaseNotesIntegrationTest { verify(telemetryService, never()).trackEvent(eq(CASE_NOTE_MERGED), anyMap(), anyMap()) } + + @Test + fun `create a new case note for resettlement passport`() { + whenever(featureFlags.enabled(ProcessResettlementPassport)).thenReturn(true) + val nomisCaseNote = PrisonCaseNoteGenerator.RESETTLEMENT_PASSPORT + + channelManager.getChannel(queueName).publishAndWait( + prepMessage(CaseNoteMessageGenerator.RESETTLEMENT_PASSPORT, wireMockserver.port()) + ) + + verify(telemetryService).trackEvent(eq(CASE_NOTE_MERGED), anyMap(), anyMap()) + val saved = caseNoteRepository.findByNomisId(nomisCaseNote.eventId) + assertNotNull(saved) + + assertThat( + saved!!.notes, + stringContainsInOrder(nomisCaseNote.type, nomisCaseNote.subType, nomisCaseNote.text) + ) + + assertThat( + saved.type.code, + equalTo(CaseNoteNomisTypeGenerator.RESETTLEMENT.type.code) + ) + + assertThat( + saved.eventId, + equalTo(EventGenerator.CUSTODIAL_EVENT.id) + ) + + val staff = staffRepository.findById(saved.staffId).orElseThrow() + assertThat(staff.code, equalTo("${ProbationAreaGenerator.DEFAULT.code}B001")) + } + + @Test + fun `does not create a new case note for resettlement passport when feature flag disabled`() { + whenever(featureFlags.enabled(ProcessResettlementPassport)).thenReturn(false) + + channelManager.getChannel(queueName).publishAndWait( + prepMessage(CaseNoteMessageGenerator.RESETTLEMENT_PASSPORT, wireMockserver.port()) + ) + + verify(telemetryService).trackEvent(eq("CaseNoteIgnored"), anyMap(), anyMap()) + } } diff --git a/projects/prison-case-notes-to-probation/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/prison/PrisonCaseNote.kt b/projects/prison-case-notes-to-probation/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/prison/PrisonCaseNote.kt index c7e076827f..1787677509 100644 --- a/projects/prison-case-notes-to-probation/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/prison/PrisonCaseNote.kt +++ b/projects/prison-case-notes-to-probation/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/prison/PrisonCaseNote.kt @@ -30,6 +30,8 @@ data class PrisonCaseNote( } else { StaffName(authorName.substringBeforeLast(" ").trim(), authorName.substringAfterLast(" ").trim()) } + + fun isResettlementPassport() = type == "RESET" && subType == "BCST" } data class CaseNoteAmendment( diff --git a/projects/prison-case-notes-to-probation/src/main/kotlin/uk/gov/justice/digital/hmpps/messaging/Handler.kt b/projects/prison-case-notes-to-probation/src/main/kotlin/uk/gov/justice/digital/hmpps/messaging/Handler.kt index 894bba7add..2d49ee36cf 100644 --- a/projects/prison-case-notes-to-probation/src/main/kotlin/uk/gov/justice/digital/hmpps/messaging/Handler.kt +++ b/projects/prison-case-notes-to-probation/src/main/kotlin/uk/gov/justice/digital/hmpps/messaging/Handler.kt @@ -8,23 +8,24 @@ import org.springframework.web.client.HttpStatusCodeException import uk.gov.justice.digital.hmpps.converter.NotificationConverter import uk.gov.justice.digital.hmpps.datetime.DeliusDateTimeFormatter import uk.gov.justice.digital.hmpps.exceptions.OffenderNotFoundException +import uk.gov.justice.digital.hmpps.flags.FeatureFlags import uk.gov.justice.digital.hmpps.integrations.delius.service.DeliusService -import uk.gov.justice.digital.hmpps.integrations.prison.PrisonCaseNote -import uk.gov.justice.digital.hmpps.integrations.prison.PrisonCaseNoteFilters -import uk.gov.justice.digital.hmpps.integrations.prison.PrisonCaseNotesClient -import uk.gov.justice.digital.hmpps.integrations.prison.toDeliusCaseNote +import uk.gov.justice.digital.hmpps.integrations.prison.* import uk.gov.justice.digital.hmpps.message.HmppsDomainEvent import uk.gov.justice.digital.hmpps.message.Notification import uk.gov.justice.digital.hmpps.telemetry.TelemetryService import uk.gov.justice.digital.hmpps.telemetry.notificationReceived import java.net.URI +const val ProcessResettlementPassport = "case-note-resettlement-passport" + @Component class Handler( val prisonCaseNotesClient: PrisonCaseNotesClient, val deliusService: DeliusService, val telemetryService: TelemetryService, - override val converter: NotificationConverter + override val converter: NotificationConverter, + val featureFlags: FeatureFlags ) : NotificationHandler { companion object { @@ -61,7 +62,11 @@ class Handler( } val reasonToIgnore: Lazy = lazy { - PrisonCaseNoteFilters.filters.firstOrNull { it.predicate.invoke(prisonCaseNote!!) }?.reason + (PrisonCaseNoteFilters.filters + PrisonCaseNoteFilter( + "Processing of Resettlement Passport case notes is disabled" + ) { it.isResettlementPassport() && !featureFlags.enabled(ProcessResettlementPassport) }).firstOrNull { + it.predicate.invoke(prisonCaseNote!!) + }?.reason } if (prisonCaseNote == null || reasonToIgnore.value != null) { diff --git a/projects/prison-case-notes-to-probation/src/test/kotlin/uk/gov/justice/digital/hmpps/messaging/HandlerTest.kt b/projects/prison-case-notes-to-probation/src/test/kotlin/uk/gov/justice/digital/hmpps/messaging/HandlerTest.kt index 30e2a14b83..4d97bf7556 100644 --- a/projects/prison-case-notes-to-probation/src/test/kotlin/uk/gov/justice/digital/hmpps/messaging/HandlerTest.kt +++ b/projects/prison-case-notes-to-probation/src/test/kotlin/uk/gov/justice/digital/hmpps/messaging/HandlerTest.kt @@ -17,6 +17,7 @@ import uk.gov.justice.digital.hmpps.converter.NotificationConverter import uk.gov.justice.digital.hmpps.data.generator.CaseNoteMessageGenerator import uk.gov.justice.digital.hmpps.exceptions.OffenderNotFoundException import uk.gov.justice.digital.hmpps.exceptions.StaffCodeExhaustedException +import uk.gov.justice.digital.hmpps.flags.FeatureFlags import uk.gov.justice.digital.hmpps.integrations.delius.service.DeliusService import uk.gov.justice.digital.hmpps.integrations.prison.PrisonCaseNote import uk.gov.justice.digital.hmpps.integrations.prison.PrisonCaseNotesClient @@ -43,6 +44,9 @@ internal class HandlerTest { @Mock private lateinit var converter: NotificationConverter + @Mock + private lateinit var featureFlags: FeatureFlags + @InjectMocks private lateinit var handler: Handler