From 2bcb7689ccd342d49f5ac6ab2667b3f1689eded3 Mon Sep 17 00:00:00 2001 From: stevomcallister <78762879+stevomcallister@users.noreply.github.com> Date: Tue, 31 Oct 2023 16:41:51 +0000 Subject: [PATCH] PI-1602 additional fix for duplicate main addresses (#2475) --- .../justice/digital/hmpps/CASIntegrationTest.kt | 4 ++-- .../hmpps/integrations/delius/AddressService.kt | 11 ++++++++--- .../hmpps/integrations/delius/entity/Person.kt | 17 ++++++++++++----- 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/projects/cas3-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/CASIntegrationTest.kt b/projects/cas3-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/CASIntegrationTest.kt index 9e60e97d80..8c2cac103b 100644 --- a/projects/cas3-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/CASIntegrationTest.kt +++ b/projects/cas3-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/CASIntegrationTest.kt @@ -145,7 +145,7 @@ internal class CASIntegrationTest { MatcherAssert.assertThat(contact!!.type.code, Matchers.equalTo("EAAR")) - val person = personRepository.findByCrnAndSoftDeletedIsFalse(event.message.crn()) + val person = personRepository.findByCrn(event.message.crn()) val address = addressRepository.findMainAddress(person!!.id) MatcherAssert.assertThat(address!!.type.code, Matchers.equalTo("A17")) @@ -170,7 +170,7 @@ internal class CASIntegrationTest { val contact = contactRepository.getByExternalReference(eventDetails.eventDetails.urn) MatcherAssert.assertThat(contact!!.type.code, Matchers.equalTo("EADP")) - val person = personRepository.findByCrnAndSoftDeletedIsFalse(event.message.crn()) + val person = personRepository.findByCrn(event.message.crn()) val address = addressRepository.findAll().filter { it.personId == person?.id }[0] MatcherAssert.assertThat(address!!.status.code, Matchers.equalTo("P")) } diff --git a/projects/cas3-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/AddressService.kt b/projects/cas3-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/AddressService.kt index 61f58dd123..e83c7629b7 100644 --- a/projects/cas3-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/AddressService.kt +++ b/projects/cas3-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/AddressService.kt @@ -7,8 +7,10 @@ import uk.gov.justice.digital.hmpps.integrations.delius.entity.AddressTypeCode import uk.gov.justice.digital.hmpps.integrations.delius.entity.Person import uk.gov.justice.digital.hmpps.integrations.delius.entity.PersonAddress import uk.gov.justice.digital.hmpps.integrations.delius.entity.PersonAddressRepository +import uk.gov.justice.digital.hmpps.integrations.delius.entity.PersonRepository import uk.gov.justice.digital.hmpps.integrations.delius.entity.ReferenceDataRepository import uk.gov.justice.digital.hmpps.integrations.delius.entity.cas3AddressType +import uk.gov.justice.digital.hmpps.integrations.delius.entity.getByIdForUpdate import uk.gov.justice.digital.hmpps.integrations.delius.entity.mainAddressStatus import uk.gov.justice.digital.hmpps.integrations.delius.entity.previousAddressStatus import java.time.LocalDate @@ -18,7 +20,8 @@ import java.time.ZonedDateTime @Transactional class AddressService( private val personAddressRepository: PersonAddressRepository, - private val referenceDataRepository: ReferenceDataRepository + private val referenceDataRepository: ReferenceDataRepository, + private val personRepository: PersonRepository ) { fun updateMainAddress(person: Person, details: PersonArrived) { endMainAddress(person, details.arrivedAt.toLocalDate()) @@ -26,7 +29,8 @@ class AddressService( } fun endMainAddress(person: Person, endDate: LocalDate) { - val currentMain = personAddressRepository.findMainAddress(person.id) + val personForUpdate = personRepository.getByIdForUpdate(person.id) + val currentMain = personAddressRepository.findMainAddress(personForUpdate.id) currentMain?.apply { val previousStatus = referenceDataRepository.previousAddressStatus() currentMain.status = previousStatus @@ -35,7 +39,8 @@ class AddressService( } fun endMainCAS3Address(person: Person, endDate: ZonedDateTime) { - val currentMain = personAddressRepository.findMainAddress(person.id) + val personForUpdate = personRepository.getByIdForUpdate(person.id) + val currentMain = personAddressRepository.findMainAddress(personForUpdate.id) currentMain?.apply { if (currentMain.type.code == AddressTypeCode.CAS3.code) { val previousStatus = referenceDataRepository.previousAddressStatus() diff --git a/projects/cas3-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/entity/Person.kt b/projects/cas3-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/entity/Person.kt index 11d981ca34..35b95bf391 100644 --- a/projects/cas3-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/entity/Person.kt +++ b/projects/cas3-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/entity/Person.kt @@ -3,14 +3,19 @@ package uk.gov.justice.digital.hmpps.integrations.delius.entity import jakarta.persistence.Column import jakarta.persistence.Entity import jakarta.persistence.Id +import jakarta.persistence.LockModeType import jakarta.persistence.Table import org.hibernate.annotations.Immutable +import org.hibernate.annotations.Where import org.springframework.data.jpa.repository.JpaRepository +import org.springframework.data.jpa.repository.Lock import uk.gov.justice.digital.hmpps.exception.NotFoundException +import java.util.Optional @Immutable @Entity @Table(name = "offender") +@Where(clause = "soft_deleted = 0") class Person( @Column(columnDefinition = "char(7)") @@ -29,12 +34,14 @@ class Person( interface PersonRepository : JpaRepository { - fun findByCrnAndSoftDeletedIsFalse(crn: String): Person? - fun findByNomsNumberAndSoftDeletedIsFalse(nomsNumber: String): Person? + fun findByCrn(crn: String): Person? + + @Lock(LockModeType.PESSIMISTIC_READ) + override fun findById(personId: Long): Optional } fun PersonRepository.getByCrn(crn: String) = - findByCrnAndSoftDeletedIsFalse(crn) ?: throw NotFoundException("Person", "crn", crn) + findByCrn(crn) ?: throw NotFoundException("Person", "crn", crn) -fun PersonRepository.getByNoms(noms: String) = - findByNomsNumberAndSoftDeletedIsFalse(noms) ?: throw NotFoundException("Person", "noms", noms) +fun PersonRepository.getByIdForUpdate(personId: Long) = + findById(personId).orElseThrow { NotFoundException("Person", "id", personId) }