Skip to content

Commit

Permalink
PI-2729 Set external_reference for case notes (#4544)
Browse files Browse the repository at this point in the history
* PI-2729

* Formatting changes

---------

Co-authored-by: probation-integration-bot[bot] <177347787+probation-integration-bot[bot]@users.noreply.github.com>
  • Loading branch information
1 parent 693259f commit 5787ca9
Show file tree
Hide file tree
Showing 20 changed files with 165 additions and 68 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,20 @@
"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/1111\",\"additionalInformation\":{\"caseNoteId\":\"1111\",\"caseNoteType\":\"NEG-IEP_WARN\"},\"personReference\":{\"identifiers\":[{\"type\":\"NOMS\",\"value\":\"AA0001A\"}]}}",
"Message": "{\"eventType\":\"person.case-note.updated\",\"version\":1,\"description\":\"A prison case note has been amended\",\"occurredAt\":\"2022-10-18T08:19:19.451579+01:00\",\"detailUrl\":\"http://localhost:{wiremock.port}/case-notes/AA0001A/0ec15f8b-6b57-471f-b02a-c89169a6a3e5\",\"additionalInformation\":{\"id\":\"0ec15f8b-6b57-471f-b02a-c89169a6a3e5\",\"legacyId\":\"1111\",\"type\":\"NEG\",\"subType\":\"IEP_WARN\"},\"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"
"Value": "person.case-note.updated"
},
"caseNoteType": {
"type": {
"Type": "String",
"Value": "NEG-IEP_WARN"
"Value": "NEG"
},
"subType": {
"Type": "String",
"Value": "IEP_WARN"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,20 @@
"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/2222\",\"additionalInformation\":{\"caseNoteId\":\"2222\",\"caseNoteType\":\"NEG-IEP_WARN\"},\"personReference\":{\"identifiers\":[{\"type\":\"NOMS\",\"value\":\"AA0001A\"}]}}",
"Message": "{\"eventType\":\"person.case-note.created\",\"version\":1,\"description\":\"A prison case note has been created\",\"occurredAt\":\"2022-10-18T08:19:19.451579+01:00\",\"detailUrl\":\"http://localhost:{wiremock.port}/case-notes/AA0001A/2cf4f9e1-df22-49a1-a2a7-5968a96529e3\",\"additionalInformation\":{\"id\":\"2cf4f9e1-df22-49a1-a2a7-5968a96529e3\",\"legacyId\":\"2222\",\"type\":\"NEG\",\"subType\":\"IEP_WARN\"},\"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"
"Value": "person.case-note.created"
},
"caseNoteType": {
"type": {
"Type": "String",
"Value": "NEG-IEP_WARN"
"Value": "NEG"
},
"subType": {
"Type": "String",
"Value": "IEP_WARN"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,20 @@
"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/4444\",\"additionalInformation\":{\"caseNoteId\":\"4444\",\"caseNoteType\":\"NEG-IEP_WARN\"},\"personReference\":{\"identifiers\":[{\"type\":\"NOMS\",\"value\":\"AA0001A\"}]}}",
"Message": "{\"eventType\":\"person.case-note.created\",\"version\":1,\"description\":\"A prison case note has been created\",\"occurredAt\":\"2022-10-18T08:19:19.451579+01:00\",\"detailUrl\":\"http://localhost:{wiremock.port}/case-notes/AA0001A/da82e1df-1a74-486e-842c-6ce961575211\",\"additionalInformation\":{\"id\":\"da82e1df-1a74-486e-842c-6ce961575211\",\"legacyId\":\"432109\",\"type\":\"NEG\",\"subType\":\"IEP_WARN\"},\"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"
"Value": "person.case-note.created"
},
"caseNoteType": {
"type": {
"Type": "String",
"Value": "NEG-IEP_WARN"
"Value": "NEG"
},
"subType": {
"Type": "String",
"Value": "IEP_WARN"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,20 @@
"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\"}]}}",
"Message": "{\"eventType\":\"person.case-note.created\",\"version\":1,\"description\":\"A prison case note has been created\",\"occurredAt\":\"2022-10-18T08:19:19.451579+01:00\",\"detailUrl\":\"http://localhost:{wiremock.port}/case-notes/AA0001A/9f0a2112-acde-4501-b1f9-3f2f5f04e426\",\"additionalInformation\":{\"id\":\"9f0a2112-acde-4501-b1f9-3f2f5f04e426\",\"legacyId\":\"576777\",\"type\":\"RESET\",\"subType\":\"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"
"Value": "person.case-note.created"
},
"caseNoteType": {
"type": {
"Type": "String",
"Value": "RESET-BCST"
"Value": "RESET"
},
"subType": {
"Type": "String",
"Value": "BCST"
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"caseNoteId": 1111,
"caseNoteId": "0ec15f8b-6b57-471f-b02a-c89169a6a3e5",
"eventId": 11111,
"offenderIdentifier": "AA0001A",
"type": "NEG",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"caseNoteId": 2222,
"caseNoteId": "2cf4f9e1-df22-49a1-a2a7-5968a96529e3",
"eventId": 22222,
"offenderIdentifier": "AA0001A",
"type": "NEG",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"caseNoteId": 5767,
"caseNoteId": "9f0a2112-acde-4501-b1f9-3f2f5f04e426",
"eventId": 576777,
"offenderIdentifier": "AA0001A",
"type": "RESET",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
{
"request": {
"method": "GET",
"url": "/case-notes/AA0001A/1111"
"url": "/case-notes/AA0001A/0ec15f8b-6b57-471f-b02a-c89169a6a3e5"
},
"response": {
"headers": {
Expand All @@ -16,7 +16,7 @@
{
"request": {
"method": "GET",
"url": "/case-notes/AA0001A/2222"
"url": "/case-notes/AA0001A/2cf4f9e1-df22-49a1-a2a7-5968a96529e3"
},
"response": {
"headers": {
Expand All @@ -30,7 +30,7 @@
{
"request": {
"method": "GET",
"url": "/case-notes/AA0001A/5767"
"url": "/case-notes/AA0001A/9f0a2112-acde-4501-b1f9-3f2f5f04e426"
},
"response": {
"headers": {
Expand All @@ -44,7 +44,7 @@
{
"request": {
"method": "GET",
"url": "/case-notes/AA0001A/4444"
"url": "/case-notes/AA0001A/da82e1df-1a74-486e-842c-6ce961575211"
},
"response": {
"status": 404,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ data class CaseNote(
val nsiId: Long?,

@Column(name = "nomis_case_note_id", updatable = false)
val nomisId: Long,
val nomisId: Long?,

@ManyToOne
@JoinColumn(name = "contact_type_id", updatable = false)
Expand Down Expand Up @@ -55,6 +55,8 @@ data class CaseNote(
@Column(updatable = false)
val probationAreaId: Long,

var externalReference: String? = null,

@Column(name = "sensitive")
@Convert(converter = YesNoConverter::class)
val isSensitive: Boolean = type.isSensitive,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@ import jakarta.validation.constraints.NotNull
import uk.gov.justice.digital.hmpps.integrations.delius.entity.CaseNoteType
import uk.gov.justice.digital.hmpps.model.StaffName
import java.time.ZonedDateTime
import java.util.*

data class DeliusCaseNote(val header: CaseNoteHeader, val body: CaseNoteBody)
data class DeliusCaseNote(val header: CaseNoteHeader, val body: CaseNoteBody) {
val urn = header.uuid?.let { "urn:uk:gov:hmpps:prison-case-note:${it}" }
}

data class CaseNoteHeader(val nomisId: String, val noteId: Long)
data class CaseNoteHeader(val nomisId: String, val legacyId: Long, val uuid: UUID?)
data class CaseNoteBody(
@NotBlank
val type: String,
Expand Down Expand Up @@ -45,7 +48,7 @@ data class CaseNoteBody(
}
}

fun isResettlementPassport() = type == "RESET" && subType == "BCST"
private fun isResettlementPassport() = type == "RESET" && subType == "BCST"
}

fun String.isAlertType() = this == "ALERT ACTIVE" || this == "ALERT INACTIVE"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ import uk.gov.justice.digital.hmpps.integrations.delius.entity.CaseNote

interface CaseNoteRepository : JpaRepository<CaseNote, Long> {
fun findByNomisId(nomisId: Long): CaseNote?
fun findByExternalReference(externalReference: String): CaseNote?
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,17 @@ class DeliusService(
private val relatedService: CaseNoteRelatedService
) : AuditableService(auditedInteractionService) {
@Transactional
fun mergeCaseNote(@Valid caseNote: DeliusCaseNote) = audit(CASE_NOTES_MERGE) {
it["nomisId"] = caseNote.header.noteId
fun mergeCaseNote(@Valid caseNote: DeliusCaseNote) = audit(CASE_NOTES_MERGE) { audit ->
audit["nomisId"] = caseNote.header.legacyId
caseNote.header.uuid?.also { audit["dpsId"] = it }

val existing = caseNoteRepository.findByNomisId(caseNote.header.noteId)
val existing = caseNote.urn?.let { caseNoteRepository.findByExternalReference(it) }
?: caseNoteRepository.findByNomisId(caseNote.header.legacyId)

val entity = if (existing == null) caseNote.newEntity() else existing.updateFrom(caseNote)
if (entity != null) {
caseNoteRepository.save(entity)
it["contactId"] = entity.id
audit["contactId"] = entity.id
}
}

Expand All @@ -48,7 +50,8 @@ class DeliusService(
notes = caseNote.body.notes(notes.length),
date = caseNote.body.contactTimeStamp,
startTime = caseNote.body.contactTimeStamp,
lastModifiedDateTime = caseNote.body.systemTimestamp
lastModifiedDateTime = caseNote.body.systemTimestamp,
externalReference = caseNote.urn
)
} else {
log.warn("Case Note update ignored because it was out of sequence ${caseNote.header}")
Expand All @@ -74,7 +77,7 @@ class DeliusService(
eventId = relatedIds.eventId,
nsiId = relatedIds.nsiId,
type = caseNoteType,
nomisId = header.noteId,
nomisId = header.legacyId,
description = description,
notes = body.notes(),
date = body.contactTimeStamp,
Expand All @@ -83,7 +86,8 @@ class DeliusService(
probationAreaId = assignment.first,
teamId = assignment.second,
staffId = assignment.third,
staffEmployeeId = assignment.third
staffEmployeeId = assignment.third,
externalReference = urn
)
}

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.model.CaseNoteHeader
import uk.gov.justice.digital.hmpps.integrations.delius.model.DeliusCaseNote
import uk.gov.justice.digital.hmpps.model.StaffName
import java.time.ZonedDateTime
import java.util.*

const val UNKNOWN_LOCATION = "UNK"

Expand All @@ -30,8 +31,6 @@ data class PrisonCaseNote(
} else {
StaffName(authorName.substringBeforeLast(" ").trim(), authorName.substringAfterLast(" ").trim())
}

fun isResettlementPassport() = type == "RESET" && subType == "BCST"
}

data class CaseNoteAmendment(
Expand All @@ -40,21 +39,27 @@ data class CaseNoteAmendment(
val additionalNoteText: String
)

fun PrisonCaseNote.toDeliusCaseNote(occurredAt: ZonedDateTime): DeliusCaseNote {
fun PrisonCaseNote.toDeliusCaseNote(): DeliusCaseNote {
fun amendments(): (CaseNoteAmendment) -> String = { a ->
"${System.lineSeparator()}[${a.authorName} updated the case notes on ${DeliusDateTimeFormatter.format(a.creationDateTime)}]${System.lineSeparator()}${a.additionalNoteText}"
}

return DeliusCaseNote(
header = CaseNoteHeader(offenderIdentifier, eventId),
header = CaseNoteHeader(offenderIdentifier, eventId, id.asUuidOrNull()),
body = CaseNoteBody(
type = type,
subType = subType,
content = text + amendments.joinToString(separator = "", transform = amendments()),
contactTimeStamp = occurredAt,
contactTimeStamp = occurrenceDateTime,
systemTimestamp = amendments.mapNotNull { it.creationDateTime }.maxOrNull() ?: creationDateTime,
staffName = getStaffName(),
establishmentCode = locationId
)
)
}

fun String.asUuidOrNull(): UUID? = try {
UUID.fromString(this)
} catch (e: Exception) {
null
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import java.time.LocalDateTime

interface PrisonCaseNotesClient {
@GetExchange
fun getCaseNote(baseUrl: URI): PrisonCaseNote?
fun getCaseNote(baseUrl: URI): PrisonCaseNote

@PostExchange
fun searchCaseNotes(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ class CaseNotePublished(
}

try {
deliusService.mergeCaseNote(prisonCaseNote.toDeliusCaseNote(event.occurredAt))
deliusService.mergeCaseNote(prisonCaseNote.toDeliusCaseNote())
telemetryService.trackEvent("CaseNoteMerged", prisonCaseNote.properties())
} catch (e: Exception) {
telemetryService.trackEvent(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,24 +14,30 @@ import uk.gov.justice.digital.hmpps.message.Notification
class Handler(
private val caseNotePublished: CaseNotePublished,
private val prisonIdentifierAdded: PrisonIdentifierAdded,
private val personCaseNote: PersonCaseNote,
override val converter: NotificationConverter<HmppsDomainEvent>,
) : NotificationHandler<HmppsDomainEvent> {

companion object {
const val CASE_NOTE_PUBLISHED = "prison.case-note.published"
const val PRISON_IDENTIFIER_ADDED = "probation-case.prison-identifier.added"
const val PERSON_CASE_NOTE_CREATED = "person.case-note.created"
const val PERSON_CASE_NOTE_UPDATED = "person.case-note.updated"
}

@Publish(
messages = [
Message(name = "prison/case-note-published"),
Message(title = "probation-case.prison-identifier.added", payload = Schema(HmppsDomainEvent::class)),
Message(title = PRISON_IDENTIFIER_ADDED, payload = Schema(HmppsDomainEvent::class)),
Message(title = PERSON_CASE_NOTE_CREATED, payload = Schema(HmppsDomainEvent::class)),
Message(title = PERSON_CASE_NOTE_UPDATED, payload = Schema(HmppsDomainEvent::class)),
]
)
override fun handle(notification: Notification<HmppsDomainEvent>) {
when (notification.eventType) {
CASE_NOTE_PUBLISHED -> caseNotePublished.handle(notification.message)
PRISON_IDENTIFIER_ADDED -> prisonIdentifierAdded.handle(notification.message)
PERSON_CASE_NOTE_CREATED, PERSON_CASE_NOTE_UPDATED -> personCaseNote.handle(notification.message)
}
}
}
Loading

0 comments on commit 5787ca9

Please sign in to comment.