From 4d807cf0308de2cf8c09c2a5d52091c55dd77290 Mon Sep 17 00:00:00 2001 From: "Joseph.Dundon" Date: Mon, 16 Dec 2024 14:41:06 +0000 Subject: [PATCH] PI-2670 - Feature flag feedback fixes --- .../justice/digital/hmpps/IntegrationTest.kt | 2 +- .../digital/hmpps/messaging/Handler.kt | 79 ++++---- .../digital/hmpps/service/PersonService.kt | 183 +++++++----------- .../digital/hmpps/messaging/HandlerTest.kt | 11 +- 4 files changed, 115 insertions(+), 160 deletions(-) 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 f49cbde64..c86a55cc5 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 @@ -333,7 +333,7 @@ internal class IntegrationTest { whenever(featureFlags.enabled("common-platform-record-creation-toggle")).thenReturn(false) val notification = Notification(message = MessageGenerator.COMMON_PLATFORM_EVENT) channelManager.getChannel(queueName).publishAndWait(notification) - verify(personService).insertPerson(any(), any()) + verify(personService, never()).insertPerson(any(), any()) thenNoRecordsAreInserted() verify(auditedInteractionService, Mockito.never()) .createAuditedInteraction(any(), any(), eq(AuditedInteraction.Outcome.FAIL), any(), anyOrNull()) 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 e5d9220d9..3606a2bdc 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 @@ -13,6 +13,8 @@ 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") @@ -50,50 +52,55 @@ class Handler( val matchedPersonResponse = probationSearchClient.match(matchRequest) if (matchedPersonResponse.matches.isNotEmpty()) { + telemetryService.trackEvent( + "ProbationSearchMatchDetected", + mapOf( + "hearingId" to notification.message.hearing.id, + "defendantId" to defendant.id, + ) + ) return@forEach } - // Insert each defendant as a person record - val savedEntities = personService.insertPerson(defendant, notification.message.hearing.courtCentre.code) + 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" + } + } + + if (featureFlags.enabled("common-platform-record-creation-toggle")) { + // Insert each defendant as a person record + val savedEntities = personService.insertPerson(defendant, notification.message.hearing.courtCentre.code) - val eventName = if (featureFlags.enabled("common-platform-record-creation-toggle")) { notifier.caseCreated(savedEntities.person) savedEntities.address?.let { notifier.addressCreated(it) } - "PersonCreated" - } else { - "SimulatedPersonCreated" - } - telemetryService.trackEvent( - eventName, - mapOf( - "hearingId" to notification.message.hearing.id, - "CRN" to savedEntities.person.crn, - "personId" to savedEntities.person.id.toString(), - "firstName" to savedEntities.person.forename, - "surname" to savedEntities.person.surname, - "dob" to savedEntities.person.dateOfBirth.toString(), - "genderCode" to savedEntities.person.gender.description, - "pnc" to savedEntities.person.pncNumber.toString(), - "personManagerId" to savedEntities.personManager.id.toString(), - "allocationDate" to savedEntities.personManager.allocationDate.toString(), - "allocationReason" to savedEntities.personManager.allocationReason.description, - "providerCode" to savedEntities.personManager.provider.code, - "teamCode" to savedEntities.personManager.team.code, - "staffCode" to savedEntities.personManager.staff.code, - "equalityId" to savedEntities.equality.id.toString(), - "addressId" to savedEntities.address?.id.toString(), - "buildingName" to savedEntities.address?.buildingName.toString(), - "addressNumber" to savedEntities.address?.addressNumber.toString(), - "streetName" to savedEntities.address?.streetName.toString(), - "town" to savedEntities.address?.town.toString(), - "district" to savedEntities.address?.district.toString(), - "county" to savedEntities.address?.county.toString(), - "type" to savedEntities.address?.type?.description.toString(), - "status" to savedEntities.address?.status?.description.toString(), - "postcode" to savedEntities.address?.postcode.toString(), + telemetryService.trackEvent( + "PersonCreated", + mapOf( + "hearingId" to notification.message.hearing.id, + "defendantId" to defendant.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(), + ) ) - ) + } else { + telemetryService.trackEvent( + "SimulatedPersonCreated", + mapOf( + "hearingId" to notification.message.hearing.id, + "defendantId" to defendant.id + ) + ) + } } } 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 9e75d0c27..fadd4169b 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 @@ -1,10 +1,8 @@ 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.flags.FeatureFlags import uk.gov.justice.digital.hmpps.integrations.client.OsClient import uk.gov.justice.digital.hmpps.integrations.client.OsPlacesResponse import uk.gov.justice.digital.hmpps.integrations.delius.audit.BusinessInteractionCode @@ -15,7 +13,6 @@ import uk.gov.justice.digital.hmpps.messaging.Address import uk.gov.justice.digital.hmpps.messaging.Defendant import java.time.LocalDate import java.time.LocalDateTime -import java.time.Period @Service class PersonService( @@ -28,137 +25,97 @@ class PersonService( private val staffRepository: StaffRepository, private val referenceDataRepository: ReferenceDataRepository, private val personAddressRepository: PersonAddressRepository, - private val osClient: OsClient, - private val featureFlags: FeatureFlags + private val osClient: OsClient ) : AuditableService(auditedInteractionService) { - @Transactional fun insertPerson(defendant: Defendant, courtCode: String): InsertPersonResult = - if (featureFlags.enabled("common-platform-record-creation-toggle")) { - audit(BusinessInteractionCode.INSERT_PERSON) { audit -> - val result = insertPersonLogic(defendant, courtCode) - audit["offenderId"] = result.person.id!! - result - } - } else { - insertPersonLogic(defendant, courtCode) - } - - fun insertPersonLogic(defendant: Defendant, courtCode: String): InsertPersonResult { - 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" - } - } + audit(BusinessInteractionCode.INSERT_PERSON) { audit -> + // Person record + val savedPerson = personRepository.save(defendant.toPerson()) + + val courtLinkedProvider = courtRepository.getByOuCode(courtCode).provider + val initialAllocation = referenceDataRepository.initialAllocationReason() + val unallocatedTeam = teamRepository.findByCode(courtLinkedProvider.code + "UAT") + val unallocatedStaff = staffRepository.findByCode(unallocatedTeam.code + "U") + + // Person manager record + val manager = PersonManager( + person = savedPerson, + staff = unallocatedStaff, + team = unallocatedTeam, + provider = courtLinkedProvider, + softDeleted = false, + active = true, + allocationReason = initialAllocation, + staffEmployeeID = unallocatedStaff.id, + trustProviderTeamId = unallocatedTeam.id, + allocationDate = LocalDateTime.of(1900, 1, 1, 0, 0) - // Person record - val savedPerson = if (featureFlags.enabled("common-platform-record-creation-toggle")) { - personRepository.save(defendant.toPerson()) - } else { - defendant.toPerson() - } - - val courtLinkedProvider = courtRepository.getByOuCode(courtCode).provider - val initialAllocation = referenceDataRepository.initialAllocationReason() - val unallocatedTeam = teamRepository.findByCode(courtLinkedProvider.code + "UAT") - val unallocatedStaff = staffRepository.findByCode(unallocatedTeam.code + "U") - - // Person manager record - val manager = PersonManager( - person = savedPerson, - staff = unallocatedStaff, - team = unallocatedTeam, - provider = courtLinkedProvider, - softDeleted = false, - active = true, - allocationReason = initialAllocation, - staffEmployeeID = unallocatedStaff.id, - trustProviderTeamId = unallocatedTeam.id, - allocationDate = LocalDateTime.of(1900, 1, 1, 0, 0) + ) + val savedManager = personManagerRepository.save(manager) - ) + // Equality record + val equality = Equality( + id = null, + personId = savedPerson.id!!, + softDeleted = false, + ) - val savedManager = if (featureFlags.enabled("common-platform-record-creation-toggle")) { - personManagerRepository.save(manager) - } else { - manager - } + val savedEquality = equalityRepository.save(equality) - // Equality record - val equality = Equality( - id = null, - personId = savedPerson.id ?: 0L, - softDeleted = false, - ) + val addressInfo = defendant.personDefendant?.personDetails?.address + val osPlacesResponse = addressInfo?.takeIf { it.containsInformation() && !it.postcode.isNullOrBlank() } + ?.let { findAddressByFreeText(it) } - val savedEquality = if (featureFlags.enabled("common-platform-record-creation-toggle")) { - equalityRepository.save(equality) - } else { - equality - } + val deliveryPointAddress = osPlacesResponse?.results?.firstOrNull()?.dpa - val addressInfo = defendant.personDefendant.personDetails.address - val osPlacesResponse = addressInfo?.takeIf { it.containsInformation() && !it.postcode.isNullOrBlank() } - ?.let { findAddressByFreeText(it) } - - val deliveryPointAddress = osPlacesResponse?.results?.firstOrNull()?.dpa - - val savedAddress = if (deliveryPointAddress != null) { - insertAddress( - PersonAddress( - id = null, - start = LocalDate.now(), - status = referenceDataRepository.mainAddressStatus(), - person = savedPerson, - type = referenceDataRepository.awaitingAssessmentAddressType(), - postcode = deliveryPointAddress.postcode, - notes = "UPRN: ${deliveryPointAddress.uprn}", - buildingName = listOfNotNull( - deliveryPointAddress.subBuildingName, - deliveryPointAddress.buildingName - ).joinToString(" "), - addressNumber = deliveryPointAddress.buildingNumber?.toString(), - streetName = deliveryPointAddress.thoroughfareName, - town = deliveryPointAddress.postTown, - district = deliveryPointAddress.localCustodianCodeDescription - ) - ) - } else { - addressInfo?.takeIf { it.containsInformation() }?.let { + val savedAddress = if (deliveryPointAddress != null) { insertAddress( PersonAddress( id = null, start = LocalDate.now(), status = referenceDataRepository.mainAddressStatus(), person = savedPerson, - postcode = it.postcode, type = referenceDataRepository.awaitingAssessmentAddressType(), - streetName = it.address1, - district = it.address2, - town = it.address3, - county = listOfNotNull(it.address4, it.address5).joinToString(", ") + postcode = deliveryPointAddress.postcode, + notes = "UPRN: ${deliveryPointAddress.uprn}", + buildingName = listOfNotNull( + deliveryPointAddress.subBuildingName, + deliveryPointAddress.buildingName + ).joinToString(" "), + addressNumber = deliveryPointAddress.buildingNumber?.toString(), + streetName = deliveryPointAddress.thoroughfareName, + town = deliveryPointAddress.postTown, + district = deliveryPointAddress.localCustodianCodeDescription ) ) + } else { + addressInfo?.takeIf { it.containsInformation() }?.let { + insertAddress( + PersonAddress( + id = null, + start = LocalDate.now(), + status = referenceDataRepository.mainAddressStatus(), + person = savedPerson, + postcode = it.postcode, + type = referenceDataRepository.awaitingAssessmentAddressType(), + streetName = it.address1, + district = it.address2, + town = it.address3, + county = listOfNotNull(it.address4, it.address5).joinToString(", ") + ) + ) + } } + audit["offenderId"] = savedPerson.id + InsertPersonResult(savedPerson, savedManager, savedEquality, savedAddress) } - return InsertPersonResult(savedPerson, savedManager, savedEquality, savedAddress) - } - fun insertAddress(address: PersonAddress): PersonAddress = - if (featureFlags.enabled("common-platform-record-creation-toggle")) { - audit(BusinessInteractionCode.INSERT_ADDRESS) { audit -> - val result = personAddressRepository.save(address) - audit["offenderId"] = result.person.id!! - result - } - } else { - address - } + fun insertAddress(address: PersonAddress): PersonAddress = audit(BusinessInteractionCode.INSERT_ADDRESS) { audit -> + val savedAddress = personAddressRepository.save(address) + audit["addressId"] = address.id!! + savedAddress + } fun generateCrn(): String { return personRepository.getNextCrn() 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 2a9701d1d..c739b4edb 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 @@ -126,23 +126,14 @@ internal class HandlerTest { @Test fun `Simulated person created logged when feature flag disabled`() { probationSearchMatchNotFound() - whenever(featureFlags.enabled("common-platform-record-creation-toggle")).thenReturn(false) - 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) verify(telemetryService).trackEvent(eq("SimulatedPersonCreated"), anyMap(), anyMap()) - verify(personService).insertPerson(any(), any()) + verify(personService, never()).insertPerson(any(), any()) verify(notifier, never()).caseCreated(any()) verify(notifier, never()).addressCreated(any()) }