diff --git a/projects/common-platform-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/AddressGenerator.kt b/projects/common-platform-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/PersonAddressGenerator.kt similarity index 95% rename from projects/common-platform-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/AddressGenerator.kt rename to projects/common-platform-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/PersonAddressGenerator.kt index 80f76a7518..fa2b186162 100644 --- a/projects/common-platform-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/AddressGenerator.kt +++ b/projects/common-platform-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/PersonAddressGenerator.kt @@ -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( diff --git a/projects/common-platform-and-delius/src/dev/resources/messages/common-platform-hearing-blank-address.json b/projects/common-platform-and-delius/src/dev/resources/messages/common-platform-hearing-blank-address.json index 6e9219f3a1..9019f25707 100644 --- a/projects/common-platform-and-delius/src/dev/resources/messages/common-platform-hearing-blank-address.json +++ b/projects/common-platform-and-delius/src/dev/resources/messages/common-platform-hearing-blank-address.json @@ -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", diff --git a/projects/common-platform-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/IntegrationTest.kt b/projects/common-platform-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/IntegrationTest.kt index f912588f47..266a378bb2 100644 --- a/projects/common-platform-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/IntegrationTest.kt +++ b/projects/common-platform-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/IntegrationTest.kt @@ -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()) } } \ No newline at end of file diff --git a/projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/messaging/Handler.kt b/projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/messaging/Handler.kt index 92a05920fe..c4fe0bf6d7 100644 --- a/projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/messaging/Handler.kt +++ b/projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/messaging/Handler.kt @@ -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, + private val notifier: Notifier, private val telemetryService: TelemetryService, private val personService: PersonService, private val probationSearchClient: ProbationSearchClient @@ -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 ) } } diff --git a/projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/messaging/Notifier.kt b/projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/messaging/Notifier.kt index 36a6a52e30..5f4a393905 100644 --- a/projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/messaging/Notifier.kt +++ b/projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/messaging/Notifier.kt @@ -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) { diff --git a/projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/InsertPersonResult.kt b/projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/InsertPersonResult.kt new file mode 100644 index 0000000000..ab2dfb41d5 --- /dev/null +++ b/projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/InsertPersonResult.kt @@ -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? +) \ No newline at end of file diff --git a/projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/PersonService.kt b/projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/PersonService.kt index 2c01a34f16..f6e7406df8 100644 --- a/projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/PersonService.kt +++ b/projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/PersonService.kt @@ -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, @@ -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()) @@ -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, @@ -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( @@ -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 } diff --git a/projects/common-platform-and-delius/src/test/kotlin/uk/gov/justice/digital/hmpps/messaging/HandlerTest.kt b/projects/common-platform-and-delius/src/test/kotlin/uk/gov/justice/digital/hmpps/messaging/HandlerTest.kt index 490aa3c97a..97f3b6ab68 100644 --- a/projects/common-platform-and-delius/src/test/kotlin/uk/gov/justice/digital/hmpps/messaging/HandlerTest.kt +++ b/projects/common-platform-and-delius/src/test/kotlin/uk/gov/justice/digital/hmpps/messaging/HandlerTest.kt @@ -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 @@ -33,6 +37,9 @@ internal class HandlerTest { @Mock lateinit var probationSearchClient: ProbationSearchClient + @Mock + lateinit var notifier: Notifier + @InjectMocks lateinit var handler: Handler @@ -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 { - 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) diff --git a/projects/common-platform-and-delius/src/test/kotlin/uk/gov/justice/digital/hmpps/messaging/NotifierTest.kt b/projects/common-platform-and-delius/src/test/kotlin/uk/gov/justice/digital/hmpps/messaging/NotifierTest.kt index 0d0b50f81a..4972813672 100644 --- a/projects/common-platform-and-delius/src/test/kotlin/uk/gov/justice/digital/hmpps/messaging/NotifierTest.kt +++ b/projects/common-platform-and-delius/src/test/kotlin/uk/gov/justice/digital/hmpps/messaging/NotifierTest.kt @@ -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 @@ -37,7 +37,7 @@ class NotifierTest { @Test fun `test address created notification`(output: CapturedOutput) { doNothing().whenever(topicPublisher).publish(any>()) - notifier.addressCreated(AddressGenerator.MAIN_ADDRESS) + notifier.addressCreated(PersonAddressGenerator.MAIN_ADDRESS) verify(topicPublisher, times(1)).publish(any>()) verifyNoMoreInteractions(topicPublisher) }