Skip to content

Commit f33e825

Browse files
1 parent 693259f commit f33e825

File tree

20 files changed

+165
-68
lines changed

20 files changed

+165
-68
lines changed

projects/prison-case-notes-to-probation/src/dev/resources/messages/case-note-exists-in-delius.json

+8-4
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,20 @@
22
"MessageId": "ae06c49e-1f41-4b9f-b2f2-dcca610d02cd",
33
"Type": "Notification",
44
"Timestamp": "2019-10-21T14:01:18.500Z",
5-
"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\"}]}}",
5+
"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\"}]}}",
66
"TopicArn": "arn:aws:sns:eu-west-1:000000000000:offender_events",
77
"MessageAttributes": {
88
"eventType": {
99
"Type": "String",
10-
"Value": "prison.case-note.published"
10+
"Value": "person.case-note.updated"
1111
},
12-
"caseNoteType": {
12+
"type": {
1313
"Type": "String",
14-
"Value": "NEG-IEP_WARN"
14+
"Value": "NEG"
15+
},
16+
"subType": {
17+
"Type": "String",
18+
"Value": "IEP_WARN"
1519
}
1620
}
1721
}

projects/prison-case-notes-to-probation/src/dev/resources/messages/case-note-new-to-delius.json

+8-4
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,20 @@
22
"MessageId": "ae06c49e-1f41-4b9f-b2f2-dcca610d02cd",
33
"Type": "Notification",
44
"Timestamp": "2019-10-21T14:01:18.500Z",
5-
"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\"}]}}",
5+
"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\"}]}}",
66
"TopicArn": "arn:aws:sns:eu-west-1:000000000000:offender_events",
77
"MessageAttributes": {
88
"eventType": {
99
"Type": "String",
10-
"Value": "prison.case-note.published"
10+
"Value": "person.case-note.created"
1111
},
12-
"caseNoteType": {
12+
"type": {
1313
"Type": "String",
14-
"Value": "NEG-IEP_WARN"
14+
"Value": "NEG"
15+
},
16+
"subType": {
17+
"Type": "String",
18+
"Value": "IEP_WARN"
1519
}
1620
}
1721
}

projects/prison-case-notes-to-probation/src/dev/resources/messages/case-note-not-found.json

+8-4
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,20 @@
22
"MessageId": "ae06c49e-1f41-4b9f-b2f2-dcca610d02cd",
33
"Type": "Notification",
44
"Timestamp": "2019-10-21T14:01:18.500Z",
5-
"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\"}]}}",
5+
"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\"}]}}",
66
"TopicArn": "arn:aws:sns:eu-west-1:000000000000:offender_events",
77
"MessageAttributes": {
88
"eventType": {
99
"Type": "String",
10-
"Value": "prison.case-note.published"
10+
"Value": "person.case-note.created"
1111
},
12-
"caseNoteType": {
12+
"type": {
1313
"Type": "String",
14-
"Value": "NEG-IEP_WARN"
14+
"Value": "NEG"
15+
},
16+
"subType": {
17+
"Type": "String",
18+
"Value": "IEP_WARN"
1519
}
1620
}
1721
}

projects/prison-case-notes-to-probation/src/dev/resources/messages/resettlement-passport-casenote.json

+8-4
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,20 @@
22
"MessageId": "ae06c49e-1f41-4b9f-b2f2-dcca610d02cd",
33
"Type": "Notification",
44
"Timestamp": "2019-10-21T14:01:18.500Z",
5-
"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\"}]}}",
5+
"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\"}]}}",
66
"TopicArn": "arn:aws:sns:eu-west-1:000000000000:offender_events",
77
"MessageAttributes": {
88
"eventType": {
99
"Type": "String",
10-
"Value": "prison.case-note.published"
10+
"Value": "person.case-note.created"
1111
},
12-
"caseNoteType": {
12+
"type": {
1313
"Type": "String",
14-
"Value": "RESET-BCST"
14+
"Value": "RESET"
15+
},
16+
"subType": {
17+
"Type": "String",
18+
"Value": "BCST"
1519
}
1620
}
1721
}

projects/prison-case-notes-to-probation/src/dev/resources/simulations/__files/get-case-note-body-exists-in-delius.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"caseNoteId": 1111,
2+
"caseNoteId": "0ec15f8b-6b57-471f-b02a-c89169a6a3e5",
33
"eventId": 11111,
44
"offenderIdentifier": "AA0001A",
55
"type": "NEG",

projects/prison-case-notes-to-probation/src/dev/resources/simulations/__files/get-case-note-body-new-to-delius.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"caseNoteId": 2222,
2+
"caseNoteId": "2cf4f9e1-df22-49a1-a2a7-5968a96529e3",
33
"eventId": 22222,
44
"offenderIdentifier": "AA0001A",
55
"type": "NEG",

projects/prison-case-notes-to-probation/src/dev/resources/simulations/__files/get-case-note-body-resettlement-passport-new.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"caseNoteId": 5767,
2+
"caseNoteId": "9f0a2112-acde-4501-b1f9-3f2f5f04e426",
33
"eventId": 576777,
44
"offenderIdentifier": "AA0001A",
55
"type": "RESET",

projects/prison-case-notes-to-probation/src/dev/resources/simulations/mappings/get-case-note.json

+4-4
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
{
44
"request": {
55
"method": "GET",
6-
"url": "/case-notes/AA0001A/1111"
6+
"url": "/case-notes/AA0001A/0ec15f8b-6b57-471f-b02a-c89169a6a3e5"
77
},
88
"response": {
99
"headers": {
@@ -16,7 +16,7 @@
1616
{
1717
"request": {
1818
"method": "GET",
19-
"url": "/case-notes/AA0001A/2222"
19+
"url": "/case-notes/AA0001A/2cf4f9e1-df22-49a1-a2a7-5968a96529e3"
2020
},
2121
"response": {
2222
"headers": {
@@ -30,7 +30,7 @@
3030
{
3131
"request": {
3232
"method": "GET",
33-
"url": "/case-notes/AA0001A/5767"
33+
"url": "/case-notes/AA0001A/9f0a2112-acde-4501-b1f9-3f2f5f04e426"
3434
},
3535
"response": {
3636
"headers": {
@@ -44,7 +44,7 @@
4444
{
4545
"request": {
4646
"method": "GET",
47-
"url": "/case-notes/AA0001A/4444"
47+
"url": "/case-notes/AA0001A/da82e1df-1a74-486e-842c-6ce961575211"
4848
},
4949
"response": {
5050
"status": 404,

projects/prison-case-notes-to-probation/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/entity/CaseNote.kt

+3-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ data class CaseNote(
2525
val nsiId: Long?,
2626

2727
@Column(name = "nomis_case_note_id", updatable = false)
28-
val nomisId: Long,
28+
val nomisId: Long?,
2929

3030
@ManyToOne
3131
@JoinColumn(name = "contact_type_id", updatable = false)
@@ -55,6 +55,8 @@ data class CaseNote(
5555
@Column(updatable = false)
5656
val probationAreaId: Long,
5757

58+
var externalReference: String? = null,
59+
5860
@Column(name = "sensitive")
5961
@Convert(converter = YesNoConverter::class)
6062
val isSensitive: Boolean = type.isSensitive,

projects/prison-case-notes-to-probation/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/model/DeliusCaseNote.kt

+6-3
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,13 @@ import jakarta.validation.constraints.NotNull
66
import uk.gov.justice.digital.hmpps.integrations.delius.entity.CaseNoteType
77
import uk.gov.justice.digital.hmpps.model.StaffName
88
import java.time.ZonedDateTime
9+
import java.util.*
910

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

12-
data class CaseNoteHeader(val nomisId: String, val noteId: Long)
15+
data class CaseNoteHeader(val nomisId: String, val legacyId: Long, val uuid: UUID?)
1316
data class CaseNoteBody(
1417
@NotBlank
1518
val type: String,
@@ -45,7 +48,7 @@ data class CaseNoteBody(
4548
}
4649
}
4750

48-
fun isResettlementPassport() = type == "RESET" && subType == "BCST"
51+
private fun isResettlementPassport() = type == "RESET" && subType == "BCST"
4952
}
5053

5154
fun String.isAlertType() = this == "ALERT ACTIVE" || this == "ALERT INACTIVE"

projects/prison-case-notes-to-probation/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/repository/CaseNoteRepository.kt

+1
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ import uk.gov.justice.digital.hmpps.integrations.delius.entity.CaseNote
55

66
interface CaseNoteRepository : JpaRepository<CaseNote, Long> {
77
fun findByNomisId(nomisId: Long): CaseNote?
8+
fun findByExternalReference(externalReference: String): CaseNote?
89
}

projects/prison-case-notes-to-probation/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/service/DeliusService.kt

+11-7
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,17 @@ class DeliusService(
2828
private val relatedService: CaseNoteRelatedService
2929
) : AuditableService(auditedInteractionService) {
3030
@Transactional
31-
fun mergeCaseNote(@Valid caseNote: DeliusCaseNote) = audit(CASE_NOTES_MERGE) {
32-
it["nomisId"] = caseNote.header.noteId
31+
fun mergeCaseNote(@Valid caseNote: DeliusCaseNote) = audit(CASE_NOTES_MERGE) { audit ->
32+
audit["nomisId"] = caseNote.header.legacyId
33+
caseNote.header.uuid?.also { audit["dpsId"] = it }
3334

34-
val existing = caseNoteRepository.findByNomisId(caseNote.header.noteId)
35+
val existing = caseNote.urn?.let { caseNoteRepository.findByExternalReference(it) }
36+
?: caseNoteRepository.findByNomisId(caseNote.header.legacyId)
3537

3638
val entity = if (existing == null) caseNote.newEntity() else existing.updateFrom(caseNote)
3739
if (entity != null) {
3840
caseNoteRepository.save(entity)
39-
it["contactId"] = entity.id
41+
audit["contactId"] = entity.id
4042
}
4143
}
4244

@@ -48,7 +50,8 @@ class DeliusService(
4850
notes = caseNote.body.notes(notes.length),
4951
date = caseNote.body.contactTimeStamp,
5052
startTime = caseNote.body.contactTimeStamp,
51-
lastModifiedDateTime = caseNote.body.systemTimestamp
53+
lastModifiedDateTime = caseNote.body.systemTimestamp,
54+
externalReference = caseNote.urn
5255
)
5356
} else {
5457
log.warn("Case Note update ignored because it was out of sequence ${caseNote.header}")
@@ -74,7 +77,7 @@ class DeliusService(
7477
eventId = relatedIds.eventId,
7578
nsiId = relatedIds.nsiId,
7679
type = caseNoteType,
77-
nomisId = header.noteId,
80+
nomisId = header.legacyId,
7881
description = description,
7982
notes = body.notes(),
8083
date = body.contactTimeStamp,
@@ -83,7 +86,8 @@ class DeliusService(
8386
probationAreaId = assignment.first,
8487
teamId = assignment.second,
8588
staffId = assignment.third,
86-
staffEmployeeId = assignment.third
89+
staffEmployeeId = assignment.third,
90+
externalReference = urn
8791
)
8892
}
8993

projects/prison-case-notes-to-probation/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/prison/PrisonCaseNote.kt

+10-5
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import uk.gov.justice.digital.hmpps.integrations.delius.model.CaseNoteHeader
77
import uk.gov.justice.digital.hmpps.integrations.delius.model.DeliusCaseNote
88
import uk.gov.justice.digital.hmpps.model.StaffName
99
import java.time.ZonedDateTime
10+
import java.util.*
1011

1112
const val UNKNOWN_LOCATION = "UNK"
1213

@@ -30,8 +31,6 @@ data class PrisonCaseNote(
3031
} else {
3132
StaffName(authorName.substringBeforeLast(" ").trim(), authorName.substringAfterLast(" ").trim())
3233
}
33-
34-
fun isResettlementPassport() = type == "RESET" && subType == "BCST"
3534
}
3635

3736
data class CaseNoteAmendment(
@@ -40,21 +39,27 @@ data class CaseNoteAmendment(
4039
val additionalNoteText: String
4140
)
4241

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

4847
return DeliusCaseNote(
49-
header = CaseNoteHeader(offenderIdentifier, eventId),
48+
header = CaseNoteHeader(offenderIdentifier, eventId, id.asUuidOrNull()),
5049
body = CaseNoteBody(
5150
type = type,
5251
subType = subType,
5352
content = text + amendments.joinToString(separator = "", transform = amendments()),
54-
contactTimeStamp = occurredAt,
53+
contactTimeStamp = occurrenceDateTime,
5554
systemTimestamp = amendments.mapNotNull { it.creationDateTime }.maxOrNull() ?: creationDateTime,
5655
staffName = getStaffName(),
5756
establishmentCode = locationId
5857
)
5958
)
6059
}
60+
61+
fun String.asUuidOrNull(): UUID? = try {
62+
UUID.fromString(this)
63+
} catch (e: Exception) {
64+
null
65+
}

projects/prison-case-notes-to-probation/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/prison/PrisonCaseNotesClient.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import java.time.LocalDateTime
88

99
interface PrisonCaseNotesClient {
1010
@GetExchange
11-
fun getCaseNote(baseUrl: URI): PrisonCaseNote?
11+
fun getCaseNote(baseUrl: URI): PrisonCaseNote
1212

1313
@PostExchange
1414
fun searchCaseNotes(

projects/prison-case-notes-to-probation/src/main/kotlin/uk/gov/justice/digital/hmpps/messaging/CaseNotePublished.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ class CaseNotePublished(
6464
}
6565

6666
try {
67-
deliusService.mergeCaseNote(prisonCaseNote.toDeliusCaseNote(event.occurredAt))
67+
deliusService.mergeCaseNote(prisonCaseNote.toDeliusCaseNote())
6868
telemetryService.trackEvent("CaseNoteMerged", prisonCaseNote.properties())
6969
} catch (e: Exception) {
7070
telemetryService.trackEvent(

projects/prison-case-notes-to-probation/src/main/kotlin/uk/gov/justice/digital/hmpps/messaging/Handler.kt

+7-1
Original file line numberDiff line numberDiff line change
@@ -14,24 +14,30 @@ import uk.gov.justice.digital.hmpps.message.Notification
1414
class Handler(
1515
private val caseNotePublished: CaseNotePublished,
1616
private val prisonIdentifierAdded: PrisonIdentifierAdded,
17+
private val personCaseNote: PersonCaseNote,
1718
override val converter: NotificationConverter<HmppsDomainEvent>,
1819
) : NotificationHandler<HmppsDomainEvent> {
1920

2021
companion object {
2122
const val CASE_NOTE_PUBLISHED = "prison.case-note.published"
2223
const val PRISON_IDENTIFIER_ADDED = "probation-case.prison-identifier.added"
24+
const val PERSON_CASE_NOTE_CREATED = "person.case-note.created"
25+
const val PERSON_CASE_NOTE_UPDATED = "person.case-note.updated"
2326
}
2427

2528
@Publish(
2629
messages = [
2730
Message(name = "prison/case-note-published"),
28-
Message(title = "probation-case.prison-identifier.added", payload = Schema(HmppsDomainEvent::class)),
31+
Message(title = PRISON_IDENTIFIER_ADDED, payload = Schema(HmppsDomainEvent::class)),
32+
Message(title = PERSON_CASE_NOTE_CREATED, payload = Schema(HmppsDomainEvent::class)),
33+
Message(title = PERSON_CASE_NOTE_UPDATED, payload = Schema(HmppsDomainEvent::class)),
2934
]
3035
)
3136
override fun handle(notification: Notification<HmppsDomainEvent>) {
3237
when (notification.eventType) {
3338
CASE_NOTE_PUBLISHED -> caseNotePublished.handle(notification.message)
3439
PRISON_IDENTIFIER_ADDED -> prisonIdentifierAdded.handle(notification.message)
40+
PERSON_CASE_NOTE_CREATED, PERSON_CASE_NOTE_UPDATED -> personCaseNote.handle(notification.message)
3541
}
3642
}
3743
}

0 commit comments

Comments
 (0)