Skip to content

Commit

Permalink
PI-2589 Handle missing NOMS number in event message (#4310)
Browse files Browse the repository at this point in the history
  • Loading branch information
marcus-bcl authored Oct 14, 2024
1 parent 9428f07 commit b8ee3fd
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,6 @@ object PersonGenerator {
val ECSLIRC_IN_CUSTODY = generate(NotificationGenerator.PRISONER_ECSLIRC_IN_CUSTODY.nomsId())
val ADMIN_MERGE = generate(NotificationGenerator.PRISONER_ADMIN_MERGE.nomsId())

fun generate(nomsNumber: String, id: Long = IdGenerator.getAndIncrement()) = Person(id, nomsNumber)
fun generate(nomsNumber: String, id: Long = IdGenerator.getAndIncrement()) =
Person(id, nomsNumber.reversed(), nomsNumber)
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import org.hibernate.annotations.Immutable
import org.hibernate.annotations.SQLRestriction
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.data.jpa.repository.Query
import uk.gov.justice.digital.hmpps.exception.NotFoundException
import uk.gov.justice.digital.hmpps.integrations.delius.referencedata.ReferenceData

@Immutable
Expand All @@ -16,6 +17,9 @@ class Person(
@Column(name = "offender_id")
val id: Long,

@Column(columnDefinition = "char(7)")
val crn: String,

@Column(columnDefinition = "char(7)")
val nomsNumber: String,

Expand All @@ -25,8 +29,14 @@ class Person(

interface PersonRepository : JpaRepository<Person, Long> {
fun findByNomsNumberAndSoftDeletedIsFalse(nomsNumber: String): List<Person>

@Query("select p.nomsNumber from Person p where p.crn = :crn and p.softDeleted = false")
fun findNomsNumberByCrn(crn: String): String?
}

fun PersonRepository.getNomsNumberByCrn(crn: String) =
findNomsNumberByCrn(crn) ?: throw NotFoundException("NOMS number for case", "crn", crn)

@Immutable
@Entity
@SQLRestriction("soft_deleted = 0")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import uk.gov.justice.digital.hmpps.converter.NotificationConverter
import uk.gov.justice.digital.hmpps.datetime.EuropeLondon
import uk.gov.justice.digital.hmpps.exception.IgnorableMessageException
import uk.gov.justice.digital.hmpps.flags.FeatureFlags
import uk.gov.justice.digital.hmpps.integrations.delius.person.entity.PersonRepository
import uk.gov.justice.digital.hmpps.integrations.delius.person.entity.getNomsNumberByCrn
import uk.gov.justice.digital.hmpps.integrations.prison.Booking
import uk.gov.justice.digital.hmpps.integrations.prison.Movement
import uk.gov.justice.digital.hmpps.integrations.prison.PrisonApiClient
Expand All @@ -30,7 +32,8 @@ class Handler(
private val telemetryService: TelemetryService,
private val prisonApiClient: PrisonApiClient,
private val actionProcessor: ActionProcessor,
override val converter: NotificationConverter<HmppsDomainEvent>
private val personRepository: PersonRepository,
override val converter: NotificationConverter<HmppsDomainEvent>,
) : NotificationHandler<HmppsDomainEvent> {
private val configs = configContainer.configs

Expand All @@ -46,10 +49,12 @@ class Handler(
telemetryService.notificationReceived(notification)
val message = notification.message
val eventType = DomainEventType.of(message.eventType)
val nomsId = message.personReference.findNomsNumber()
?: personRepository.getNomsNumberByCrn(requireNotNull(message.personReference.findCrn()))

try {
val movement = when (eventType) {
IdentifierAdded, IdentifierUpdated, PrisonerReceived, PrisonerReleased -> {
val nomsId = message.personReference.findNomsNumber()!!
val booking = prisonApiClient.bookingFromNomsId(nomsId)
val movement = prisonApiClient.getLatestMovement(listOf(nomsId)).firstOrNull()
movement?.let { booking.prisonerMovement(it) }
Expand All @@ -63,7 +68,7 @@ class Handler(
if (movement == null) {
throw IgnorableMessageException(
"NoMovementInNomis", mapOf(
"nomsNumber" to message.personReference.findNomsNumber()!!
"nomsNumber" to nomsId
)
)
}
Expand Down Expand Up @@ -109,10 +114,7 @@ class Handler(
throw failure.exception
}
} catch (e: IgnorableMessageException) {
telemetryService.trackEvent(
e.message,
message.telemetryProperties() + e.additionalProperties
)
telemetryService.trackEvent(e.message, message.telemetryProperties(nomsId) + e.additionalProperties)
}
}

Expand All @@ -126,9 +128,9 @@ class Handler(

fun HmppsDomainEvent.prisonId() = additionalInformation["prisonId"] as String?
fun HmppsDomainEvent.details() = additionalInformation["details"] as String?
fun HmppsDomainEvent.telemetryProperties() = listOfNotNull(
fun HmppsDomainEvent.telemetryProperties(nomsId: String) = listOfNotNull(
"occurredAt" to occurredAt.toString(),
"nomsNumber" to personReference.findNomsNumber()!!,
"nomsNumber" to nomsId,
prisonId()?.let { "institution" to it },
details()?.let { "details" to it }
).toMap()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import uk.gov.justice.digital.hmpps.converter.NotificationConverter
import uk.gov.justice.digital.hmpps.data.generator.InstitutionGenerator
import uk.gov.justice.digital.hmpps.datetime.EuropeLondon
import uk.gov.justice.digital.hmpps.flags.FeatureFlags
import uk.gov.justice.digital.hmpps.integrations.delius.person.entity.PersonRepository
import uk.gov.justice.digital.hmpps.integrations.prison.Booking
import uk.gov.justice.digital.hmpps.integrations.prison.Movement
import uk.gov.justice.digital.hmpps.integrations.prison.PrisonApiClient
Expand Down Expand Up @@ -40,6 +41,9 @@ internal class HandlerTest {
@Mock
lateinit var actionProcessor: ActionProcessor

@Mock
lateinit var personRepository: PersonRepository

private val configs = PrisonerMovementConfigs(
listOf(
PrisonerMovementConfig(
Expand All @@ -58,7 +62,15 @@ internal class HandlerTest {

@BeforeEach
fun setup() {
handler = Handler(configs, featureFlags, telemetryService, prisonApiClient, actionProcessor, converter)
handler = Handler(
configs,
featureFlags,
telemetryService,
prisonApiClient,
actionProcessor,
personRepository,
converter
)
}

private val notification = Notification(
Expand Down Expand Up @@ -292,6 +304,25 @@ internal class HandlerTest {
)
}

@Test
fun `lookup noms number by crn`() {
whenever(personRepository.findNomsNumberByCrn("X123456")).thenReturn("A1234AA")
whenever(prisonApiClient.getBookingByNomsId("A1234AA")).thenReturn(booking.copy(active = false))

handler.handle(
notification.copy(
message = notification.message.copy(
personReference = PersonReference(listOf(PersonIdentifier("CRN", "X123456"))),
)
)
)

verify(personRepository).findNomsNumberByCrn("X123456")
verify(telemetryService).trackEvent(eq("BookingInactive"), check {
assertThat(it["nomsNumber"], equalTo("A1234AA"))
}, any())
}

private fun Booking.movement() = Movement(
"OUT",
agencyId,
Expand Down

0 comments on commit b8ee3fd

Please sign in to comment.