From 4d7d0b2db7cca13387c79cebdab37a006cf7d559 Mon Sep 17 00:00:00 2001 From: achimber-moj <161360519+achimber-moj@users.noreply.github.com> Date: Tue, 11 Jun 2024 10:36:05 +0100 Subject: [PATCH] PI-2258 prison custody status to delius transaction not rolling back (#3890) * PI-2258 replicate transaction rollback error Signed-off-by: Amardeep Chimber * PI-2258 move transaction annotation to handler and update tests Signed-off-by: Amardeep Chimber * PI-2258 undo change to dev queue timeout value Signed-off-by: Amardeep Chimber * PI-2258 move transaction rollback test in a separate file Signed-off-by: Amardeep Chimber * Formatting changes * Empty-Commit * PI-2258 refactor test attribute names Signed-off-by: Amardeep Chimber --------- Signed-off-by: Amardeep Chimber Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .../justice/digital/hmpps/data/DataLoader.kt | 55 +++++++++++++++++-- .../hmpps/data/generator/BookingGenerator.kt | 5 ++ .../data/generator/InstitutionGenerator.kt | 1 + .../data/generator/NotificationGenerator.kt | 1 + .../hmpps/data/generator/PersonGenerator.kt | 1 + .../data/generator/ProbationAreaGenerator.kt | 5 +- .../data/generator/ReferenceDataGenerator.kt | 4 ++ .../messages/prisoner-matched-with-pom.json | 17 ++++++ ...PcstdIntegrationTransactionRollbackTest.kt | 39 +++++++++++++ .../hmpps/messaging/ActionProcessor.kt | 2 - .../digital/hmpps/messaging/Handler.kt | 2 + 11 files changed, 123 insertions(+), 9 deletions(-) create mode 100644 projects/prison-custody-status-to-delius/src/dev/resources/messages/prisoner-matched-with-pom.json create mode 100644 projects/prison-custody-status-to-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/PcstdIntegrationTransactionRollbackTest.kt diff --git a/projects/prison-custody-status-to-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/DataLoader.kt b/projects/prison-custody-status-to-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/DataLoader.kt index 51e603da55..520cf7b76c 100644 --- a/projects/prison-custody-status-to-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/DataLoader.kt +++ b/projects/prison-custody-status-to-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/DataLoader.kt @@ -22,6 +22,8 @@ import uk.gov.justice.digital.hmpps.integrations.delius.licencecondition.entity. import uk.gov.justice.digital.hmpps.integrations.delius.licencecondition.entity.LicenceConditionRepository import uk.gov.justice.digital.hmpps.integrations.delius.person.entity.Person import uk.gov.justice.digital.hmpps.integrations.delius.person.entity.PersonRepository +import uk.gov.justice.digital.hmpps.integrations.delius.person.manager.prison.entity.PrisonManager +import uk.gov.justice.digital.hmpps.integrations.delius.person.manager.prison.entity.PrisonManagerRepository import uk.gov.justice.digital.hmpps.integrations.delius.person.manager.probation.entity.PersonManagerRepository import uk.gov.justice.digital.hmpps.integrations.delius.probationarea.institution.entity.InstitutionRepository import uk.gov.justice.digital.hmpps.integrations.delius.recall.entity.RecallReasonRepository @@ -34,6 +36,7 @@ import uk.gov.justice.digital.hmpps.integrations.delius.staff.entity.StaffReposi import uk.gov.justice.digital.hmpps.integrations.delius.team.entity.TeamRepository import uk.gov.justice.digital.hmpps.user.AuditUser import uk.gov.justice.digital.hmpps.user.AuditUserRepository +import java.time.ZoneId import java.time.ZonedDateTime @Component @@ -60,7 +63,8 @@ class DataLoader( private val teamRepository: TeamRepository, private val probationAreaRepository: ProbationAreaRepository, private val licenceConditionRepository: LicenceConditionRepository, - private val licenceConditionCategoryRepository: LicenceConditionCategoryRepository + private val licenceConditionCategoryRepository: LicenceConditionCategoryRepository, + private val prisonManagerRepository: PrisonManagerRepository, ) : ApplicationListener { @PostConstruct @@ -102,7 +106,8 @@ class DataLoader( ReferenceDataGenerator.PERSON_MANAGER_ALLOCATION_REASON.set, ReferenceDataGenerator.PRISON_MANAGER_ALLOCATION_REASON.set, ReferenceDataSetGenerator.ACCEPTED_DECISION, - ReferenceDataSetGenerator.LICENCE_AREA_TRANSFER_REJECTION_REASON + ReferenceDataSetGenerator.LICENCE_AREA_TRANSFER_REJECTION_REASON, + ReferenceDataSetGenerator.AUTO_TRANSFER_REASON ) ) referenceDataRepository.saveAll( @@ -115,15 +120,53 @@ class DataLoader( ReferenceDataGenerator.PRISON_MANAGER_ALLOCATION_REASON, ReferenceDataGenerator.LICENCE_CONDITION_TERMINATION_REASON, ReferenceDataGenerator.LC_REJECTED_DECISION, - ReferenceDataGenerator.LC_REJECTED_REASON + ReferenceDataGenerator.LC_REJECTED_REASON, + ReferenceDataGenerator.AUTO_TRANSFER ) ) recallReasonRepository.saveAll(ReferenceDataGenerator.RECALL_REASON.values) contactTypeRepository.saveAll(ReferenceDataGenerator.CONTACT_TYPE.values) - institutionRepository.saveAll(listOf(InstitutionGenerator.DEFAULT, InstitutionGenerator.MOVED_TO)) - probationAreaRepository.save(InstitutionGenerator.DEFAULT.probationArea!!) + institutionRepository.saveAll( + listOf( + InstitutionGenerator.DEFAULT, + InstitutionGenerator.MOVED_TO, + InstitutionGenerator.MOVED_TO_WITH_POM + ) + ) + probationAreaRepository.saveAll( + listOf( + InstitutionGenerator.DEFAULT.probationArea!!, + InstitutionGenerator.MOVED_TO_WITH_POM.probationArea!! + ) + ) val team = teamRepository.save(TeamGenerator.allStaff(InstitutionGenerator.DEFAULT.probationArea!!)) + val teamBir = + teamRepository.save(TeamGenerator.allStaff(InstitutionGenerator.MOVED_TO_WITH_POM.probationArea!!)) + val prisonManager = PrisonManager( + IdGenerator.getAndIncrement(), + 0, + PersonGenerator.MATCHABLE_WITH_POM.id, + ZonedDateTime.of(2023, 1, 1, 1, 0, 0, 0, ZoneId.systemDefault()), + ReferenceDataGenerator.AUTO_TRANSFER, + StaffGenerator.UNALLOCATED, + teamBir, + InstitutionGenerator.MOVED_TO_WITH_POM.probationArea!!, + false + ) + val prisonManager1 = PrisonManager( + IdGenerator.getAndIncrement(), + 0, + PersonGenerator.MATCHABLE_WITH_POM.id, + ZonedDateTime.of(2023, 2, 1, 1, 0, 0, 0, ZoneId.systemDefault()), + ReferenceDataGenerator.AUTO_TRANSFER, + StaffGenerator.UNALLOCATED, + teamBir, + InstitutionGenerator.MOVED_TO_WITH_POM.probationArea!!, + false + ) + prisonManagerRepository.saveAll(listOf(prisonManager, prisonManager1)) staffRepository.save(StaffGenerator.unallocated(team)) + staffRepository.save(StaffGenerator.unallocated(teamBir)) institutionRepository.saveAll(InstitutionGenerator.STANDARD_INSTITUTIONS.values) probationAreaRepository.saveAll(InstitutionGenerator.STANDARD_INSTITUTIONS.values.mapNotNull { it.probationArea }) val teams = teamRepository.saveAll( @@ -163,6 +206,8 @@ class DataLoader( private fun createMatchablePerson() { createPerson(PersonGenerator.MATCHABLE) createEvent(EventGenerator.custodialEvent(PersonGenerator.MATCHABLE, InstitutionGenerator.DEFAULT)) + createPerson(PersonGenerator.MATCHABLE_WITH_POM) + createEvent(EventGenerator.custodialEvent(PersonGenerator.MATCHABLE_WITH_POM, InstitutionGenerator.DEFAULT)) } private fun createNewCustodyPerson() { diff --git a/projects/prison-custody-status-to-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/BookingGenerator.kt b/projects/prison-custody-status-to-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/BookingGenerator.kt index 23310f1adf..24892d469e 100644 --- a/projects/prison-custody-status-to-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/BookingGenerator.kt +++ b/projects/prison-custody-status-to-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/BookingGenerator.kt @@ -13,6 +13,11 @@ object BookingGenerator { "INT", prisonId = InstitutionGenerator.MOVED_TO.nomisCdeCode!! ) + val MATCHED_WITH_POM = generateReceive( + PersonGenerator.MATCHABLE_WITH_POM.nomsNumber, + "INT", + prisonId = InstitutionGenerator.MOVED_TO_WITH_POM.nomisCdeCode!! + ) val NEW_CUSTODY = generateReceive(PersonGenerator.NEW_CUSTODY.nomsNumber, "N") val RECALLED = generateReceive(PersonGenerator.RECALLED.nomsNumber, "24") val HOSPITAL_RELEASE = generateRelease(PersonGenerator.HOSPITAL_RELEASED.nomsNumber, "HO") diff --git a/projects/prison-custody-status-to-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/InstitutionGenerator.kt b/projects/prison-custody-status-to-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/InstitutionGenerator.kt index 7a40af7f57..7c34ffc06d 100644 --- a/projects/prison-custody-status-to-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/InstitutionGenerator.kt +++ b/projects/prison-custody-status-to-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/InstitutionGenerator.kt @@ -8,6 +8,7 @@ object InstitutionGenerator { val DEFAULT = generate("WSIHMP", "WSI") val STANDARD_INSTITUTIONS = InstitutionCode.entries.associateWith { generate(it.code, null) } val MOVED_TO = generate("SWIHMP", "SWI") + val MOVED_TO_WITH_POM = generate("BIRHMP", "BIR") fun generate(code: String, prisonId: String?): Institution { val institution = Institution( diff --git a/projects/prison-custody-status-to-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/NotificationGenerator.kt b/projects/prison-custody-status-to-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/NotificationGenerator.kt index db1d7611e0..83209304ed 100644 --- a/projects/prison-custody-status-to-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/NotificationGenerator.kt +++ b/projects/prison-custody-status-to-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/NotificationGenerator.kt @@ -8,6 +8,7 @@ object NotificationGenerator { val PRISONER_RECEIVED = ResourceLoader.notification("prisoner-received") val PRISONER_DIED = ResourceLoader.notification("prisoner-died") val PRISONER_MATCHED = ResourceLoader.notification("prisoner-matched") + val PRISONER_MATCHED_WITH_POM = ResourceLoader.notification("prisoner-matched-with-pom") val PRISONER_NEW_CUSTODY = ResourceLoader.notification("prisoner-received-new-custody") val PRISONER_RECALLED = ResourceLoader.notification("prisoner-received-recalled") val PRISONER_HOSPITAL_RELEASED = diff --git a/projects/prison-custody-status-to-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/PersonGenerator.kt b/projects/prison-custody-status-to-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/PersonGenerator.kt index df774639df..cfcb370057 100644 --- a/projects/prison-custody-status-to-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/PersonGenerator.kt +++ b/projects/prison-custody-status-to-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/PersonGenerator.kt @@ -8,6 +8,7 @@ object PersonGenerator { val RECALLABLE = generate(NotificationGenerator.PRISONER_RECEIVED.nomsId()) val DIED = generate(NotificationGenerator.PRISONER_DIED.nomsId()) val MATCHABLE = generate(NotificationGenerator.PRISONER_MATCHED.nomsId()) + val MATCHABLE_WITH_POM = generate(NotificationGenerator.PRISONER_MATCHED_WITH_POM.nomsId()) val NEW_CUSTODY = generate(NotificationGenerator.PRISONER_NEW_CUSTODY.nomsId()) val RECALLED = generate(NotificationGenerator.PRISONER_RECALLED.nomsId()) val HOSPITAL_RELEASED = generate(NotificationGenerator.PRISONER_HOSPITAL_RELEASED.nomsId()) diff --git a/projects/prison-custody-status-to-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/ProbationAreaGenerator.kt b/projects/prison-custody-status-to-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/ProbationAreaGenerator.kt index 38d5ea8f23..f9b50d722d 100644 --- a/projects/prison-custody-status-to-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/ProbationAreaGenerator.kt +++ b/projects/prison-custody-status-to-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/ProbationAreaGenerator.kt @@ -7,6 +7,7 @@ object ProbationAreaGenerator { fun generate( code: String, - description: String = "description for $code" - ) = ProbationArea(IdGenerator.getAndIncrement(), code, description) + description: String = "description for $code", + + ) = ProbationArea(IdGenerator.getAndIncrement(), code, description) } diff --git a/projects/prison-custody-status-to-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/ReferenceDataGenerator.kt b/projects/prison-custody-status-to-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/ReferenceDataGenerator.kt index adfc2a4b55..aa670ea178 100644 --- a/projects/prison-custody-status-to-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/ReferenceDataGenerator.kt +++ b/projects/prison-custody-status-to-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/ReferenceDataGenerator.kt @@ -1,6 +1,7 @@ package uk.gov.justice.digital.hmpps.data.generator import uk.gov.justice.digital.hmpps.data.generator.ReferenceDataSetGenerator.ACCEPTED_DECISION +import uk.gov.justice.digital.hmpps.data.generator.ReferenceDataSetGenerator.AUTO_TRANSFER_REASON import uk.gov.justice.digital.hmpps.data.generator.ReferenceDataSetGenerator.LICENCE_AREA_TRANSFER_REJECTION_REASON import uk.gov.justice.digital.hmpps.integrations.delius.contact.entity.ContactType import uk.gov.justice.digital.hmpps.integrations.delius.recall.entity.RecallReason @@ -42,6 +43,8 @@ object ReferenceDataGenerator { val LC_REJECTED_DECISION = generate("R", ACCEPTED_DECISION) val LC_REJECTED_REASON = generate("TWR", LICENCE_AREA_TRANSFER_REJECTION_REASON) + val AUTO_TRANSFER = generate("AUT", AUTO_TRANSFER_REASON) + fun generate( code: String, dataset: ReferenceDataSet, @@ -57,6 +60,7 @@ object ReferenceDataSetGenerator { val TRANSFER_STATUS = generate("TRANSFER STATUS") val ACCEPTED_DECISION = generate("ACCEPTED DECISION") val LICENCE_AREA_TRANSFER_REJECTION_REASON = generate("LICENCE AREA TRANSFER REJECTION REASON") + val AUTO_TRANSFER_REASON = generate("Automatic Transfer") fun generate(name: String, id: Long = IdGenerator.getAndIncrement()) = ReferenceDataSet(id, name) } diff --git a/projects/prison-custody-status-to-delius/src/dev/resources/messages/prisoner-matched-with-pom.json b/projects/prison-custody-status-to-delius/src/dev/resources/messages/prisoner-matched-with-pom.json new file mode 100644 index 0000000000..91b568e771 --- /dev/null +++ b/projects/prison-custody-status-to-delius/src/dev/resources/messages/prisoner-matched-with-pom.json @@ -0,0 +1,17 @@ +{ + "Type": "Notification", + "MessageId": "b11f8b6c-a7bc-4a3e-af9c-3e4870924eaa", + "TopicArn": "", + "Message": "{\"eventType\":\"probation-case.prison-identifier.added\",\"version\":1,\"occurredAt\":\"2023-07-31T09:26:39+01:00\",\"publishedAt\":\"2023-07-31T09:26:39.362Z+01:00\",\"description\":\"A prisoner identifier has been added\",\"personReference\":{\"identifiers\":[{\"type\":\"NOMS\",\"value\":\"B5295DZ\"}]}}", + "Timestamp": "2023-07-31T09:26:39.362Z", + "SignatureVersion": "1", + "Signature": "", + "SigningCertURL": "", + "UnsubscribeURL": "", + "MessageAttributes": { + "eventType": { + "Type": "String", + "Value": "probation-case.prison-identifier.added" + } + } +} \ No newline at end of file diff --git a/projects/prison-custody-status-to-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/PcstdIntegrationTransactionRollbackTest.kt b/projects/prison-custody-status-to-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/PcstdIntegrationTransactionRollbackTest.kt new file mode 100644 index 0000000000..4fbd20c9f2 --- /dev/null +++ b/projects/prison-custody-status-to-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/PcstdIntegrationTransactionRollbackTest.kt @@ -0,0 +1,39 @@ +package uk.gov.justice.digital.hmpps + +import org.hamcrest.MatcherAssert.assertThat +import org.hamcrest.Matchers.equalTo +import org.junit.jupiter.api.Assertions.assertTrue +import org.junit.jupiter.api.Test +import org.springframework.test.context.TestPropertySource +import uk.gov.justice.digital.hmpps.data.generator.BookingGenerator +import uk.gov.justice.digital.hmpps.data.generator.InstitutionGenerator +import uk.gov.justice.digital.hmpps.data.generator.NotificationGenerator +import uk.gov.justice.digital.hmpps.data.generator.PersonGenerator + +@TestPropertySource(properties = ["logging.level.org.springframework.transaction=DEBUG", "logging.level.org.hibernate.engine.transaction.internal.TransactionImpl=DEBUG"]) +class PcstdIntegrationTransactionRollbackTest : PcstdIntegrationTestBase() { + private val releaseOnLicence = "Released on Licence" + + @Test + fun `when a prisoner is matched with more than one pom`() { + + val notification = NotificationGenerator.PRISONER_MATCHED_WITH_POM + val person = PersonGenerator.MATCHABLE_WITH_POM + withBooking( + BookingGenerator.MATCHED_WITH_POM, + BookingGenerator.MATCHED_WITH_POM.lastMovement(notification.message.occurredAt) + ) + val before = getCustody(person.nomsNumber) + assertThat(before.institution?.code, equalTo(InstitutionGenerator.DEFAULT.code)) + + channelManager.getChannel(queueName).publishAndWait(notification) + + val custody = getCustody(person.nomsNumber) + assertTrue(custody.isInCustody()) + assertThat(custody.institution?.code, equalTo(InstitutionGenerator.DEFAULT.code)) + + verifyCustodyHistory( + custody + ) + } +} diff --git a/projects/prison-custody-status-to-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/messaging/ActionProcessor.kt b/projects/prison-custody-status-to-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/messaging/ActionProcessor.kt index 3735888449..42edb35cce 100644 --- a/projects/prison-custody-status-to-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/messaging/ActionProcessor.kt +++ b/projects/prison-custody-status-to-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/messaging/ActionProcessor.kt @@ -1,7 +1,6 @@ package uk.gov.justice.digital.hmpps.messaging import org.springframework.stereotype.Service -import org.springframework.transaction.annotation.Transactional import uk.gov.justice.digital.hmpps.exception.IgnorableMessageException import uk.gov.justice.digital.hmpps.integrations.delius.event.EventService @@ -9,7 +8,6 @@ import uk.gov.justice.digital.hmpps.integrations.delius.event.EventService class ActionProcessor(actionsList: List, private val eventService: EventService) { private val actions = actionsList.associateBy { it.name } - @Transactional(noRollbackFor = [IgnorableMessageException::class]) fun processActions(prisonerMovement: PrisonerMovement, actionNames: List): List = try { eventService.getActiveCustodialEvents(prisonerMovement.nomsId) diff --git a/projects/prison-custody-status-to-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/messaging/Handler.kt b/projects/prison-custody-status-to-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/messaging/Handler.kt index 7e27f907af..3e95ce2788 100644 --- a/projects/prison-custody-status-to-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/messaging/Handler.kt +++ b/projects/prison-custody-status-to-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/messaging/Handler.kt @@ -1,6 +1,7 @@ package uk.gov.justice.digital.hmpps.messaging import org.springframework.stereotype.Component +import org.springframework.transaction.annotation.Transactional import uk.gov.justice.digital.hmpps.converter.NotificationConverter import uk.gov.justice.digital.hmpps.datetime.EuropeLondon import uk.gov.justice.digital.hmpps.exception.IgnorableMessageException @@ -16,6 +17,7 @@ import uk.gov.justice.digital.hmpps.telemetry.TelemetryService import java.time.ZonedDateTime @Component +@Transactional(noRollbackFor = [IgnorableMessageException::class]) class Handler( configContainer: PrisonerMovementConfigs, private val featureFlags: FeatureFlags,