From e1483b74ba7e71caca71bccf5260f11dcc6afb5c Mon Sep 17 00:00:00 2001 From: "Joseph.Dundon" Date: Fri, 18 Oct 2024 17:15:29 +0100 Subject: [PATCH] PI-2575 - Insert address logic implemented --- .../deploy/database/access.yml | 1 + .../justice/digital/hmpps/data/DataLoader.kt | 5 + .../hmpps/data/generator/AddressGenerator.kt | 24 ++++ .../generator/BusinessInteractionGenerator.kt | 5 + .../hmpps/data/generator/MessageGenerator.kt | 2 + .../data/generator/ReferenceDataGenerator.kt | 12 +- .../src/dev/resources/db/oracle.sql | 13 ++ ...common-platform-hearing-blank-address.json | 29 +++++ .../messages/common-platform-hearing.json | 2 +- .../justice/digital/hmpps/IntegrationTest.kt | 112 +++++++++++++++++- .../delius/audit/BusinessInteractionCode.kt | 3 +- .../integrations/delius/entity/Equality.kt | 3 + .../integrations/delius/entity/Person.kt | 20 +++- .../delius/entity/PersonAddress.kt | 111 +++++++++++++++++ .../delius/entity/PersonManager.kt | 13 +- .../delius/entity/ReferenceData.kt | 38 +++++- .../entity/repository/EqualityRepository.kt | 6 - .../repository/PersonManagerRepository.kt | 16 --- .../entity/repository/PersonRepository.kt | 7 -- .../repository/ReferenceDataRepository.kt | 29 ----- .../hmpps/messaging/CommonPlatformHearing.kt | 10 +- .../digital/hmpps/messaging/Handler.kt | 60 ++++++++-- .../digital/hmpps/service/AddressService.kt | 23 ++++ .../digital/hmpps/service/PersonService.kt | 8 +- .../digital/hmpps/messaging/HandlerTest.kt | 23 +++- .../hmpps/service/AddressServiceTest.kt | 42 +++++++ .../{ServiceTest.kt => PersonServiceTest.kt} | 7 +- 27 files changed, 528 insertions(+), 96 deletions(-) create mode 100644 projects/common-platform-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/AddressGenerator.kt create mode 100644 projects/common-platform-and-delius/src/dev/resources/db/oracle.sql create mode 100644 projects/common-platform-and-delius/src/dev/resources/messages/common-platform-hearing-blank-address.json create mode 100644 projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/entity/PersonAddress.kt delete mode 100644 projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/entity/repository/EqualityRepository.kt delete mode 100644 projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/entity/repository/PersonManagerRepository.kt delete mode 100644 projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/entity/repository/PersonRepository.kt delete mode 100644 projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/entity/repository/ReferenceDataRepository.kt create mode 100644 projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/AddressService.kt create mode 100644 projects/common-platform-and-delius/src/test/kotlin/uk/gov/justice/digital/hmpps/service/AddressServiceTest.kt rename projects/common-platform-and-delius/src/test/kotlin/uk/gov/justice/digital/hmpps/service/{ServiceTest.kt => PersonServiceTest.kt} (91%) diff --git a/projects/common-platform-and-delius/deploy/database/access.yml b/projects/common-platform-and-delius/deploy/database/access.yml index 1813a0db8d..e5b1ee6307 100644 --- a/projects/common-platform-and-delius/deploy/database/access.yml +++ b/projects/common-platform-and-delius/deploy/database/access.yml @@ -8,6 +8,7 @@ database: - offender_manager - equality - audited_interaction + - address packages: - offender_support_api # for generating crn diff --git a/projects/common-platform-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/DataLoader.kt b/projects/common-platform-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/DataLoader.kt index f0c935eb9f..0434e94531 100644 --- a/projects/common-platform-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/DataLoader.kt +++ b/projects/common-platform-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/DataLoader.kt @@ -26,11 +26,16 @@ class DataLoader( override fun onApplicationEvent(are: ApplicationReadyEvent) { entityManager.run { persist(BusinessInteractionGenerator.INSERT_PERSON) + persist(BusinessInteractionGenerator.INSERT_ADDRESS) persist(DatasetGenerator.GENDER) persist(DatasetGenerator.OM_ALLOCATION_REASON) + persist(DatasetGenerator.ADDRESS_STATUS) + persist(DatasetGenerator.ADDRESS_TYPE) persist(ReferenceDataGenerator.GENDER_MALE) persist(ReferenceDataGenerator.GENDER_FEMALE) persist(ReferenceDataGenerator.INITIAL_ALLOCATION) + persist(ReferenceDataGenerator.MAIN_ADDRESS_STATUS) + persist(ReferenceDataGenerator.AWAITING_ASSESSMENT) persist(ProviderGenerator.DEFAULT) persist(TeamGenerator.ALLOCATED) persist(TeamGenerator.UNALLOCATED) 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/AddressGenerator.kt new file mode 100644 index 0000000000..566fadcaec --- /dev/null +++ b/projects/common-platform-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/AddressGenerator.kt @@ -0,0 +1,24 @@ +package uk.gov.justice.digital.hmpps.data.generator + +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 { + val MAIN_ADDRESS = generate(person = PersonGenerator.DEFAULT) + + fun generate( + id: Long? = IdGenerator.getAndIncrement(), + person: Person, + notes: String? = null, + postcode: String? = null, + ) = PersonAddress( + id = id, + start = LocalDate.now(), + status = ReferenceDataGenerator.MAIN_ADDRESS_STATUS, + personId = person.id!!, + notes = notes, + postcode = postcode, + type = ReferenceDataGenerator.AWAITING_ASSESSMENT + ) +} diff --git a/projects/common-platform-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/BusinessInteractionGenerator.kt b/projects/common-platform-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/BusinessInteractionGenerator.kt index cd3f821af9..c6d09dcbaf 100644 --- a/projects/common-platform-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/BusinessInteractionGenerator.kt +++ b/projects/common-platform-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/BusinessInteractionGenerator.kt @@ -10,4 +10,9 @@ object BusinessInteractionGenerator { BusinessInteractionCode.INSERT_PERSON.code, ZonedDateTime.now().minusMonths(6) ) + val INSERT_ADDRESS = BusinessInteraction( + IdGenerator.getAndIncrement(), + BusinessInteractionCode.INSERT_ADDRESS.code, + ZonedDateTime.now().minusMonths(6) + ) } diff --git a/projects/common-platform-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/MessageGenerator.kt b/projects/common-platform-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/MessageGenerator.kt index 3da2c8634c..21c1aec18c 100644 --- a/projects/common-platform-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/MessageGenerator.kt +++ b/projects/common-platform-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/MessageGenerator.kt @@ -9,4 +9,6 @@ object MessageGenerator { ResourceLoader.message("common-platform-hearing-validation-error") val COMMON_PLATFORM_EVENT_NO_CASES = ResourceLoader.message("common-platform-hearing-no-cases") + val COMMON_PLATFORM_EVENT_BLANK_ADDRESS = + ResourceLoader.message("common-platform-hearing-blank-address") } diff --git a/projects/common-platform-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/ReferenceDataGenerator.kt b/projects/common-platform-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/ReferenceDataGenerator.kt index 6dada114a3..b1946ea95b 100644 --- a/projects/common-platform-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/ReferenceDataGenerator.kt +++ b/projects/common-platform-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/ReferenceDataGenerator.kt @@ -1,14 +1,18 @@ package uk.gov.justice.digital.hmpps.data.generator +import uk.gov.justice.digital.hmpps.data.generator.DatasetGenerator.ADDRESS_STATUS +import uk.gov.justice.digital.hmpps.data.generator.DatasetGenerator.ADDRESS_TYPE import uk.gov.justice.digital.hmpps.data.generator.DatasetGenerator.GENDER import uk.gov.justice.digital.hmpps.data.generator.DatasetGenerator.OM_ALLOCATION_REASON import uk.gov.justice.digital.hmpps.integrations.delius.entity.* object ReferenceDataGenerator { - val GENDER_FEMALE = generate("F", GENDER.id, "Female") - val GENDER_MALE = generate("M", GENDER.id, "Male") - val INITIAL_ALLOCATION = generate("IN1", OM_ALLOCATION_REASON.id, "Initial Allocation") + val GENDER_FEMALE = generate(ReferenceData.GenderCode.FEMALE.deliusValue, GENDER.id, "Female") + val GENDER_MALE = generate(ReferenceData.GenderCode.MALE.deliusValue, GENDER.id, "Male") + val INITIAL_ALLOCATION = generate(ReferenceData.StandardRefDataCode.INITIAL_ALLOCATION.code, OM_ALLOCATION_REASON.id, "Initial Allocation") + val MAIN_ADDRESS_STATUS = generate(ReferenceData.StandardRefDataCode.ADDRESS_MAIN_STATUS.code, ADDRESS_STATUS.id, "Main") + val AWAITING_ASSESSMENT = generate(ReferenceData.StandardRefDataCode.AWAITING_ASSESSMENT.code, ADDRESS_TYPE.id, "Awaiting Assessment") fun generate( code: String, @@ -22,6 +26,8 @@ object DatasetGenerator { val ALL_DATASETS = DatasetCode.entries.map { Dataset(IdGenerator.getAndIncrement(), it) }.associateBy { it.code } val GENDER = ALL_DATASETS[DatasetCode.GENDER]!! val OM_ALLOCATION_REASON = ALL_DATASETS[DatasetCode.OM_ALLOCATION_REASON]!! + val ADDRESS_TYPE = ALL_DATASETS[DatasetCode.ADDRESS_TYPE]!! + val ADDRESS_STATUS = ALL_DATASETS[DatasetCode.ADDRESS_STATUS]!! } object CourtGenerator { diff --git a/projects/common-platform-and-delius/src/dev/resources/db/oracle.sql b/projects/common-platform-and-delius/src/dev/resources/db/oracle.sql new file mode 100644 index 0000000000..a7ab3f64c6 --- /dev/null +++ b/projects/common-platform-and-delius/src/dev/resources/db/oracle.sql @@ -0,0 +1,13 @@ +CREATE OR REPLACE PACKAGE offender_support_api IS + FUNCTION getNextCRN RETURN VARCHAR2; +END offender_support_api; + +GRANT EXECUTE ON offender_support_api TO delius_app_schema; + +CREATE OR REPLACE PACKAGE BODY offender_support_api IS + FUNCTION getNextCRN RETURN VARCHAR2 IS + BEGIN + RETURN 'A111111'; + END getNextCRN; +END offender_support_api; +/ \ No newline at end of file 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 new file mode 100644 index 0000000000..6e9219f3a1 --- /dev/null +++ b/projects/common-platform-and-delius/src/dev/resources/messages/common-platform-hearing-blank-address.json @@ -0,0 +1,29 @@ +{ + "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\":[]}]}}", + "Timestamp": "2022-07-27T14:22:08.509Z", + "SignatureVersion": "1", + "Signature": "EXAMPLE", + "SigningCertURL": "https://sns.eu-west-2.amazonaws.com/EXAMPLE.pem", + "UnsubscribeURL": "https://sns.eu-west-2.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=EXAMPLE", + "MessageAttributes": { + "tracestate": { + "Type": "String", + "Value": "00-01a234b56c7de8f9g01h234i56789j0k-1l234m567n8o9p01-01" + }, + "eventType": { + "Type": "String", + "Value": "COMMON_PLATFORM_HEARING" + }, + "hearingEventType": { + "Type": "String", + "Value": "ConfirmedOrUpdated" + }, + "traceparent": { + "Type": "String", + "Value": "00-01a234b56c7de8f9g01h234i56789j0k-1l234m567n8o9p01-01" + } + } +} \ No newline at end of file diff --git a/projects/common-platform-and-delius/src/dev/resources/messages/common-platform-hearing.json b/projects/common-platform-and-delius/src/dev/resources/messages/common-platform-hearing.json index d4aa789163..73bb2c8f3e 100644 --- a/projects/common-platform-and-delius/src/dev/resources/messages/common-platform-hearing.json +++ b/projects/common-platform-and-delius/src/dev/resources/messages/common-platform-hearing.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\":\"Example Address Line 1\",\"address2\":\"Example Address Line 2\",\"address3\":\"Example Address Line 3\",\"address4\":null,\"address5\":null,\"postcode\":\"AA1 1AA\"},\"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\":[],\"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\":\"Example Address Line 1\",\"address2\":\"Example Address Line 2\",\"address3\":\"Example Address Line 3\",\"address4\":null,\"address5\":null,\"postcode\":\"AA1 1AA\"},\"contact\":{\"home\":\"01234567890\",\"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 e0ba519da8..109f7eadfc 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 @@ -4,6 +4,8 @@ import com.github.tomakehurst.wiremock.WireMockServer import com.github.tomakehurst.wiremock.client.WireMock.* import org.hamcrest.MatcherAssert.assertThat import org.hamcrest.Matchers +import org.junit.jupiter.api.Assertions.assertNotNull +import org.junit.jupiter.api.Assertions.assertNull import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.mockito.Mockito @@ -20,12 +22,17 @@ import uk.gov.justice.digital.hmpps.audit.service.AuditedInteractionService import uk.gov.justice.digital.hmpps.data.generator.MessageGenerator import uk.gov.justice.digital.hmpps.integrations.delius.audit.BusinessInteractionCode import uk.gov.justice.digital.hmpps.integrations.delius.entity.Person -import uk.gov.justice.digital.hmpps.integrations.delius.entity.repository.PersonRepository +import uk.gov.justice.digital.hmpps.integrations.delius.entity.PersonRepository +import uk.gov.justice.digital.hmpps.integrations.delius.entity.ReferenceData +import uk.gov.justice.digital.hmpps.integrations.delius.person.entity.PersonAddress +import uk.gov.justice.digital.hmpps.integrations.delius.person.entity.PersonAddressRepository import uk.gov.justice.digital.hmpps.message.Notification import uk.gov.justice.digital.hmpps.messaging.HmppsChannelManager +import uk.gov.justice.digital.hmpps.service.AddressService 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 @AutoConfigureMockMvc @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @@ -48,9 +55,15 @@ internal class IntegrationTest { @SpyBean lateinit var personRepository: PersonRepository + @SpyBean + lateinit var addressRepository: PersonAddressRepository + @SpyBean lateinit var personService: PersonService + @SpyBean + lateinit var addressService: AddressService + @BeforeEach fun setup() { doReturn("A000001").whenever(personService).generateCrn() @@ -64,7 +77,7 @@ internal class IntegrationTest { } @Test - fun `When a probation search match is detected then a person is not inserted`() { + fun `When a probation search match is detected no insert is performed`() { wireMockServer.stubFor( post(urlPathEqualTo("/probation-search/match")) .willReturn( @@ -79,6 +92,8 @@ internal class IntegrationTest { channelManager.getChannel(queueName).publishAndWait(notification) verify(personService, never()).insertPerson(any(), any()) verify(personRepository, never()).save(any()) + verify(addressService, never()).insertAddress(any()) + verify(addressRepository, never()).save(any()) verify(auditedInteractionService, Mockito.never()).createAuditedInteraction( any(), any(), @@ -105,11 +120,37 @@ internal class IntegrationTest { channelManager.getChannel(queueName).publishAndWait(notification) verify(personService, never()).insertPerson(any(), any()) + verify(addressService, never()).insertAddress(any()) + verify(addressRepository, never()).save(any()) verify(personRepository, never()).save(any()) verify(auditedInteractionService, Mockito.never()) .createAuditedInteraction(any(), any(), any(), any(), anyOrNull()) } + @Test + fun `When a person under 10 years old is found no insert is performed`() { + wireMockServer.stubFor( + post(urlPathEqualTo("/probation-search/match")) + .willReturn( + aResponse() + .withStatus(200) + .withHeader("Content-Type", "application/json") + .withBodyFile("probation-search-no-results.json") + ) + ) + + val notification = Notification(message = MessageGenerator.COMMON_PLATFORM_EVENT_VALIDATION_ERROR) + + channelManager.getChannel(queueName).publishAndWait(notification) + + verify(personService, never()).insertPerson(any(), any()) + verify(personRepository, never()).save(any()) + verify(addressService, never()).insertAddress(any()) + verify(addressRepository, never()).save(any()) + verify(auditedInteractionService, Mockito.never()) + .createAuditedInteraction(any(), any(), any(), any(), anyOrNull()) + } + @Test fun `When a probation search match is not detected then a person is inserted`() { wireMockServer.stubFor( @@ -130,6 +171,8 @@ internal class IntegrationTest { verify(personRepository).save(check { assertThat(it.forename, Matchers.equalTo("Example First Name")) assertThat(it.surname, Matchers.equalTo("Example Last Name")) + assertThat(it.mobileNumber, Matchers.equalTo("07000000000")) + assertThat(it.telephoneNumber, Matchers.equalTo("01234567890")) }) verify(auditedInteractionService).createAuditedInteraction( @@ -140,4 +183,69 @@ internal class IntegrationTest { anyOrNull() ) } + + @Test + fun `When a hearing with an address is received then an address record is inserted`() { + wireMockServer.stubFor( + post(urlPathEqualTo("/probation-search/match")) + .willReturn( + aResponse() + .withStatus(200) + .withHeader("Content-Type", "application/json") + .withBodyFile("probation-search-no-results.json") + ) + ) + + val notification = Notification(message = MessageGenerator.COMMON_PLATFORM_EVENT) + channelManager.getChannel(queueName).publishAndWait(notification) + + verify(addressService).insertAddress(any()) + + verify(addressRepository).save(check { + assertThat(it.start, Matchers.equalTo(LocalDate.now())) + assertNull(it.endDate) + assertNotNull(it.notes) + assertThat(it.softDeleted, Matchers.equalTo(false)) + assertThat(it.status.code, Matchers.equalTo(ReferenceData.StandardRefDataCode.ADDRESS_MAIN_STATUS.code)) + assertThat(it.noFixedAbode, Matchers.equalTo(false)) + assertThat(it.type.code, Matchers.equalTo(ReferenceData.StandardRefDataCode.AWAITING_ASSESSMENT.code)) + assertThat(it.typeVerified, Matchers.equalTo(false)) + }) + + verify(auditedInteractionService).createAuditedInteraction( + eq(BusinessInteractionCode.INSERT_ADDRESS), + any(), + eq(AuditedInteraction.Outcome.SUCCESS), + any(), + anyOrNull() + ) + } + + @Test + fun `When a hearing with an empty address is received then an address record is not inserted`() { + wireMockServer.stubFor( + post(urlPathEqualTo("/probation-search/match")) + .willReturn( + aResponse() + .withStatus(200) + .withHeader("Content-Type", "application/json") + .withBodyFile("probation-search-no-results.json") + ) + ) + + val notification = Notification(message = MessageGenerator.COMMON_PLATFORM_EVENT_BLANK_ADDRESS) + channelManager.getChannel(queueName).publishAndWait(notification) + + verify(addressService, never()).insertAddress(any()) + + verify(addressRepository, never()).save(any()) + + verify(auditedInteractionService, never()).createAuditedInteraction( + eq(BusinessInteractionCode.INSERT_ADDRESS), + 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/integrations/delius/audit/BusinessInteractionCode.kt b/projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/audit/BusinessInteractionCode.kt index a4ea180eac..f2b5feeea2 100644 --- a/projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/audit/BusinessInteractionCode.kt +++ b/projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/audit/BusinessInteractionCode.kt @@ -3,5 +3,6 @@ package uk.gov.justice.digital.hmpps.integrations.delius.audit import uk.gov.justice.digital.hmpps.audit.InteractionCode enum class BusinessInteractionCode(override val code: String) : InteractionCode { - INSERT_PERSON("OIBI025") + INSERT_PERSON("OIBI025"), + INSERT_ADDRESS("OIBI029") } diff --git a/projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/entity/Equality.kt b/projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/entity/Equality.kt index 04a4929bb3..bccf55ba36 100644 --- a/projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/entity/Equality.kt +++ b/projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/entity/Equality.kt @@ -5,6 +5,7 @@ import org.springframework.data.annotation.CreatedBy import org.springframework.data.annotation.CreatedDate import org.springframework.data.annotation.LastModifiedBy import org.springframework.data.annotation.LastModifiedDate +import org.springframework.data.jpa.repository.JpaRepository import java.time.ZonedDateTime @Entity @@ -38,3 +39,5 @@ class Equality( @Version val rowVersion: Long = 0L ) + +interface EqualityRepository : JpaRepository \ No newline at end of file diff --git a/projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/entity/Person.kt b/projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/entity/Person.kt index 508b67bfe6..194f233d2b 100644 --- a/projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/entity/Person.kt +++ b/projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/entity/Person.kt @@ -7,6 +7,7 @@ import org.springframework.data.annotation.CreatedDate import org.springframework.data.annotation.LastModifiedBy import org.springframework.data.annotation.LastModifiedDate import org.springframework.data.jpa.domain.support.AuditingEntityListener +import org.springframework.data.jpa.repository.JpaRepository import java.time.LocalDate import java.time.ZonedDateTime @@ -46,9 +47,24 @@ class Person( @JoinColumn(name = "gender_id") val gender: ReferenceData, + @Column(name = "telephone_number") + val telephoneNumber: String? = null, + + @Column(name = "mobile_number") + val mobileNumber: String? = null, + @Column(columnDefinition = "number") val softDeleted: Boolean = false, + @Column(name="current_disposal", columnDefinition = "number") + val currentDisposal: Boolean = false, + + @Column(name="current_restriction", columnDefinition = "number") + val currentRestriction: Boolean = false, + + @Column(name="pending_transfer", columnDefinition = "number") + val pendingTransfer: Boolean = false, + @Column @Version val rowVersion: Long = 0L, @@ -64,4 +80,6 @@ class Person( @LastModifiedBy var lastUpdatedUserId: Long = 0, -) \ No newline at end of file +) + +interface PersonRepository : JpaRepository \ No newline at end of file diff --git a/projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/entity/PersonAddress.kt b/projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/entity/PersonAddress.kt new file mode 100644 index 0000000000..13b1c09bf4 --- /dev/null +++ b/projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/entity/PersonAddress.kt @@ -0,0 +1,111 @@ +package uk.gov.justice.digital.hmpps.integrations.delius.person.entity + +import jakarta.persistence.* +import org.hibernate.type.YesNoConverter +import org.springframework.data.annotation.CreatedBy +import org.springframework.data.annotation.CreatedDate +import org.springframework.data.annotation.LastModifiedBy +import org.springframework.data.annotation.LastModifiedDate +import org.springframework.data.jpa.domain.support.AuditingEntityListener +import org.springframework.data.jpa.repository.JpaRepository +import uk.gov.justice.digital.hmpps.integrations.delius.entity.ReferenceData +import java.time.LocalDate +import java.time.ZonedDateTime + +@Entity +@Table(name = "offender_address") +@EntityListeners(AuditingEntityListener::class) +@SequenceGenerator(name = "offender_address_id_generator", sequenceName = "offender_address_id_seq", allocationSize = 1) +class PersonAddress( + @Id + @Column(name = "offender_address_id") + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "offender_address_id_generator") + val id: Long? = null, + + @Column(name = "start_date") + val start: LocalDate? = null, + + @Column(name = "end_date") + val endDate: LocalDate? = null, + + @Column(name = "partition_area_id", nullable = false) + val partitionAreaId: Long = 0, + + @Column(name = "soft_deleted", updatable = false, columnDefinition = "NUMBER") + val softDeleted: Boolean = false, + + @Column(name = "row_version") + @Version + val rowVersion: Long = 0L, + + @ManyToOne + @JoinColumn(name = "address_status_id") + var status: ReferenceData, + + @Convert(converter = YesNoConverter::class) + @Column(name = "no_fixed_abode") + val noFixedAbode: Boolean? = false, + + @Column(name = "offender_id") + val personId: Long, + + @Column(name = "notes", columnDefinition = "clob") + val notes: String? = null, + + @Column(name = "address_number") + val addressNumber: String? = null, + + @Column(name = "street_name") + var streetName: String? = null, + + @Column(name = "district") + var district: String? = null, + + @Column(name = "town_city") + var town: String? = null, + + @CreatedDate + @Column(nullable = false) + var createdDatetime: ZonedDateTime = ZonedDateTime.now(), + + @Column(name = "county") + var county: String? = null, + + @Column(nullable = false) + @LastModifiedDate + var lastUpdatedDatetime: ZonedDateTime = ZonedDateTime.now(), + + @Column(name = "building_name") + var buildingName: String? = null, + + @Column(name = "postcode") + var postcode: String? = null, + + @Column(nullable = false) + @CreatedBy + var createdByUserId: Long = 0, + + @Column(name = "telephone_number") + val telephoneNumber: String? = null, + + @Column(nullable = false) + @LastModifiedBy + var lastUpdatedUserId: Long = 0, + + @Column(name = "awaiting_assessment", columnDefinition = "NUMBER", nullable = false) + val awaitingAssessment: Boolean = false, + + @ManyToOne + @JoinColumn(name = "address_type_id") + val type: ReferenceData, + + @Column(name = "type_verified") + @Convert(converter = YesNoConverter::class) + val typeVerified: Boolean? = false, + + @Column(name = "approved_premises_residence_id") + val approvedPremisesResidenceId: Long? = null, + ) + + +interface PersonAddressRepository : JpaRepository \ No newline at end of file diff --git a/projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/entity/PersonManager.kt b/projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/entity/PersonManager.kt index ab719be0a5..3a7aaa951a 100644 --- a/projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/entity/PersonManager.kt +++ b/projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/entity/PersonManager.kt @@ -7,6 +7,7 @@ import org.springframework.data.annotation.CreatedBy import org.springframework.data.annotation.CreatedDate import org.springframework.data.annotation.LastModifiedBy import org.springframework.data.annotation.LastModifiedDate +import org.springframework.data.jpa.repository.JpaRepository import java.time.LocalDate import java.time.LocalDateTime import java.time.ZonedDateTime @@ -101,4 +102,14 @@ class Team( @Column val description: String, -) \ No newline at end of file +) + +interface PersonManagerRepository : JpaRepository + +interface TeamRepository : JpaRepository { + fun findByCode(code: String): Team +} + +interface StaffRepository : JpaRepository { + fun findByCode(code: String): Staff +} \ No newline at end of file diff --git a/projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/entity/ReferenceData.kt b/projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/entity/ReferenceData.kt index e024daefd5..4a27747ae0 100644 --- a/projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/entity/ReferenceData.kt +++ b/projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/entity/ReferenceData.kt @@ -3,6 +3,9 @@ package uk.gov.justice.digital.hmpps.integrations.delius.entity import jakarta.persistence.* import org.hibernate.annotations.Immutable import org.hibernate.type.YesNoConverter +import org.springframework.data.jpa.repository.JpaRepository +import org.springframework.data.jpa.repository.Query +import uk.gov.justice.digital.hmpps.exception.NotFoundException import java.time.LocalDate @Entity @@ -29,8 +32,10 @@ class ReferenceData( NOT_KNOWN("NOT KNOWN", "N") } - enum class AllocationCode(val code: String) { - INITIAL_ALLOCATION("IN1") + enum class StandardRefDataCode(val code: String) { + INITIAL_ALLOCATION("IN1"), + ADDRESS_MAIN_STATUS("M"), + AWAITING_ASSESSMENT("A16") } } @@ -49,6 +54,8 @@ class Dataset( enum class DatasetCode(val value: String) { OM_ALLOCATION_REASON("OM ALLOCATION REASON"), + ADDRESS_STATUS("ADDRESS STATUS"), + ADDRESS_TYPE("ADDRESS TYPE"), GENDER("GENDER"); companion object { @@ -110,3 +117,30 @@ class Court( @Column(name = "national_court_code") val nationalCourtCode: String? ) + +interface ReferenceDataRepository : JpaRepository { + @Query( + """ + select rd from ReferenceData rd + join Dataset ds on rd.datasetId = ds.id + where ds.code = :datasetCode and rd.code = :code + """ + ) + fun findByCodeAndDatasetCode(code: String, datasetCode: DatasetCode): ReferenceData? +} + +fun ReferenceDataRepository.initialAllocationReason() = + findByCodeAndDatasetCode(ReferenceData.StandardRefDataCode.INITIAL_ALLOCATION.code, DatasetCode.OM_ALLOCATION_REASON) + ?: throw NotFoundException("Allocation Reason", "code", ReferenceData.StandardRefDataCode.INITIAL_ALLOCATION.code) + +fun ReferenceDataRepository.mainAddressStatus() = + findByCodeAndDatasetCode(ReferenceData.StandardRefDataCode.ADDRESS_MAIN_STATUS.code, DatasetCode.ADDRESS_STATUS) + ?: throw NotFoundException("Address Status", "code", ReferenceData.StandardRefDataCode.ADDRESS_MAIN_STATUS.code) + +fun ReferenceDataRepository.awaitingAssessmentAddressType() = + findByCodeAndDatasetCode(ReferenceData.StandardRefDataCode.AWAITING_ASSESSMENT.code, DatasetCode.ADDRESS_TYPE) + ?: throw NotFoundException("Address Type", "code", ReferenceData.StandardRefDataCode.AWAITING_ASSESSMENT.code) + +interface CourtRepository : JpaRepository { + fun findByNationalCourtCode(nationalCourtCode: String): Court +} \ No newline at end of file diff --git a/projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/entity/repository/EqualityRepository.kt b/projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/entity/repository/EqualityRepository.kt deleted file mode 100644 index c8c263cb26..0000000000 --- a/projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/entity/repository/EqualityRepository.kt +++ /dev/null @@ -1,6 +0,0 @@ -package uk.gov.justice.digital.hmpps.integrations.delius.entity.repository - -import org.springframework.data.jpa.repository.JpaRepository -import uk.gov.justice.digital.hmpps.integrations.delius.entity.Equality - -interface EqualityRepository : JpaRepository \ No newline at end of file diff --git a/projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/entity/repository/PersonManagerRepository.kt b/projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/entity/repository/PersonManagerRepository.kt deleted file mode 100644 index fe0df47a88..0000000000 --- a/projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/entity/repository/PersonManagerRepository.kt +++ /dev/null @@ -1,16 +0,0 @@ -package uk.gov.justice.digital.hmpps.integrations.delius.entity.repository - -import org.springframework.data.jpa.repository.JpaRepository -import uk.gov.justice.digital.hmpps.integrations.delius.entity.PersonManager -import uk.gov.justice.digital.hmpps.integrations.delius.entity.Staff -import uk.gov.justice.digital.hmpps.integrations.delius.entity.Team - -interface PersonManagerRepository : JpaRepository - -interface TeamRepository : JpaRepository { - fun findByCode(code: String): Team -} - -interface StaffRepository : JpaRepository { - fun findByCode(code: String): Staff -} \ No newline at end of file diff --git a/projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/entity/repository/PersonRepository.kt b/projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/entity/repository/PersonRepository.kt deleted file mode 100644 index 2551bba051..0000000000 --- a/projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/entity/repository/PersonRepository.kt +++ /dev/null @@ -1,7 +0,0 @@ -package uk.gov.justice.digital.hmpps.integrations.delius.entity.repository - -import org.springframework.data.jpa.repository.JpaRepository -import uk.gov.justice.digital.hmpps.integrations.delius.entity.Person - -interface PersonRepository : JpaRepository - diff --git a/projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/entity/repository/ReferenceDataRepository.kt b/projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/entity/repository/ReferenceDataRepository.kt deleted file mode 100644 index 6b5e376992..0000000000 --- a/projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/entity/repository/ReferenceDataRepository.kt +++ /dev/null @@ -1,29 +0,0 @@ -package uk.gov.justice.digital.hmpps.integrations.delius.entity.repository - -import org.springframework.data.jpa.repository.JpaRepository -import org.springframework.data.jpa.repository.Query -import uk.gov.justice.digital.hmpps.exception.NotFoundException -import uk.gov.justice.digital.hmpps.integrations.delius.entity.Court -import uk.gov.justice.digital.hmpps.integrations.delius.entity.DatasetCode -import uk.gov.justice.digital.hmpps.integrations.delius.entity.ReferenceData - -interface ReferenceDataRepository : JpaRepository { - fun findByCode(code: String): ReferenceData - - @Query( - """ - select rd from ReferenceData rd - join Dataset ds on rd.datasetId = ds.id - where ds.code = :datasetCode and rd.code = :code - """ - ) - fun findByCodeAndDatasetCode(code: String, datasetCode: DatasetCode): ReferenceData? -} - -fun ReferenceDataRepository.initialAllocationReason() = - findByCodeAndDatasetCode(ReferenceData.AllocationCode.INITIAL_ALLOCATION.code, DatasetCode.OM_ALLOCATION_REASON) - ?: throw NotFoundException("Allocation Reason", "code", ReferenceData.AllocationCode.INITIAL_ALLOCATION.code) - -interface CourtRepository : JpaRepository { - fun findByNationalCourtCode(nationalCourtCode: String): Court -} \ No newline at end of file diff --git a/projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/messaging/CommonPlatformHearing.kt b/projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/messaging/CommonPlatformHearing.kt index 05dc305ccf..176780f88e 100644 --- a/projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/messaging/CommonPlatformHearing.kt +++ b/projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/messaging/CommonPlatformHearing.kt @@ -68,17 +68,17 @@ data class PersonDetails( val firstName: String, val dateOfBirth: LocalDate, val address: Address, - val contact: Contact, + val contact: Contact?, val ethnicity: Ethnicity ) data class Address( - val address1: String, - val address2: String, - val address3: String, + val address1: String? = null, + val address2: String? = null, + val address3: String? = null, val address4: String? = null, val address5: String? = null, - val postcode: String + val postcode: String? = null ) data class Contact( 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 12842e538a..1bf0322248 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 @@ -10,10 +10,10 @@ import org.springframework.stereotype.Component import uk.gov.justice.digital.hmpps.converter.NotificationConverter import uk.gov.justice.digital.hmpps.integrations.client.ProbationMatchRequest import uk.gov.justice.digital.hmpps.integrations.client.ProbationSearchClient -import uk.gov.justice.digital.hmpps.integrations.delius.entity.Person -import uk.gov.justice.digital.hmpps.integrations.delius.entity.ReferenceData -import uk.gov.justice.digital.hmpps.integrations.delius.entity.repository.ReferenceDataRepository +import uk.gov.justice.digital.hmpps.integrations.delius.entity.* +import uk.gov.justice.digital.hmpps.integrations.delius.person.entity.PersonAddress import uk.gov.justice.digital.hmpps.message.Notification +import uk.gov.justice.digital.hmpps.service.AddressService 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 @@ -26,6 +26,7 @@ class Handler( override val converter: NotificationConverter, private val telemetryService: TelemetryService, private val personService: PersonService, + private val addressService: AddressService, private val referenceDataRepository: ReferenceDataRepository, private val probationSearchClient: ProbationSearchClient ) : NotificationHandler { @@ -34,8 +35,9 @@ class Handler( override fun handle(notification: Notification) { telemetryService.notificationReceived(notification) - val defendant = notification.message.hearing.prosecutionCases.firstOrNull()?.defendants?.firstOrNull() - ?: throw IllegalArgumentException("No prosecution cases found") + val defendants = notification.message.hearing.prosecutionCases + .flatMap { it.defendants } + .ifEmpty { throw IllegalArgumentException("No defendants found") } val courtCode = notification.message.hearing.courtCentre.code @@ -59,7 +61,31 @@ class Handler( log.debug("Matching offender(s) found for: {}", matchRequest) return } - personService.insertPerson(defendant.toPerson(), courtCode) + + defendants.forEach { defendant -> + // Insert each defendant as a person record + val savedPerson = personService.insertPerson(defendant.toPerson(), courtCode) + + val address = defendant.personDefendant?.personDetails?.address + + // Insert each defendant's address record + val savedAddress = if (address.containsInformation()) { + addressService.insertAddress( + PersonAddress( + id = null, + start = LocalDate.now(), + status = referenceDataRepository.mainAddressStatus(), + personId = savedPerson.id!!, + notes = address?.buildNotes(), + postcode = address?.postcode, + type = referenceDataRepository.awaitingAssessmentAddressType() + ) + ) + } else { + log.debug("No address found for defendant with pncId: {}", defendant.pncId) + null + } + } } companion object { @@ -77,9 +103,11 @@ class Handler( pncNumber = this.pncId, forename = personDetails.firstName, secondName = personDetails.middleName, + telephoneNumber = personDetails.contact?.home, + mobileNumber = personDetails.contact?.mobile, surname = personDetails.lastName, dateOfBirth = personDetails.dateOfBirth, - gender = referenceDataRepository.findByCode(genderCode), + gender = referenceDataRepository.findByCodeAndDatasetCode(genderCode, DatasetCode.GENDER)!!, softDeleted = false ) } @@ -99,6 +127,24 @@ class Handler( fun String.toDeliusGender() = ReferenceData.GenderCode.entries.find { it.commonPlatformValue == this }?.deliusValue ?: throw IllegalStateException("Gender not found: $this") + + fun Address?.containsInformation(): Boolean { + return this != null && listOf( + this.address1, this.address2, this.address3, + this.address4, this.address5, this.postcode + ).any { !it.isNullOrBlank() } + } + + fun Address.buildNotes(): String { + return listOf( + "Address record automatically created by common-platform-delius-service with the following information:", + "Address1: ${this.address1 ?: "N/A"}", + "Address2: ${this.address2 ?: "N/A"}", + "Address3: ${this.address3 ?: "N/A"}", + "Address4: ${this.address4 ?: "N/A"}", + "Postcode: ${this.postcode ?: "N/A"}" + ).joinToString("\n") + } } diff --git a/projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/AddressService.kt b/projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/AddressService.kt new file mode 100644 index 0000000000..3cab13df31 --- /dev/null +++ b/projects/common-platform-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/AddressService.kt @@ -0,0 +1,23 @@ +package uk.gov.justice.digital.hmpps.service + +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional +import uk.gov.justice.digital.hmpps.audit.service.AuditableService +import uk.gov.justice.digital.hmpps.audit.service.AuditedInteractionService +import uk.gov.justice.digital.hmpps.integrations.delius.audit.BusinessInteractionCode +import uk.gov.justice.digital.hmpps.integrations.delius.person.entity.PersonAddress +import uk.gov.justice.digital.hmpps.integrations.delius.person.entity.PersonAddressRepository + +@Service +class AddressService( + auditedInteractionService: AuditedInteractionService, + private val personAddressRepository: PersonAddressRepository +) : AuditableService(auditedInteractionService) { + + @Transactional + fun insertAddress(address: PersonAddress): PersonAddress = audit(BusinessInteractionCode.INSERT_ADDRESS) { audit -> + val savedAddress = personAddressRepository.save(address) + audit["offenderId"] = address.personId + savedAddress + } +} \ 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 73a40eb76b..a1e45df056 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 @@ -8,10 +8,7 @@ import org.springframework.transaction.annotation.Transactional import uk.gov.justice.digital.hmpps.audit.service.AuditableService import uk.gov.justice.digital.hmpps.audit.service.AuditedInteractionService import uk.gov.justice.digital.hmpps.integrations.delius.audit.BusinessInteractionCode -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.entity.repository.* +import uk.gov.justice.digital.hmpps.integrations.delius.entity.* import java.sql.Types import java.time.LocalDateTime @@ -37,7 +34,7 @@ class PersonService( ) @Transactional - fun insertPerson(person: Person, courtCode: String) = audit(BusinessInteractionCode.INSERT_PERSON) { audit -> + fun insertPerson(person: Person, courtCode: String): Person = audit(BusinessInteractionCode.INSERT_PERSON) { audit -> // Person record val savedPerson = personRepository.save(person) @@ -72,6 +69,7 @@ class PersonService( equalityRepository.save(equality) audit["offenderId"] = savedPerson.id + savedPerson } fun generateCrn(): String { 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 db3538fa50..65b192cdc1 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 @@ -1,5 +1,6 @@ package uk.gov.justice.digital.hmpps.messaging +import com.fasterxml.jackson.module.kotlin.MissingKotlinParameterException import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertThrows import org.junit.jupiter.api.extension.ExtendWith @@ -11,10 +12,15 @@ 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.PersonGenerator import uk.gov.justice.digital.hmpps.data.generator.ReferenceDataGenerator -import uk.gov.justice.digital.hmpps.integrations.client.* -import uk.gov.justice.digital.hmpps.integrations.delius.entity.repository.ReferenceDataRepository +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.DatasetCode +import uk.gov.justice.digital.hmpps.integrations.delius.entity.ReferenceData +import uk.gov.justice.digital.hmpps.integrations.delius.entity.ReferenceDataRepository import uk.gov.justice.digital.hmpps.message.Notification +import uk.gov.justice.digital.hmpps.service.AddressService 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 @@ -30,6 +36,9 @@ internal class HandlerTest { @Mock lateinit var personService: PersonService + @Mock + lateinit var addressService: AddressService + @Mock lateinit var referenceDataRepository: ReferenceDataRepository @@ -48,7 +57,11 @@ internal class HandlerTest { ) ) whenever(personService.generateCrn()).thenReturn("A000001") - whenever(referenceDataRepository.findByCode("M")).thenReturn(ReferenceDataGenerator.GENDER_MALE) + whenever(personService.insertPerson(any(), any())).thenReturn(PersonGenerator.DEFAULT) + whenever(referenceDataRepository.findByCodeAndDatasetCode(ReferenceData.GenderCode.MALE.deliusValue, DatasetCode.GENDER)).thenReturn(ReferenceDataGenerator.GENDER_MALE) + whenever(referenceDataRepository.findByCodeAndDatasetCode(ReferenceData.StandardRefDataCode.ADDRESS_MAIN_STATUS.code, DatasetCode.ADDRESS_STATUS)).thenReturn(ReferenceDataGenerator.MAIN_ADDRESS_STATUS) + whenever(referenceDataRepository.findByCodeAndDatasetCode(ReferenceData.StandardRefDataCode.AWAITING_ASSESSMENT.code, DatasetCode.ADDRESS_TYPE)).thenReturn(ReferenceDataGenerator.AWAITING_ASSESSMENT) + val notification = Notification(message = MessageGenerator.COMMON_PLATFORM_EVENT) handler.handle(notification) verify(telemetryService).notificationReceived(notification) @@ -64,11 +77,11 @@ internal class HandlerTest { } @Test - fun `exception thrown prosecution cases is empty`() { + fun `exception thrown when prosecution cases is empty`() { val notification = Notification(message = MessageGenerator.COMMON_PLATFORM_EVENT_NO_CASES) val exception = assertThrows { handler.handle(notification) } - assert(exception.message!!.contains("No prosecution cases found")) + assert(exception.message!!.contains("No defendants found")) } } diff --git a/projects/common-platform-and-delius/src/test/kotlin/uk/gov/justice/digital/hmpps/service/AddressServiceTest.kt b/projects/common-platform-and-delius/src/test/kotlin/uk/gov/justice/digital/hmpps/service/AddressServiceTest.kt new file mode 100644 index 0000000000..c3ce313ce3 --- /dev/null +++ b/projects/common-platform-and-delius/src/test/kotlin/uk/gov/justice/digital/hmpps/service/AddressServiceTest.kt @@ -0,0 +1,42 @@ +package uk.gov.justice.digital.hmpps.service + +import org.hamcrest.MatcherAssert.assertThat +import org.hamcrest.Matchers.equalTo +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith +import org.mockito.InjectMocks +import org.mockito.Mock +import org.mockito.Mockito.verify +import org.mockito.junit.jupiter.MockitoExtension +import org.mockito.kotlin.check +import org.mockito.kotlin.whenever +import uk.gov.justice.digital.hmpps.audit.service.AuditedInteractionService +import uk.gov.justice.digital.hmpps.data.generator.AddressGenerator +import uk.gov.justice.digital.hmpps.integrations.delius.person.entity.PersonAddressRepository + +@ExtendWith(MockitoExtension::class) +class AddressServiceTest { + @Mock + lateinit var auditedInteractionService: AuditedInteractionService + + @Mock + private lateinit var addressRepository: PersonAddressRepository + + @InjectMocks + private lateinit var addressService: AddressService + + @Test + fun `successfully inserts address record`() { + val mainAddress = AddressGenerator.MAIN_ADDRESS + whenever(addressRepository.save(mainAddress)).thenReturn(mainAddress) + + addressService.insertAddress(mainAddress) + + verify(addressRepository).save(check { + assertThat(it.personId, equalTo(mainAddress.personId)) + assertThat(it.start, equalTo(mainAddress.start)) + assertThat(it.status, equalTo(mainAddress.status)) + assertThat(it.type, equalTo(mainAddress.type)) + }) + } +} diff --git a/projects/common-platform-and-delius/src/test/kotlin/uk/gov/justice/digital/hmpps/service/ServiceTest.kt b/projects/common-platform-and-delius/src/test/kotlin/uk/gov/justice/digital/hmpps/service/PersonServiceTest.kt similarity index 91% rename from projects/common-platform-and-delius/src/test/kotlin/uk/gov/justice/digital/hmpps/service/ServiceTest.kt rename to projects/common-platform-and-delius/src/test/kotlin/uk/gov/justice/digital/hmpps/service/PersonServiceTest.kt index 2eb11a35e4..487387e571 100644 --- a/projects/common-platform-and-delius/src/test/kotlin/uk/gov/justice/digital/hmpps/service/ServiceTest.kt +++ b/projects/common-platform-and-delius/src/test/kotlin/uk/gov/justice/digital/hmpps/service/PersonServiceTest.kt @@ -15,10 +15,7 @@ import org.mockito.kotlin.whenever import org.springframework.jdbc.core.JdbcTemplate import uk.gov.justice.digital.hmpps.audit.service.AuditedInteractionService import uk.gov.justice.digital.hmpps.data.generator.* -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.entity.repository.* +import uk.gov.justice.digital.hmpps.integrations.delius.entity.* import java.time.LocalDateTime @ExtendWith(MockitoExtension::class) @@ -64,7 +61,7 @@ class PersonServiceTest { whenever(personRepository.save(person)).thenReturn(savedPerson) whenever(courtRepository.findByNationalCourtCode(anyString())).thenReturn(court) - whenever(referenceDataRepository.findByCodeAndDatasetCode(anyString(), any())).thenReturn(initialAllocation) + whenever(referenceDataRepository.findByCodeAndDatasetCode(ReferenceData.StandardRefDataCode.INITIAL_ALLOCATION.code, DatasetCode.OM_ALLOCATION_REASON)).thenReturn(initialAllocation) whenever(teamRepository.findByCode(anyString())).thenReturn(unallocatedTeam) whenever(staffRepository.findByCode(anyString())).thenReturn(unallocatedStaff)