Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
- PR Review Feedback
  • Loading branch information
joseph-bcl committed Oct 25, 2024
1 parent 3589669 commit 7cb2068
Show file tree
Hide file tree
Showing 9 changed files with 86 additions and 69 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import uk.gov.justice.digital.hmpps.integrations.delius.entity.Person
import uk.gov.justice.digital.hmpps.integrations.delius.person.entity.PersonAddress
import java.time.LocalDate

object AddressGenerator {
object PersonAddressGenerator {
val MAIN_ADDRESS = generate(person = PersonGenerator.DEFAULT)

fun generate(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"Type": "Notification",
"MessageId": "aa2c2828-167f-529b-8e19-73735a2fb85c",
"TopicArn": "arn:aws:sns:eu-west-2:000000000000:example",
"Message": "{\"hearing\":{\"id\":\"00000000-0000-0000-0000-000000000000\",\"courtCentre\":{\"id\":\"00000000-0000-0000-0000-000000000000\",\"code\":\"A00AA00\",\"roomId\":\"00000000-0000-0000-0000-000000000000\",\"roomName\":\"Courtroom 01\"},\"type\":{\"id\":\"00000000-0000-0000-0000-000000000000\",\"description\":\"First hearing\",\"welshDescription\":null},\"jurisdictionType\":\"MAGISTRATES\",\"hearingDays\":[{\"sittingDay\":\"2024-01-01T12:00:00\",\"listedDurationMinutes\":30,\"listingSequence\":1}],\"prosecutionCases\":[{\"id\":\"00000000-0000-0000-0000-000000000000\",\"initiationCode\":\"A\",\"prosecutionCaseIdentifier\":{\"prosecutionAuthorityCode\":\"AAAAA\",\"prosecutionAuthorityId\":\"00000000-0000-0000-0000-000000000000\",\"caseURN\":\"00AA000000\"},\"defendants\":[{\"id\":\"00000000-0000-0000-0000-000000000000\",\"offences\":[{\"id\":\"00000000-0000-0000-0000-000000000000\",\"offenceDefinitionId\":\"00000000-0000-0000-0000-000000000000\",\"offenceCode\":\"AA00000\",\"offenceTitle\":\"Example Offense Title\",\"wording\":\"Example of the offense committed\",\"offenceLegislation\":\"Example legislation\",\"listingNumber\":1,\"judicialResults\":[],\"plea\":null,\"verdict\":null}],\"prosecutionCaseId\":\"00000000-0000-0000-0000-000000000000\",\"personDefendant\":{\"personDetails\":{\"gender\":\"MALE\",\"lastName\":\"Example Last Name\",\"middleName\":null,\"firstName\":\"Example First Name\",\"dateOfBirth\":\"2000-01-01\",\"address\":{\"address1\":null,\"address2\":null,\"address3\":null,\"address4\":null,\"address5\":null,\"postcode\":null},\"contact\":{\"home\":null,\"mobile\":\"07000000000\",\"work\":null},\"ethnicity\":{\"observedEthnicityDescription\":\"White\",\"selfDefinedEthnicityDescription\":\"British\"}}},\"legalEntityDefendant\":null,\"masterDefendantId\":\"00000000-0000-0000-0000-000000000000\",\"pncId\":\"00000000000A\",\"croNumber\":\"000000/00A\"}],\"caseStatus\":\"ACTIVE\",\"caseMarkers\":[]}]}}",
"Message": "{\"hearing\":{\"id\":\"00000000-0000-0000-0000-000000000000\",\"courtCentre\":{\"id\":\"00000000-0000-0000-0000-000000000000\",\"code\":\"A00AA00\",\"roomId\":\"00000000-0000-0000-0000-000000000000\",\"roomName\":\"Courtroom 01\"},\"type\":{\"id\":\"00000000-0000-0000-0000-000000000000\",\"description\":\"First hearing\",\"welshDescription\":null},\"jurisdictionType\":\"MAGISTRATES\",\"hearingDays\":[{\"sittingDay\":\"2024-01-01T12:00:00\",\"listedDurationMinutes\":30,\"listingSequence\":1}],\"prosecutionCases\":[{\"id\":\"00000000-0000-0000-0000-000000000000\",\"initiationCode\":\"A\",\"prosecutionCaseIdentifier\":{\"prosecutionAuthorityCode\":\"AAAAA\",\"prosecutionAuthorityId\":\"00000000-0000-0000-0000-000000000000\",\"caseURN\":\"00AA000000\"},\"defendants\":[{\"id\":\"00000000-0000-0000-0000-000000000000\",\"offences\":[{\"id\":\"00000000-0000-0000-0000-000000000000\",\"offenceDefinitionId\":\"00000000-0000-0000-0000-000000000000\",\"offenceCode\":\"AA00000\",\"offenceTitle\":\"Example Offense Title\",\"wording\":\"Example of the offense committed\",\"offenceLegislation\":\"Example legislation\",\"listingNumber\":1,\"judicialResults\":[{\"isConvictedResult\":true,\"label\":\"Remanded in custody\",\"judicialResultTypeId\":\"00000000-0000-0000-0000-000000000000\",\"resultText\":\"RI - Remanded in custody\"}],\"plea\":null,\"verdict\":null}],\"prosecutionCaseId\":\"00000000-0000-0000-0000-000000000000\",\"personDefendant\":{\"personDetails\":{\"gender\":\"MALE\",\"lastName\":\"Example Last Name\",\"middleName\":null,\"firstName\":\"Example First Name\",\"dateOfBirth\":\"2000-01-01\",\"address\":{\"address1\":null,\"address2\":null,\"address3\":null,\"address4\":null,\"address5\":null,\"postcode\":null},\"contact\":{\"home\":null,\"mobile\":\"07000000000\",\"work\":null},\"ethnicity\":{\"observedEthnicityDescription\":\"White\",\"selfDefinedEthnicityDescription\":\"British\"}}},\"legalEntityDefendant\":null,\"masterDefendantId\":\"00000000-0000-0000-0000-000000000000\",\"pncId\":\"00000000000A\",\"croNumber\":\"000000/00A\"}],\"caseStatus\":\"ACTIVE\",\"caseMarkers\":[]}]}}",
"Timestamp": "2022-07-27T14:22:08.509Z",
"SignatureVersion": "1",
"Signature": "EXAMPLE",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -315,11 +315,10 @@ internal class IntegrationTest {
}

private fun thenNoRecordsAreInserted() {
verify(personService, never()).insertPerson(any(), any())
verify(personService, never()).insertAddress(any())
verify(addressRepository, never()).save(any())
verify(personRepository, never()).save(any())
verify(auditedInteractionService, Mockito.never())
.createAuditedInteraction(any(), any(), any(), any(), anyOrNull())
.createAuditedInteraction(any(), any(), eq(AuditedInteraction.Outcome.SUCCESS), any(), anyOrNull())
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,12 @@ import uk.gov.justice.digital.hmpps.message.Notification
import uk.gov.justice.digital.hmpps.service.PersonService
import uk.gov.justice.digital.hmpps.telemetry.TelemetryMessagingExtensions.notificationReceived
import uk.gov.justice.digital.hmpps.telemetry.TelemetryService
import java.time.LocalDate
import java.time.Period

@Component
@Channel("common-platform-and-delius-queue")
class Handler(
override val converter: NotificationConverter<CommonPlatformHearing>,
private val notifier: Notifier,
private val telemetryService: TelemetryService,
private val personService: PersonService,
private val probationSearchClient: ProbationSearchClient
Expand All @@ -42,49 +41,41 @@ class Handler(

val courtCode = notification.message.hearing.courtCentre.code

val dateOfBirth = notification.message.hearing.prosecutionCases
.firstOrNull()?.defendants?.firstOrNull()
?.personDefendant?.personDetails?.dateOfBirth
?: throw IllegalArgumentException("Date of birth not found in message")
defendants.forEach { defendant ->
val matchRequest = defendant.toProbationMatchRequest()
val matchedPersonResponse = probationSearchClient.match(matchRequest)

// Under 10 years old validation
dateOfBirth.let {
val age = Period.between(it, LocalDate.now()).years
require(age > 10) {
"Date of birth would indicate person is under ten years old: $it"
if (matchedPersonResponse.matches.isNotEmpty()) {
return
}
}

val matchRequest = notification.message.toProbationMatchRequest()
val matchedPersonResponse = probationSearchClient.match(matchRequest)

if (matchedPersonResponse.matches.isNotEmpty()) {
return
}
defendants.forEach { defendant ->
// Insert each defendant as a person record
val savedPerson = personService.insertPerson(defendant, courtCode)
val savedEntities = personService.insertPerson(defendant, courtCode)

notifier.caseCreated(savedEntities.person)
savedEntities.address?.let { notifier.addressCreated(it) }

telemetryService.trackEvent(
"PersonCreated", mapOf(
"CRN" to savedPerson.crn,
"personId" to savedPerson.id.toString(),
"hearingId" to notification.message.hearing.id
"hearingId" to notification.message.hearing.id,
"CRN" to savedEntities.person.crn,
"personId" to savedEntities.person.id.toString(),
"personManagerId" to savedEntities.personManager.id.toString(),
"equalityId" to savedEntities.equality.id.toString(),
"addressId" to savedEntities.address?.id.toString()
)
)
}
}

fun CommonPlatformHearing.toProbationMatchRequest(): ProbationMatchRequest {
val defendant = this.hearing.prosecutionCases.firstOrNull()?.defendants?.firstOrNull()
val personDetails =
defendant?.personDefendant?.personDetails ?: throw IllegalArgumentException("Person details are required")
fun Defendant.toProbationMatchRequest(): ProbationMatchRequest {
val personDetails = this.personDefendant?.personDetails ?: throw IllegalArgumentException("Person details are required")
return ProbationMatchRequest(
firstName = personDetails.firstName,
surname = personDetails.lastName,
dateOfBirth = personDetails.dateOfBirth,
pncNumber = defendant.pncId,
croNumber = defendant.croNumber
pncNumber = this.pncId,
croNumber = this.croNumber
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ class Notifier(
) {
@Subscribe(
messages = [
Message(title = "probation-case.engagement.created", payload = Schema(HmppsDomainEvent::class))
Message(title = "probation-case.engagement.created", payload = Schema(HmppsDomainEvent::class)),
Message(title = "probation-case.address.created", payload = Schema(HmppsDomainEvent::class))
]
)
fun caseCreated(person: Person) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package uk.gov.justice.digital.hmpps.service

import uk.gov.justice.digital.hmpps.integrations.delius.entity.Equality
import uk.gov.justice.digital.hmpps.integrations.delius.entity.Person
import uk.gov.justice.digital.hmpps.integrations.delius.entity.PersonManager
import uk.gov.justice.digital.hmpps.integrations.delius.person.entity.PersonAddress

data class InsertPersonResult(
val person: Person,
val personManager: PersonManager,
val equality: Equality,
var address: PersonAddress?
)
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,14 @@ import uk.gov.justice.digital.hmpps.integrations.delius.person.entity.PersonAddr
import uk.gov.justice.digital.hmpps.integrations.delius.person.entity.PersonAddressRepository
import uk.gov.justice.digital.hmpps.messaging.Address
import uk.gov.justice.digital.hmpps.messaging.Defendant
import uk.gov.justice.digital.hmpps.messaging.Notifier
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.Period

@Service
class PersonService(
jdbcTemplate: JdbcTemplate,
auditedInteractionService: AuditedInteractionService,
private val notifier: Notifier,
private val personRepository: PersonRepository,
private val courtRepository: CourtRepository,
private val equalityRepository: EqualityRepository,
Expand All @@ -36,8 +35,20 @@ class PersonService(
.withFunctionName("getNextCRN")

@Transactional
fun insertPerson(defendant: Defendant, courtCode: String): Person =
fun insertPerson(defendant: Defendant, courtCode: String): InsertPersonResult =
audit(BusinessInteractionCode.INSERT_PERSON) { audit ->

val dateOfBirth = defendant.personDefendant?.personDetails?.dateOfBirth
?: throw IllegalArgumentException("Date of birth not found in message")

// Under 10 years old validation
dateOfBirth.let {
val age = Period.between(it, LocalDate.now()).years
require(age > 10) {
"Date of birth would indicate person is under ten years old: $it"
}
}

// Person record
val savedPerson = personRepository.save(defendant.toPerson())

Expand All @@ -46,8 +57,6 @@ class PersonService(
val unallocatedTeam = teamRepository.findByCode(courtLinkedProvider.code + "UAT")
val unallocatedStaff = staffRepository.findByCode(unallocatedTeam.code + "U")

notifier.caseCreated(savedPerson)

// Person manager record
val manager = PersonManager(
person = savedPerson,
Expand All @@ -62,7 +71,7 @@ class PersonService(
allocationDate = LocalDateTime.of(1900, 1, 1, 0, 0)

)
personManagerRepository.save(manager)
val savedManager = personManagerRepository.save(manager)

// Equality record
val equality = Equality(
Expand All @@ -71,30 +80,29 @@ class PersonService(
softDeleted = false,
)

equalityRepository.save(equality)

val address = defendant.personDefendant?.personDetails?.address
if (address.containsInformation()) {
insertAddress(
PersonAddress(
id = null,
start = LocalDate.now(),
status = referenceDataRepository.mainAddressStatus(),
person = savedPerson,
notes = address?.buildNotes(),
postcode = address?.postcode,
type = referenceDataRepository.awaitingAssessmentAddressType()
val savedEquality = equalityRepository.save(equality)

val savedAddress =
defendant.personDefendant.personDetails.address.takeIf { it.containsInformation() }?.let {
insertAddress(
PersonAddress(
id = null,
start = LocalDate.now(),
status = referenceDataRepository.mainAddressStatus(),
person = savedPerson,
notes = it.buildNotes(),
postcode = it.postcode,
type = referenceDataRepository.awaitingAssessmentAddressType()
)
)
)
}
}
audit["offenderId"] = savedPerson.id
savedPerson
InsertPersonResult(savedPerson, savedManager, savedEquality, savedAddress)
}

@Transactional
fun insertAddress(address: PersonAddress): PersonAddress = audit(BusinessInteractionCode.INSERT_ADDRESS) { audit ->
val savedAddress = personAddressRepository.save(address)
notifier.addressCreated(savedAddress)
audit["addressId"] = address.id!!
savedAddress
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,14 @@ import org.mockito.kotlin.verify
import org.mockito.kotlin.whenever
import uk.gov.justice.digital.hmpps.converter.NotificationConverter
import uk.gov.justice.digital.hmpps.data.generator.MessageGenerator
import uk.gov.justice.digital.hmpps.data.generator.PersonAddressGenerator
import uk.gov.justice.digital.hmpps.data.generator.PersonGenerator
import uk.gov.justice.digital.hmpps.data.generator.PersonManagerGenerator
import uk.gov.justice.digital.hmpps.integrations.client.ProbationMatchResponse
import uk.gov.justice.digital.hmpps.integrations.client.ProbationSearchClient
import uk.gov.justice.digital.hmpps.integrations.delius.entity.Equality
import uk.gov.justice.digital.hmpps.message.Notification
import uk.gov.justice.digital.hmpps.service.InsertPersonResult
import uk.gov.justice.digital.hmpps.service.PersonService
import uk.gov.justice.digital.hmpps.telemetry.TelemetryMessagingExtensions.notificationReceived
import uk.gov.justice.digital.hmpps.telemetry.TelemetryService
Expand All @@ -33,6 +37,9 @@ internal class HandlerTest {
@Mock
lateinit var probationSearchClient: ProbationSearchClient

@Mock
lateinit var notifier: Notifier

@InjectMocks
lateinit var handler: Handler

Expand All @@ -44,22 +51,20 @@ internal class HandlerTest {
matchedBy = "NONE"
)
)
whenever(personService.insertPerson(any(), any())).thenReturn(PersonGenerator.DEFAULT)
whenever(personService.insertPerson(any(), any())).thenReturn(
InsertPersonResult(
person = PersonGenerator.DEFAULT,
personManager = PersonManagerGenerator.DEFAULT,
equality = Equality(id = 1L, personId = 1L, softDeleted = false),
address = PersonAddressGenerator.MAIN_ADDRESS,
)
)

val notification = Notification(message = MessageGenerator.COMMON_PLATFORM_EVENT)
handler.handle(notification)
verify(telemetryService).notificationReceived(notification)
}

@Test
fun `exception thrown when age is under 10 years old`() {
val notification = Notification(message = MessageGenerator.COMMON_PLATFORM_EVENT_DOB_ERROR)
val exception = assertThrows<IllegalArgumentException> {
handler.handle(notification)
}
assert(exception.message!!.contains("Date of birth would indicate person is under ten years old"))
}

@Test
fun `exception thrown when prosecution cases is empty`() {
val notification = Notification(message = MessageGenerator.COMMON_PLATFORM_EVENT_NO_CASES)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import org.mockito.junit.jupiter.MockitoExtension
import org.mockito.kotlin.*
import org.springframework.boot.test.system.CapturedOutput
import org.springframework.boot.test.system.OutputCaptureExtension
import uk.gov.justice.digital.hmpps.data.generator.AddressGenerator
import uk.gov.justice.digital.hmpps.data.generator.PersonAddressGenerator
import uk.gov.justice.digital.hmpps.data.generator.PersonGenerator
import uk.gov.justice.digital.hmpps.message.Notification
import uk.gov.justice.digital.hmpps.publisher.NotificationPublisher
Expand Down Expand Up @@ -37,7 +37,7 @@ class NotifierTest {
@Test
fun `test address created notification`(output: CapturedOutput) {
doNothing().whenever(topicPublisher).publish(any<Notification<*>>())
notifier.addressCreated(AddressGenerator.MAIN_ADDRESS)
notifier.addressCreated(PersonAddressGenerator.MAIN_ADDRESS)
verify(topicPublisher, times(1)).publish(any<Notification<*>>())
verifyNoMoreInteractions(topicPublisher)
}
Expand Down

0 comments on commit 7cb2068

Please sign in to comment.