Skip to content

Commit b3d3b5f

Browse files
authored
PI-2726 Mark previous reviews as complete + update notes (#4549)
1 parent f26b394 commit b3d3b5f

File tree

4 files changed

+80
-29
lines changed

4 files changed

+80
-29
lines changed

projects/assessment-summary-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/DataLoader.kt

+3-1
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,9 @@ class DataLoader(
121121
val contact = entityManager.merge(ContactGenerator.generateContact(this, type.registrationContactType!!))
122122
val registration =
123123
RegistrationGenerator.generate(this.id, LocalDate.parse("2023-06-14"), contact, type, level)
124-
val reviewContact = entityManager.merge(ContactGenerator.generateContact(this, type.reviewContactType!!))
124+
val reviewContact = entityManager.merge(
125+
ContactGenerator.generateContact(this, type.reviewContactType!!).withNotes("existing notes")
126+
)
125127
saveAll(this, registration.withReview(reviewContact))
126128
}
127129
return this

projects/assessment-summary-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/IntegrationTest.kt

+46-11
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import uk.gov.justice.digital.hmpps.data.generator.PersonGenerator
2323
import uk.gov.justice.digital.hmpps.data.generator.ReferenceDataGenerator
2424
import uk.gov.justice.digital.hmpps.data.generator.RegistrationGenerator
2525
import uk.gov.justice.digital.hmpps.datetime.DeliusDateFormatter
26+
import uk.gov.justice.digital.hmpps.datetime.toDeliusDate
2627
import uk.gov.justice.digital.hmpps.enum.RiskLevel
2728
import uk.gov.justice.digital.hmpps.enum.RiskOfSeriousHarmType
2829
import uk.gov.justice.digital.hmpps.enum.RiskType
@@ -343,7 +344,6 @@ internal class IntegrationTest {
343344
assertThat(
344345
review.contact.notes?.trim(), equalTo(
345346
"""
346-
The OASys assessment of Review on 07/12/2023 identified the Risk to children to be H.
347347
Type: Safeguarding - Risk to children
348348
Next Review Date: ${DeliusDateFormatter.format(LocalDate.now().plusMonths(6))}
349349
""".trimIndent()
@@ -361,6 +361,7 @@ internal class IntegrationTest {
361361
registrationRepository.findByPersonIdAndTypeCode(person.id, RiskType.CHILDREN.code).single()
362362
assertThat(riskToChildrenBefore.level?.code, equalTo(RiskLevel.H.code))
363363
assertThat(riskToChildrenBefore.reviews, hasSize(1))
364+
assertThat(riskToChildrenBefore.reviews[0].completed, equalTo(false))
364365
val riskToPrisonerBefore = registrationRepository.findByPersonIdAndTypeCode(person.id, RiskType.PRISONER.code)
365366
assertThat(riskToPrisonerBefore, hasSize(0))
366367
val altRiskToPrisonerBefore =
@@ -382,18 +383,41 @@ internal class IntegrationTest {
382383

383384
val domainEvents = domainEventRepository.findAllForCrn(PersonGenerator.EXISTING_RISKS.crn)
384385

385-
// Unchanged value from OASys - adds a review
386+
// Unchanged value from OASys - completes existing review and adds a new review
386387
val riskToChildren =
387388
registrationRepository.findByPersonIdAndTypeCode(person.id, RiskType.CHILDREN.code).single()
388389
assertThat(riskToChildren.level?.code, equalTo(RiskLevel.H.code))
389390
assertThat(riskToChildren.reviews, hasSize(2))
390-
val expectedReviewNotes = """
391+
assertThat(riskToChildren.nextReviewDate, equalTo(LocalDate.now().plusMonths(6)))
392+
val completedReview = riskToChildren.reviews.single { it.completed }
393+
assertThat(completedReview.date, equalTo(LocalDate.now()))
394+
assertThat(completedReview.reviewDue, equalTo(LocalDate.now().plusMonths(6)))
395+
"""
396+
existing notes
397+
The OASys assessment of Review on 07/12/2023 identified the Risk to children to be H.
398+
399+
*R10.1 Who is at risk*
400+
Known adults - Joe Bloggs
401+
402+
*R10.2 What is the nature of the risk*
403+
Physical harm - Physical assault, shown willingness to use a weapon
404+
""".trimIndent().let { assertThat(completedReview.notes?.trim(), equalTo(it)) }
405+
"""
406+
existing notes
391407
The OASys assessment of Review on 07/12/2023 identified the Risk to children to be H.
408+
409+
See review for more details
410+
""".trimIndent().let { assertThat(completedReview.contact.notes?.trim(), equalTo(it)) }
411+
val newReview = riskToChildren.reviews.single { !it.completed }
412+
assertThat(newReview.date, equalTo(LocalDate.now().plusMonths(6)))
413+
assertThat(newReview.reviewDue, nullValue())
414+
"""
392415
Type: Safeguarding - Risk to children
393-
Next Review Date: 14/12/2023
394-
""".trimIndent()
395-
assertThat(riskToChildren.reviews[1].notes?.trim(), equalTo(expectedReviewNotes))
396-
assertThat(riskToChildren.reviews[1].contact.notes?.trim(), equalTo(expectedReviewNotes))
416+
Next Review Date: ${LocalDate.now().plusMonths(6).toDeliusDate()}
417+
""".trimIndent().let {
418+
assertThat(newReview.notes?.trim(), equalTo(it))
419+
assertThat(newReview.contact.notes?.trim(), equalTo(it))
420+
}
397421
assertThat(domainEvents.ofType(RiskType.CHILDREN), hasSize(0))
398422

399423
// No existing registration - add new
@@ -423,10 +447,21 @@ internal class IntegrationTest {
423447
val riskToPublic = registrationRepository.findByPersonIdAndTypeCode(person.id, RiskType.PUBLIC.code).single()
424448
assertThat(riskToPublic.level?.code, equalTo(RiskLevel.V.code))
425449
assertThat(riskToPublic.reviews, hasSize(1))
426-
assertThat(
427-
riskToPublic.notes,
428-
startsWith("The OASys assessment of Review on 07/12/2023 identified the Risk to public to have increased to V.")
429-
)
450+
"""
451+
The OASys assessment of Review on 07/12/2023 identified the Risk to public to have increased to V.
452+
453+
*R10.1 Who is at risk*
454+
Known adults - Joe Bloggs
455+
456+
*R10.2 What is the nature of the risk*
457+
Physical harm - Physical assault, shown willingness to use a weapon
458+
""".trimIndent().let { assertThat(riskToPublic.notes, equalTo(it)) }
459+
"""
460+
461+
The OASys assessment of Review on 07/12/2023 identified the Risk to public to have increased to V.
462+
463+
See Register for more details
464+
""".trimIndent().let { assertThat(riskToPublic.contact.notes, equalTo(it)) }
430465
assertThat(domainEvents.ofType(RiskType.PUBLIC), hasSize(2))
431466
assertThat(
432467
domainEvents.ofType(RiskType.PUBLIC).map { it.eventType },

projects/assessment-summary-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/person/entity/Registration.kt

+6-6
Original file line numberDiff line numberDiff line change
@@ -77,16 +77,16 @@ class Registration(
7777
var reviews: MutableList<RegistrationReview> = mutableListOf()
7878
private set
7979

80-
fun withReview(contact: Contact): Registration {
81-
reviews += RegistrationReview(personId, this, contact, nextReviewDate, null, teamId, staffId, contact.notes)
80+
fun withReview(contact: Contact, notes: String? = contact.notes): Registration {
81+
reviews += RegistrationReview(personId, this, contact, nextReviewDate, null, teamId, staffId, notes)
8282
return this
8383
}
8484

8585
fun deregister(contact: Contact) {
8686
deregistration = DeRegistration(LocalDate.now(), this, personId, contact, contact.teamId, contact.staffId)
8787
deregistered = true
8888
nextReviewDate = null
89-
reviews.removeIf { !it.completed && it.notes == null }
89+
reviews.removeIf { !it.completed && it.lastUpdatedDatetime == it.createdDatetime }
9090
reviews.firstOrNull()?.reviewDue = null
9191
}
9292
}
@@ -159,7 +159,7 @@ class RegistrationReview(
159159
val contact: Contact,
160160

161161
@Column(name = "review_date")
162-
val date: LocalDate?,
162+
var date: LocalDate?,
163163

164164
@Column(name = "review_date_due")
165165
var reviewDue: LocalDate?,
@@ -171,10 +171,10 @@ class RegistrationReview(
171171
val staffId: Long,
172172

173173
@Lob
174-
val notes: String? = null,
174+
var notes: String? = null,
175175

176176
@Convert(converter = YesNoConverter::class)
177-
val completed: Boolean = false,
177+
var completed: Boolean = false,
178178

179179
@Column(columnDefinition = "number")
180180
@Convert(converter = NumericBooleanConverter::class)

projects/assessment-summary-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/RiskService.kt

+25-11
Original file line numberDiff line numberDiff line change
@@ -76,21 +76,24 @@ class RiskService(
7676
val (matchingRegistrations, registrationsToRemove) = registrations.partition { it.level!!.code == riskLevel.code }
7777
val events = registrationsToRemove.map { person.removeRegistration(it) }.toMutableList()
7878

79-
// Add registration with the identified level if it doesn't already exist
79+
// Get RoSH answers from OASys
8080
val type = registerTypeRepository.getByCode(riskType.code)
8181
val existingLevel = RiskLevel.maxByCode(registrationsToRemove.mapNotNull { it.level?.code })
8282
val assessmentNote = "The OASys assessment of ${summary.furtherInformation.pOAssessmentDesc} on " +
8383
"${summary.dateCompleted.toDeliusDate()} identified the ${type.description} " +
8484
"${existingLevel.increasedOrDecreasedTo(riskLevel)} ${level.description}."
85-
86-
if (matchingRegistrations.isEmpty()) {
87-
val roshSummary = ordsClient.getRoshSummary(summary.assessmentPk)?.assessments?.singleOrNull()
88-
val notes = """
85+
val roshSummary = ordsClient.getRoshSummary(summary.assessmentPk)?.assessments?.singleOrNull()
86+
val roshNotes = """
8987
|$assessmentNote
9088
|${roshSummary?.whoAtRisk?.let { "\n|*R10.1 Who is at risk*\n|$it" }}
9189
|${roshSummary?.natureOfRisk?.let { "\n|*R10.2 What is the nature of the risk*\n|$it" }}
9290
""".trimMargin()
93-
events += registrations.addRegistration(person, type, level, notes).regEvent(person.crn)
91+
92+
// Add registration with the identified level if it doesn't already exist
93+
if (matchingRegistrations.isEmpty()) {
94+
val contactNotes = "$assessmentNote\n\nSee Register for more details"
95+
events += registrations.addRegistration(person, type, level, roshNotes, contactNotes)
96+
.regEvent(person.crn)
9497

9598
// Registrations in the type's duplicate group should also be removed
9699
registerTypeRepository.findOtherTypesInGroup(riskType.code)
@@ -102,9 +105,17 @@ class RiskService(
102105
}
103106
}
104107

105-
// Always add a review, regardless of whether the register level has changed
108+
// Complete any open reviews and add a new one, regardless of whether the level has changed
106109
registrationRepository.findByPersonIdAndTypeCode(person.id, riskType.code).singleOrNull()?.let {
107-
it.withReview(it.reviewContact(person, "$assessmentNote\n${it.notes()}"))
110+
it.nextReviewDate = it.type.reviewPeriod?.let { LocalDate.now().plusMonths(it) }
111+
it.reviews.filter { !it.completed }.forEach { review ->
112+
review.completed = true
113+
review.date = LocalDate.now()
114+
review.reviewDue = it.nextReviewDate
115+
review.notes = review.notes?.let { "$it\n$roshNotes" } ?: roshNotes
116+
review.contact.withNotes("$assessmentNote\n\nSee review for more details")
117+
}
118+
it.withReview(it.reviewContact(person))
108119
}
109120

110121
return@flatMap events
@@ -116,13 +127,14 @@ class RiskService(
116127
type: RegisterType,
117128
level: ReferenceData? = null,
118129
notes: String? = null,
130+
contactNotes: String? = null,
119131
): Registration {
120132
val nextReviewDate = type.reviewPeriod?.let { LocalDate.now().plusMonths(it) }
121133

122134
val contact = contactService.createContact(
123135
ContactDetail(
124136
ContactType.Code.REGISTRATION,
125-
notes = reviewNotes(type, nextReviewDate),
137+
notes = contactNotes ?: reviewNotes(type, nextReviewDate),
126138
contactType = type.registrationContactType
127139
),
128140
person
@@ -146,7 +158,7 @@ class RiskService(
146158

147159
private fun Person.removeRegistration(
148160
registration: Registration,
149-
notes: String = registration.notes()
161+
notes: String = registration.type.notes()
150162
): HmppsDomainEvent {
151163
val contact = contactService.createContact(ContactDetail(DEREGISTRATION, notes = notes), this)
152164
registration.deregister(contact)
@@ -163,8 +175,10 @@ class RiskService(
163175
)
164176
}
165177

178+
fun RegisterType.notes() = "Type: ${flag.description} - $description"
179+
166180
fun reviewNotes(type: RegisterType, nextReviewDate: LocalDate?) = listOfNotNull(
167-
"Type: ${type.flag.description} - ${type.description}",
181+
type.notes(),
168182
nextReviewDate?.let { "Next Review Date: ${it.toDeliusDate()}" }
169183
).joinToString(System.lineSeparator())
170184

0 commit comments

Comments
 (0)