Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

PI-2314: Only process cases with single active custodial events #3982

Merged
merged 4 commits into from
Jul 4, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,8 @@ class DataLoader(
PersonGenerator.CREATE_HANDOVER_AND_START,
PersonGenerator.UPDATE_HANDOVER_AND_START,
PersonGenerator.CREATE_SENTENCE_CHANGED,
PersonGenerator.PERSON_NOT_FOUND
PersonGenerator.PERSON_NOT_FOUND,
PersonGenerator.PERSON_MULTIPLE_CUSTODIAL
)
)
personManagerRepository.saveAll(
Expand Down Expand Up @@ -147,6 +148,24 @@ class DataLoader(
disposalRepository.save(EventGenerator.generateDisposal(sentenceChangedHandoverEvent))
custodyRepository.save(EventGenerator.generateCustody(sentenceChangedHandoverDisposal))

val notFoundSentenceChangedHandoverEvent =
eventRepository.save(EventGenerator.generateEvent(PersonGenerator.PERSON_NOT_FOUND.id))
val notFoundSentenceChangedHandoverDisposal =
disposalRepository.save(EventGenerator.generateDisposal(notFoundSentenceChangedHandoverEvent))
custodyRepository.save(EventGenerator.generateCustody(notFoundSentenceChangedHandoverDisposal))

//Multiple custodial
val multipleHandoverEvent1 =
eventRepository.save(EventGenerator.generateEvent(PersonGenerator.PERSON_MULTIPLE_CUSTODIAL.id))
val multipleHandoverEvent2 =
eventRepository.save(EventGenerator.generateEvent(PersonGenerator.PERSON_MULTIPLE_CUSTODIAL.id))
val multipleHandoverDisposal1 =
disposalRepository.save(EventGenerator.generateDisposal(multipleHandoverEvent1))
val multipleHandoverDisposal2 =
disposalRepository.save(EventGenerator.generateDisposal(multipleHandoverEvent2))
custodyRepository.save(EventGenerator.generateCustody(multipleHandoverDisposal1))
custodyRepository.save(EventGenerator.generateCustody(multipleHandoverDisposal2))

val handoverEvent = eventRepository.save(EventGenerator.generateEvent(PersonGenerator.HANDOVER.id))
val handoverDisposal = disposalRepository.save(EventGenerator.generateDisposal(handoverEvent))
custodyRepository.save(EventGenerator.generateCustody(handoverDisposal))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package uk.gov.justice.digital.hmpps.data.generator

import uk.gov.justice.digital.hmpps.data.generator.ReferenceDataGenerator.DEFAULT_CUSTODY_STATUS
import uk.gov.justice.digital.hmpps.integrations.delius.allocation.entity.event.Custody
import uk.gov.justice.digital.hmpps.integrations.delius.allocation.entity.event.Disposal
import uk.gov.justice.digital.hmpps.integrations.delius.allocation.entity.event.Event
Expand All @@ -26,9 +27,11 @@ object EventGenerator {

fun generateCustody(
disposal: Disposal,
status: ReferenceData = DEFAULT_CUSTODY_STATUS,
prisonerNumber: String? = "P1",
softDeleted: Boolean = false,
id: Long = IdGenerator.getAndIncrement()
) = Custody(disposal, softDeleted, id)
) = Custody(disposal, status, prisonerNumber, softDeleted, id)

fun generateKeyDate(
custody: Custody,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,6 @@ import uk.gov.justice.digital.hmpps.resourceloader.ResourceLoader
object MessageGenerator {
val SENTENCE_CHANGED = ResourceLoader.message<ProbationOffenderEvent>("sentence-changed")
val SENTENCE_CHANGED_NOT_FOUND = ResourceLoader.message<ProbationOffenderEvent>("sentence-changed-not-found")
val SENTENCE_CHANGED_MULTIPLE_CUSTODIAL =
ResourceLoader.message<ProbationOffenderEvent>("sentence-changed-multiple-custodial")
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ object PersonGenerator {
val CREATE_HANDOVER_AND_START = generate("H123458", "A4096BY")
val CREATE_SENTENCE_CHANGED = generate("H123459", "A4096CY")
val PERSON_NOT_FOUND = generate("H123410", "A4096DY")
val PERSON_MULTIPLE_CUSTODIAL = generate("H123412", "A4096DX")

fun generate(
crn: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import uk.gov.justice.digital.hmpps.integrations.delius.reference.entity.Referen
object ReferenceDataGenerator {
val KEY_DATE_TYPE_DATASET = generateDataSet(ReferenceDataSet.Code.KEY_DATE_TYPE.value)
val POM_ALLOCATION_DATASET = generateDataSet(ReferenceDataSet.Code.POM_ALLOCATION_REASON.value)
val CUSTODY_STATUS_DATASET = generateDataSet(ReferenceDataSet.Code.CUSTODY_STATUS.value)
val TIER_2 = generate("2", "Tier 2")
val DECISION_ENHANCED = generate("R")
val DECISION_NORMAL = generate("A")
Expand All @@ -17,6 +18,9 @@ object ReferenceDataGenerator {
val ALLOCATION_AUTO = generate("AUT", dataSetId = POM_ALLOCATION_DATASET.id)
val ALLOCATION_INA = generate("INA", dataSetId = POM_ALLOCATION_DATASET.id)

val TERMINATED_CUSTODY_STATUS = generate("P", dataSetId = CUSTODY_STATUS_DATASET.id)
val DEFAULT_CUSTODY_STATUS = generate("D", dataSetId = CUSTODY_STATUS_DATASET.id)

val KEY_DATE_HANDOVER_TYPE = generate(KeyDate.TypeCode.HANDOVER_DATE.value, dataSetId = KEY_DATE_TYPE_DATASET.id)
val KEY_DATE_HANDOVER_START_DATE_TYPE =
generate(KeyDate.TypeCode.HANDOVER_START_DATE.value, dataSetId = KEY_DATE_TYPE_DATASET.id)
Expand All @@ -32,7 +36,9 @@ object ReferenceDataGenerator {
KEY_DATE_HANDOVER_TYPE,
KEY_DATE_HANDOVER_START_DATE_TYPE,
ALLOCATION_AUTO,
ALLOCATION_INA
ALLOCATION_INA,
TERMINATED_CUSTODY_STATUS,
DEFAULT_CUSTODY_STATUS
)

fun generateDataSet(name: String, id: Long = IdGenerator.getAndIncrement()) = ReferenceDataSet(name, id)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"Type": "Notification",
"MessageId": "20e13002-d1be-56e7-be8c-66cdd7e23341",
"TopicArn": "arn:aws:sns:eu-west-2:754256621582:cloud-platform-Digital-Prison-Services-f221e27fcfcf78f6ab4f4c3cc165eee7",
"Message": "{\"eventType\":\"SENTENCE_CHANGED\",\"eventDatetime\":\"2020-02-25T11:24:32.935401\",\"offenderId\":1,\"crn\":\"H123412\",\"sourceId\":\"2500974056\"}",
"Timestamp": "2020-02-25T11:25:16.169Z",
"SignatureVersion": "1",
"Signature": "h5p3FnnbsSHxj53RFePh8HR40cbVvgEZa6XUVTlYs/yuqfDsi17MPA+bX4ijKmmTT2l6xG2xYhcmRAbJWQ4wrwncTBm2azgiwSO5keRNWYVdiC0rI484KLZboP1SDsE+Y7hOU/R0dz49q7+0yd+QIocPteKB/8xG7/6kjGStAZKf3cEdlxOwLhN+7RU1Yk2ENuwAJjVRtvlAa76yKB3xvL2hId7P7ZLmHGlzZDNZNYxbg9C8HGxteOzZ9ZeeQsWDf9jmZ+5+7dKXQoW9LeqwHxEAq2vuwSZ8uwM5JljXbtS5w1P0psXPYNoin2gU1F5MDK8RPzjUtIvjINx08rmEOA==",
"SigningCertURL": "https://sns.eu-west-2.amazonaws.com/SimpleNotificationService-a86cb10b4e1f29c941702d737128f7b6.pem",
"UnsubscribeURL": "https://sns.eu-west-2.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:eu-west-2:754256621582:cloud-platform-Digital-Prison-Services-f221e27fcfcf78f6ab4f4c3cc165eee7:92545cfe-de5d-43e1-8339-c366bf0172aa",
"MessageAttributes": {
"eventType": {
"Type": "String",
"Value": "SENTENCE_CHANGED"
},
"id": {
"Type": "String",
"Value": "cb4645f2-d0c1-4677-806a-8036ed54bf69"
},
"contentType": {
"Type": "String",
"Value": "text/plain;charset=UTF-8"
},
"timestamp": {
"Type": "Number.java.lang.Long",
"Value": "1582629916147"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import com.github.tomakehurst.wiremock.WireMockServer
import org.hamcrest.MatcherAssert.assertThat
import org.hamcrest.Matchers.equalTo
import org.junit.jupiter.api.Test
import org.mockito.kotlin.any
import org.mockito.kotlin.times
import org.mockito.kotlin.verify
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Value
Expand Down Expand Up @@ -140,4 +142,16 @@ internal class HandoverMessagingIntegrationTest {
)
)
}

@Test
fun `ignores a sentence changed event due to multiple custodial sentences`() {
val notification = Notification(
message = MessageGenerator.SENTENCE_CHANGED_MULTIPLE_CUSTODIAL,
attributes = MessageAttributes(eventType = "SENTENCE_CHANGED")
)

channelManager.getChannel(queueName).publishAndWait(notification)
//Check only 1 telemetry event
verify(telemetryService, times(1)).trackEvent(any(), any(), any())
}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
package uk.gov.justice.digital.hmpps.integrations.delius.allocation.entity.event

import jakarta.persistence.Column
import jakarta.persistence.Entity
import jakarta.persistence.Id
import jakarta.persistence.JoinColumn
import jakarta.persistence.OneToOne
import jakarta.persistence.Table
import jakarta.persistence.*
import org.hibernate.annotations.Immutable
import org.hibernate.annotations.SQLRestriction
import org.springframework.data.jpa.repository.JpaRepository
import uk.gov.justice.digital.hmpps.integrations.delius.reference.entity.ReferenceData

@Immutable
@Entity
Expand Down Expand Up @@ -63,6 +59,13 @@ class Custody(
@JoinColumn(name = "disposal_id", updatable = false)
val disposal: Disposal,

@ManyToOne
@JoinColumn(name = "custodial_status_id")
val status: ReferenceData,

@Column(name = "prisoner_number")
val bookingRef: String?,

@Column(columnDefinition = "number", nullable = false)
val softDeleted: Boolean = false,

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,21 @@ interface PersonRepository : JpaRepository<Person, Long> {
@Query("select p.id from Person p where p.id = :personId")
fun findForUpdate(personId: Long): Long

@Query("select p.nomsId from Person p where p.crn = :crn and p.softDeleted = false")
fun findNomsIdByCrn(crn: String): String?
@Query(
"""
select p.noms_number
from offender p
join event e on e.offender_id = p.offender_id and e.active_flag = 1 and e.soft_deleted = 0
join disposal d on d.event_id = e.event_id and d.active_flag = 1 and d.soft_deleted = 0
join custody c on c.disposal_id = d.disposal_id and c.prisoner_number is not null and c.soft_deleted = 0
join r_standard_reference_list cs on cs.standard_reference_list_id = c.custodial_status_id and cs.code_value <> 'P'
where p.crn = :crn
and p.noms_number is not null and p.soft_deleted = 0
group by p.noms_number
having count(p.noms_number) = 1
""", nativeQuery = true
)
fun findNomsSingleCustodial(crn: String): String?
}

fun PersonRepository.getByNomsId(nomsId: String) =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ class ReferenceDataSet(
) {
enum class Code(val value: String) {
KEY_DATE_TYPE("THROUGHCARE DATE TYPE"),
POM_ALLOCATION_REASON("POM ALLOCATION REASON")
POM_ALLOCATION_REASON("POM ALLOCATION REASON"),
CUSTODY_STATUS("THROUGHCARE STATUS"),
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class PomCaseMessageHandler(

is ProbationOffenderEvent -> when (notification.eventType) {
"SENTENCE_CHANGED",
-> personRepository.findNomsIdByCrn(message.crn)?.let {
-> personRepository.findNomsSingleCustodial(message.crn)?.let {
try {
handoverDatesChanged.process(
HandoverMessage(
Expand Down