Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
- Insert address logic implemented
  • Loading branch information
joseph-bcl committed Oct 18, 2024
1 parent 3ff62c6 commit e1483b7
Show file tree
Hide file tree
Showing 27 changed files with 528 additions and 96 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ database:
- offender_manager
- equality
- audited_interaction
- address
packages:
- offender_support_api # for generating crn

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
@@ -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
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -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)
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,6 @@ object MessageGenerator {
ResourceLoader.message<CommonPlatformHearing>("common-platform-hearing-validation-error")
val COMMON_PLATFORM_EVENT_NO_CASES =
ResourceLoader.message<CommonPlatformHearing>("common-platform-hearing-no-cases")
val COMMON_PLATFORM_EVENT_BLANK_ADDRESS =
ResourceLoader.message<CommonPlatformHearing>("common-platform-hearing-blank-address")
}
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -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 {
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
/
Original file line number Diff line number Diff line change
@@ -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"
}
}
}
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\":\"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",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
Expand All @@ -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()
Expand All @@ -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(
Expand All @@ -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(),
Expand All @@ -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(
Expand All @@ -130,6 +171,8 @@ internal class IntegrationTest {
verify(personRepository).save(check<Person> {
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(
Expand All @@ -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<PersonAddress> {
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()
)
}
}
Loading

0 comments on commit e1483b7

Please sign in to comment.