Skip to content

Commit

Permalink
PI-1835 Handle recommendation deletion messages (#3127)
Browse files Browse the repository at this point in the history
  • Loading branch information
marcus-bcl authored Jan 29, 2024
1 parent eee6bbc commit 9cfb990
Show file tree
Hide file tree
Showing 12 changed files with 131 additions and 59 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,7 @@ import org.springframework.boot.context.event.ApplicationReadyEvent
import org.springframework.context.ApplicationListener
import org.springframework.stereotype.Component
import org.springframework.transaction.annotation.Transactional
import uk.gov.justice.digital.hmpps.data.generator.AddressGenerator
import uk.gov.justice.digital.hmpps.data.generator.ContactGenerator
import uk.gov.justice.digital.hmpps.data.generator.ContactOutcomeGenerator
import uk.gov.justice.digital.hmpps.data.generator.ContactTypeGenerator
import uk.gov.justice.digital.hmpps.data.generator.EventGenerator
import uk.gov.justice.digital.hmpps.data.generator.PersonGenerator
import uk.gov.justice.digital.hmpps.data.generator.PersonManagerGenerator
import uk.gov.justice.digital.hmpps.data.generator.RegistrationGenerator
import uk.gov.justice.digital.hmpps.data.generator.UserGenerator
import uk.gov.justice.digital.hmpps.data.generator.*
import uk.gov.justice.digital.hmpps.user.AuditUserRepository

@Component
Expand All @@ -34,11 +26,13 @@ class DataLoader(
override fun onApplicationEvent(ape: ApplicationReadyEvent) {
entityManager.run {
persist(ContactTypeGenerator.MANAGEMENT_OVERSIGHT_RECALL)
persist(ContactTypeGenerator.RECOMMENDATION_DELETED)
persist(ContactOutcomeGenerator.DECISION_TO_RECALL)
persist(ContactOutcomeGenerator.DECISION_NOT_TO_RECALL)
persist(PersonGenerator.RECOMMENDATION_STARTED)
persist(PersonGenerator.DECISION_TO_RECALL)
persist(PersonGenerator.DECISION_NOT_TO_RECALL)
persist(PersonGenerator.RECOMMENDATION_DELETED)

persist(PersonGenerator.DEFAULT_PROVIDER)
persist(PersonGenerator.DEFAULT_LAU)
Expand All @@ -47,6 +41,7 @@ class DataLoader(
persist(PersonGenerator.RECOMMENDATION_STARTED.manager!!)
persist(PersonGenerator.DECISION_TO_RECALL.manager!!)
persist(PersonGenerator.DECISION_NOT_TO_RECALL.manager!!)
persist(PersonGenerator.RECOMMENDATION_DELETED.manager!!)

persist(PersonGenerator.CASE_SUMMARY.gender)
persist(PersonGenerator.CASE_SUMMARY.ethnicity)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,6 @@ import uk.gov.justice.digital.hmpps.integrations.delius.recommendation.contact.e
object ContactTypeGenerator {
val MANAGEMENT_OVERSIGHT_RECALL =
ContactType(IdGenerator.getAndIncrement(), ContactType.MANAGEMENT_OVERSIGHT_RECALL)
val RECOMMENDATION_DELETED =
ContactType(IdGenerator.getAndIncrement(), ContactType.RECOMMENDATION_DELETED)
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ object PersonGenerator {
val RESTRICTED = generateUserAccess("X000005", restrictions = listOf(UserGenerator.TEST_USER1))
val EXCLUDED = generateUserAccess("X000006", exclusions = listOf(UserGenerator.TEST_USER1))
val NO_ACCESS_LIMITATIONS = generateUserAccess("X000007")
val RECOMMENDATION_DELETED = generate("X000008")

fun generate(
crn: String,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"eventType": "prison-recall.recommendation.deleted",
"version": 1,
"description": "Deleted recommendation in 'Consider a recall'",
"detailUrl": "http://localhost:{wiremock.port}/mrd/delete-recommendation-rationale/1",
"occurredAt": "2022-12-01T14:25:40.117Z",
"additionalInformation": {
"recommendationUrl": "https://example.com/overview",
"bookedBy": {
"username": "WithStaff"
}
},
"personReference": {
"identifiers": [
{
"type": "CRN",
"value": "X000008"
}
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"notes": "my rationale for deleting the case",
"sensitive": true
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,30 @@
{
"request": {
"method": "GET",
"urlPath": "/mrd/management-oversight/1"
},
"response": {
"headers": {
"Content-Type": "application/json"
"mappings": [
{
"request": {
"method": "GET",
"urlPath": "/mrd/management-oversight/1"
},
"response": {
"headers": {
"Content-Type": "application/json"
},
"status": 200,
"bodyFileName": "management-oversight-detail.json"
}
},
"status": 200,
"bodyFileName": "management-oversight-detail.json"
}
{
"request": {
"method": "GET",
"urlPath": "/mrd/delete-recommendation-rationale/1"
},
"response": {
"headers": {
"Content-Type": "application/json"
},
"status": 200,
"bodyFileName": "deletion.json"
}
}
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ internal class RecommendationIntegrationTest {
lateinit var telemetryService: TelemetryService

@Test
fun `management overview decision to recall`() {
fun `management oversight decision to recall`() {
val notification = prepEvent("management-oversight-recall", wireMockServer.port())
channelManager.getChannel(queueName).publishAndWait(notification)

Expand All @@ -56,7 +56,7 @@ internal class RecommendationIntegrationTest {
}

@Test
fun `management overview decision not to recall`() {
fun `management oversight decision not to recall`() {
val notification = prepEvent("management-oversight-not-recall", wireMockServer.port())
channelManager.getChannel(queueName).publishAndWait(notification)

Expand All @@ -74,6 +74,22 @@ internal class RecommendationIntegrationTest {
verify(telemetryService, atLeastOnce()).notificationReceived(notification)
}

@Test
fun `recommendation deleted`() {
val notification = prepEvent("recommendation-deleted", wireMockServer.port())
channelManager.getChannel(queueName).publishAndWait(notification)

val person = PersonGenerator.RECOMMENDATION_DELETED
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("my rationale for deleting the case"))
assertThat(contact.isSensitive, equalTo(true))
verify(telemetryService, atLeastOnce()).notificationReceived(notification)
}

private fun getContact(personId: Long) = entityManager
.createQuery("select c from Contact c where c.personId = :personId", Contact::class.java)
.setParameter("personId", personId)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,6 @@
package uk.gov.justice.digital.hmpps.integrations.delius.recommendation.contact.entity

import jakarta.persistence.Column
import jakarta.persistence.Convert
import jakarta.persistence.Entity
import jakarta.persistence.EntityListeners
import jakarta.persistence.GeneratedValue
import jakarta.persistence.GenerationType
import jakarta.persistence.Id
import jakarta.persistence.JoinColumn
import jakarta.persistence.Lob
import jakarta.persistence.ManyToOne
import jakarta.persistence.SequenceGenerator
import jakarta.persistence.Table
import jakarta.persistence.Version
import jakarta.persistence.*
import org.hibernate.annotations.Immutable
import org.hibernate.type.YesNoConverter
import org.springframework.data.annotation.CreatedBy
Expand Down Expand Up @@ -107,6 +95,7 @@ class ContactType(
) {
companion object {
const val MANAGEMENT_OVERSIGHT_RECALL = "MO5"
const val RECOMMENDATION_DELETED = "C517"
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import java.net.URI

interface MakeRecallDecisionsClient {
@GetExchange
fun getDetails(url: URI): DecisionDetails
fun getDetails(url: URI): RecommendationDetails

data class DecisionDetails(val notes: String, val sensitive: Boolean)
data class RecommendationDetails(val notes: String, val sensitive: Boolean)
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ import uk.gov.justice.digital.hmpps.converter.NotificationConverter
import uk.gov.justice.digital.hmpps.integrations.makerecalldecisions.MakeRecallDecisionsClient
import uk.gov.justice.digital.hmpps.message.HmppsDomainEvent
import uk.gov.justice.digital.hmpps.message.Notification
import uk.gov.justice.digital.hmpps.service.ManagementOversightRecall
import uk.gov.justice.digital.hmpps.service.RecommendationService
import uk.gov.justice.digital.hmpps.telemetry.TelemetryService
import uk.gov.justice.digital.hmpps.telemetry.notificationReceived
import java.net.URI

@Component
class Handler(
override val converter: NotificationConverter<HmppsDomainEvent>,
private val managementOversightRecall: ManagementOversightRecall,
private val recommendationService: RecommendationService,
private val makeRecallDecisionsClient: MakeRecallDecisionsClient,
private val telemetryService: TelemetryService
) : NotificationHandler<HmppsDomainEvent> {
Expand All @@ -22,14 +22,21 @@ class Handler(
val crn = notification.message.personReference.findCrn()
?: throw IllegalArgumentException("CRN not found in message")
when (notification.eventType) {
"prison-recall.recommendation.management-oversight" -> managementOversightRecall.decision(
"prison-recall.recommendation.management-oversight" -> recommendationService.managementOversight(
crn = crn,
decision = notification.decision(),
details = notification.details(),
username = notification.bookedByUsername(),
occurredAt = notification.message.occurredAt
)

"prison-recall.recommendation.deleted" -> recommendationService.deletion(
crn = crn,
details = notification.details(),
username = notification.bookedByUsername(),
occurredAt = notification.message.occurredAt
)

else -> throw NotImplementedError("Unhandled message type received: ${notification.eventType}")
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import uk.gov.justice.digital.hmpps.integrations.delius.recommendation.contact.C
import uk.gov.justice.digital.hmpps.integrations.delius.recommendation.contact.ContactRepository
import uk.gov.justice.digital.hmpps.integrations.delius.recommendation.contact.ContactTypeRepository
import uk.gov.justice.digital.hmpps.integrations.delius.recommendation.contact.entity.Contact
import uk.gov.justice.digital.hmpps.integrations.delius.recommendation.contact.entity.ContactOutcome
import uk.gov.justice.digital.hmpps.integrations.delius.recommendation.contact.entity.ContactType
import uk.gov.justice.digital.hmpps.integrations.delius.recommendation.contact.getByCode
import uk.gov.justice.digital.hmpps.integrations.delius.recommendation.person.PersonRepository
Expand All @@ -13,52 +14,71 @@ import uk.gov.justice.digital.hmpps.integrations.delius.recommendation.person.ge
import uk.gov.justice.digital.hmpps.integrations.delius.user.staff.StaffRepository
import uk.gov.justice.digital.hmpps.integrations.delius.user.staff.entity.Staff
import uk.gov.justice.digital.hmpps.integrations.delius.user.staff.getStaff
import uk.gov.justice.digital.hmpps.integrations.makerecalldecisions.MakeRecallDecisionsClient.DecisionDetails
import uk.gov.justice.digital.hmpps.integrations.makerecalldecisions.MakeRecallDecisionsClient.RecommendationDetails
import uk.gov.justice.digital.hmpps.messaging.ManagementDecision
import java.time.ZonedDateTime

@Service
class ManagementOversightRecall(
class RecommendationService(
private val personRepository: PersonRepository,
private val staffRepository: StaffRepository,
private val contactTypeRepository: ContactTypeRepository,
private val contactOutcomeRepository: ContactOutcomeRepository,
private val contactRepository: ContactRepository
) {

fun decision(
fun managementOversight(
crn: String,
decision: ManagementDecision,
details: DecisionDetails,
details: RecommendationDetails,
username: String,
occurredAt: ZonedDateTime
) {
val person = personRepository.getPerson(crn)
val staff = staffRepository.getStaff(username)
val contact = person.managementOversightRecall(decision, details.notes, details.sensitive, staff, occurredAt)
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)
)
contactRepository.save(contact)
}

private fun Person.managementOversightRecall(
decision: ManagementDecision,
notes: String,
sensitive: Boolean,
staff: Staff,
fun deletion(
crn: String,
details: RecommendationDetails,
username: String,
occurredAt: ZonedDateTime
) {
val contact = personRepository.getPerson(crn).addContact(
details,
date = occurredAt,
staff = staffRepository.getStaff(username),
type = contactTypeRepository.getByCode(ContactType.RECOMMENDATION_DELETED)
)
contactRepository.save(contact)
}

private fun Person.addContact(
details: RecommendationDetails,
staff: Staff,
date: ZonedDateTime,
type: ContactType,
outcome: ContactOutcome? = null,
): Contact {
checkNotNull(manager) { "No Active Person Manager" }
return Contact(
0,
id,
occurredAt,
occurredAt,
type = contactTypeRepository.getByCode(ContactType.MANAGEMENT_OVERSIGHT_RECALL),
notes = notes,
date,
date,
type = type,
notes = details.notes,
providerId = manager.providerId,
teamId = manager.teamId,
staffId = staff.id,
outcome = contactOutcomeRepository.getByCode(decision.code),
isSensitive = sensitive
outcome = outcome,
isSensitive = details.sensitive
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import uk.gov.justice.digital.hmpps.message.HmppsDomainEvent
import uk.gov.justice.digital.hmpps.message.MessageAttributes
import uk.gov.justice.digital.hmpps.message.Notification
import uk.gov.justice.digital.hmpps.message.PersonReference
import uk.gov.justice.digital.hmpps.service.ManagementOversightRecall
import uk.gov.justice.digital.hmpps.service.RecommendationService
import uk.gov.justice.digital.hmpps.telemetry.TelemetryService
import uk.gov.justice.digital.hmpps.telemetry.notificationReceived
import java.net.URI
Expand All @@ -30,7 +30,7 @@ internal class HandlerTest {
lateinit var converter: NotificationConverter<HmppsDomainEvent>

@Mock
lateinit var managementOversightRecall: ManagementOversightRecall
lateinit var recommendationService: RecommendationService

@Mock
lateinit var makeRecallDecisionsClient: MakeRecallDecisionsClient
Expand Down

0 comments on commit 9cfb990

Please sign in to comment.