From f9d93c93b18cd8290c97e69053085643f8b6a9ae Mon Sep 17 00:00:00 2001 From: davidatkinsuk Date: Mon, 6 Jan 2025 09:55:22 +0000 Subject: [PATCH 1/3] Move logic from Booking to Space Booking for reuse MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit extracts the logic used to extract ‘Management Info’ from delius booking imports into a common service such that it can be reused for a new seed jobs that creates `SpaceBooking` for delius referrals that don’t have an existing booking in CAS1. --- .../cas1/Cas1BookingManagementInfoService.kt | 86 +++++++++++++++++++ .../cas1/Cas1BookingToSpaceBookingSeedJob.kt | 84 ++---------------- .../Cas1BookingToSpaceBookingSeedJobTest.kt | 8 +- 3 files changed, 94 insertions(+), 84 deletions(-) create mode 100644 src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/seed/cas1/Cas1BookingManagementInfoService.kt diff --git a/src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/seed/cas1/Cas1BookingManagementInfoService.kt b/src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/seed/cas1/Cas1BookingManagementInfoService.kt new file mode 100644 index 0000000000..4928ae88b1 --- /dev/null +++ b/src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/seed/cas1/Cas1BookingManagementInfoService.kt @@ -0,0 +1,86 @@ +package uk.gov.justice.digital.hmpps.approvedpremisesapi.seed.cas1 + +import org.springframework.stereotype.Service +import uk.gov.justice.digital.hmpps.approvedpremisesapi.api.model.ServiceName +import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.BookingEntity +import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.DepartureReasonEntity +import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.DepartureReasonRepository +import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.ManagementInfoSource +import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.MoveOnCategoryEntity +import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.MoveOnCategoryRepository +import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.NonArrivalReasonEntity +import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.NonArrivalReasonRepository +import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.cas1.Cas1DeliusBookingImportEntity +import uk.gov.justice.digital.hmpps.approvedpremisesapi.util.toLocalDate +import uk.gov.justice.digital.hmpps.approvedpremisesapi.util.toLocalDateTime +import java.time.LocalDate +import java.time.LocalTime +import java.time.OffsetDateTime + +@Service +class Cas1BookingManagementInfoService( + private val departureReasonRepository: DepartureReasonRepository, + private val moveOnCategoryRepository: MoveOnCategoryRepository, + private val nonArrivalReasonReasonEntity: NonArrivalReasonRepository, +) { + + fun fromBooking(booking: BookingEntity) = ManagementInfo( + source = ManagementInfoSource.LEGACY_CAS_1, + arrivedAtDate = booking.arrival?.arrivalDateTime?.toLocalDate(), + arrivedAtTime = booking.arrival?.arrivalDateTime?.toLocalDateTime()?.toLocalTime(), + departedAtDate = booking.departure?.dateTime?.toLocalDate(), + departedAtTime = booking.departure?.dateTime?.toLocalDateTime()?.toLocalTime(), + keyWorkerStaffCode = null, + keyWorkerName = null, + departureReason = booking.departure?.reason, + departureMoveOnCategory = booking.departure?.moveOnCategory, + departureNotes = booking.departure?.notes, + nonArrivalConfirmedAt = booking.nonArrival?.createdAt, + nonArrivalReason = booking.nonArrival?.reason, + nonArrivalNotes = booking.nonArrival?.notes, + ) + + fun fromDeliusBookingImport(import: Cas1DeliusBookingImportEntity) = ManagementInfo( + source = ManagementInfoSource.DELIUS, + arrivedAtDate = import.arrivalDate, + arrivedAtTime = null, + departedAtDate = import.departureDate, + departedAtTime = null, + keyWorkerStaffCode = import.keyWorkerStaffCode, + keyWorkerName = import.keyWorkerStaffCode?.let { "${import.keyWorkerForename} ${import.keyWorkerSurname}" }, + departureReason = import.departureReasonCode?.let { reasonCode -> + departureReasonRepository + .findAllByServiceScope(ServiceName.approvedPremises.value) + .filter { it.legacyDeliusReasonCode == reasonCode } + .maxByOrNull { it.isActive } + ?: error("Could not resolve DepartureReason for code $reasonCode") + }, + departureMoveOnCategory = import.moveOnCategoryCode?.let { reasonCode -> + moveOnCategoryRepository + .findAllByServiceScope(ServiceName.approvedPremises.value) + .firstOrNull { it.legacyDeliusCategoryCode == reasonCode } ?: error("Could not resolve MoveOnCategory for code $reasonCode") + }, + departureNotes = null, + nonArrivalConfirmedAt = import.nonArrivalContactDatetime, + nonArrivalReason = import.nonArrivalReasonCode?.let { + nonArrivalReasonReasonEntity.findByLegacyDeliusReasonCode(it) ?: error("Could not resolve NonArrivalReason for code $it") + }, + nonArrivalNotes = import.nonArrivalNotes, + ) +} + +data class ManagementInfo( + val source: ManagementInfoSource, + val arrivedAtDate: LocalDate?, + val arrivedAtTime: LocalTime?, + val departedAtDate: LocalDate?, + val departedAtTime: LocalTime?, + val keyWorkerStaffCode: String?, + val keyWorkerName: String?, + val departureReason: DepartureReasonEntity?, + val departureMoveOnCategory: MoveOnCategoryEntity?, + val departureNotes: String?, + val nonArrivalConfirmedAt: OffsetDateTime?, + val nonArrivalReason: NonArrivalReasonEntity?, + val nonArrivalNotes: String?, +) diff --git a/src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/seed/cas1/Cas1BookingToSpaceBookingSeedJob.kt b/src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/seed/cas1/Cas1BookingToSpaceBookingSeedJob.kt index 268fcd29ad..a66b07822f 100644 --- a/src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/seed/cas1/Cas1BookingToSpaceBookingSeedJob.kt +++ b/src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/seed/cas1/Cas1BookingToSpaceBookingSeedJob.kt @@ -5,7 +5,6 @@ import org.springframework.data.repository.findByIdOrNull import org.springframework.stereotype.Component import org.springframework.transaction.support.TransactionTemplate import uk.gov.justice.digital.hmpps.approvedpremisesapi.api.events.cas1.model.BookingMadeEnvelope -import uk.gov.justice.digital.hmpps.approvedpremisesapi.api.model.ServiceName import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.ApprovedPremisesApplicationEntity import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.ApprovedPremisesEntity import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.ApprovedPremisesRepository @@ -13,29 +12,16 @@ import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.BookingEntity import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.BookingRepository import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.Cas1SpaceBookingEntity import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.Cas1SpaceBookingRepository -import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.DepartureReasonEntity -import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.DepartureReasonRepository import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.DomainEventRepository import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.DomainEventType -import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.ManagementInfoSource -import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.MoveOnCategoryEntity -import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.MoveOnCategoryRepository -import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.NonArrivalReasonEntity -import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.NonArrivalReasonRepository import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.PlacementRequestRepository import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.UserEntity import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.UserRepository -import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.cas1.Cas1DeliusBookingImportEntity import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.cas1.Cas1DeliusBookingImportRepository import uk.gov.justice.digital.hmpps.approvedpremisesapi.model.DomainEvent import uk.gov.justice.digital.hmpps.approvedpremisesapi.seed.SeedJob import uk.gov.justice.digital.hmpps.approvedpremisesapi.service.EnvironmentService import uk.gov.justice.digital.hmpps.approvedpremisesapi.service.cas1.Cas1DomainEventService -import uk.gov.justice.digital.hmpps.approvedpremisesapi.util.toLocalDate -import uk.gov.justice.digital.hmpps.approvedpremisesapi.util.toLocalDateTime -import java.time.LocalDate -import java.time.LocalTime -import java.time.OffsetDateTime import java.util.UUID @Component @@ -49,9 +35,7 @@ class Cas1BookingToSpaceBookingSeedJob( private val userRepository: UserRepository, private val transactionTemplate: TransactionTemplate, private val cas1DeliusBookingImportRepository: Cas1DeliusBookingImportRepository, - private val departureReasonRepository: DepartureReasonRepository, - private val moveOnCategoryRepository: MoveOnCategoryRepository, - private val nonArrivalReasonReasonEntity: NonArrivalReasonRepository, + private val cas1BookingManagementInfoService: Cas1BookingManagementInfoService, private val environmentService: EnvironmentService, private val placementRequestRepository: PlacementRequestRepository, ) : SeedJob( @@ -181,69 +165,13 @@ class Cas1BookingToSpaceBookingSeedJob( log.warn("Could not retrieve referral details from delius import for booking ${booking.id}") } - return deliusImport?.toManagementInfo() ?: booking.toManagementInfo() + return if (deliusImport != null) { + cas1BookingManagementInfoService.fromDeliusBookingImport(deliusImport) + } else { + cas1BookingManagementInfoService.fromBooking(booking) + } } - private fun Cas1DeliusBookingImportEntity.toManagementInfo() = ManagementInfo( - source = ManagementInfoSource.DELIUS, - arrivedAtDate = arrivalDate, - arrivedAtTime = null, - departedAtDate = departureDate, - departedAtTime = null, - keyWorkerStaffCode = keyWorkerStaffCode, - keyWorkerName = keyWorkerStaffCode?.let { "$keyWorkerForename $keyWorkerSurname" }, - departureReason = departureReasonCode?.let { reasonCode -> - departureReasonRepository - .findAllByServiceScope(ServiceName.approvedPremises.value) - .filter { it.legacyDeliusReasonCode == reasonCode } - .maxByOrNull { it.isActive } - ?: error("Could not resolve DepartureReason for code $reasonCode") - }, - departureMoveOnCategory = moveOnCategoryCode?.let { reasonCode -> - moveOnCategoryRepository - .findAllByServiceScope(ServiceName.approvedPremises.value) - .firstOrNull { it.legacyDeliusCategoryCode == reasonCode } ?: error("Could not resolve MoveOnCategory for code $reasonCode") - }, - departureNotes = null, - nonArrivalConfirmedAt = nonArrivalContactDatetime, - nonArrivalReason = nonArrivalReasonCode?.let { - nonArrivalReasonReasonEntity.findByLegacyDeliusReasonCode(it) ?: error("Could not resolve NonArrivalReason for code $it") - }, - nonArrivalNotes = nonArrivalNotes, - ) - - private fun BookingEntity.toManagementInfo() = ManagementInfo( - source = ManagementInfoSource.LEGACY_CAS_1, - arrivedAtDate = arrival?.arrivalDateTime?.toLocalDate(), - arrivedAtTime = arrival?.arrivalDateTime?.toLocalDateTime()?.toLocalTime(), - departedAtDate = departure?.dateTime?.toLocalDate(), - departedAtTime = departure?.dateTime?.toLocalDateTime()?.toLocalTime(), - keyWorkerStaffCode = null, - keyWorkerName = null, - departureReason = departure?.reason, - departureMoveOnCategory = departure?.moveOnCategory, - departureNotes = departure?.notes, - nonArrivalConfirmedAt = nonArrival?.createdAt, - nonArrivalReason = nonArrival?.reason, - nonArrivalNotes = nonArrival?.notes, - ) - - private data class ManagementInfo( - val source: ManagementInfoSource, - val arrivedAtDate: LocalDate?, - val arrivedAtTime: LocalTime?, - val departedAtDate: LocalDate?, - val departedAtTime: LocalTime?, - val keyWorkerStaffCode: String?, - val keyWorkerName: String?, - val departureReason: DepartureReasonEntity?, - val departureMoveOnCategory: MoveOnCategoryEntity?, - val departureNotes: String?, - val nonArrivalConfirmedAt: OffsetDateTime?, - val nonArrivalReason: NonArrivalReasonEntity?, - val nonArrivalNotes: String?, - ) - private fun BookingEntity.getEssentialRoomCriteriaOfInterest() = placementRequest?.placementRequirements?.essentialCriteria ?.filter { it.isModelScopeRoom() } diff --git a/src/test/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/unit/seed/cas1/Cas1BookingToSpaceBookingSeedJobTest.kt b/src/test/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/unit/seed/cas1/Cas1BookingToSpaceBookingSeedJobTest.kt index 2577fe7c3a..f36812426e 100644 --- a/src/test/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/unit/seed/cas1/Cas1BookingToSpaceBookingSeedJobTest.kt +++ b/src/test/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/unit/seed/cas1/Cas1BookingToSpaceBookingSeedJobTest.kt @@ -9,13 +9,11 @@ import uk.gov.justice.digital.hmpps.approvedpremisesapi.factory.ApprovedPremises import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.ApprovedPremisesRepository import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.BookingRepository import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.Cas1SpaceBookingRepository -import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.DepartureReasonRepository import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.DomainEventRepository -import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.MoveOnCategoryRepository -import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.NonArrivalReasonRepository import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.PlacementRequestRepository import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.UserRepository import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.cas1.Cas1DeliusBookingImportRepository +import uk.gov.justice.digital.hmpps.approvedpremisesapi.seed.cas1.Cas1BookingManagementInfoService import uk.gov.justice.digital.hmpps.approvedpremisesapi.seed.cas1.Cas1BookingToSpaceBookingSeedCsvRow import uk.gov.justice.digital.hmpps.approvedpremisesapi.seed.cas1.Cas1BookingToSpaceBookingSeedJob import uk.gov.justice.digital.hmpps.approvedpremisesapi.service.EnvironmentService @@ -34,9 +32,7 @@ class Cas1BookingToSpaceBookingSeedJobTest { userRepository = mockk(), transactionTemplate = mockk(), cas1DeliusBookingImportRepository = mockk(), - departureReasonRepository = mockk(), - moveOnCategoryRepository = mockk(), - nonArrivalReasonReasonEntity = mockk(), + cas1BookingManagementInfoService = mockk(), environmentService = mockk(), placementRequestRepository = mockk(), ) From d6085c5c531bd7f9a5cf910716edd4ed431a62bf Mon Sep 17 00:00:00 2001 From: davidatkinsuk Date: Mon, 6 Jan 2025 12:15:03 +0000 Subject: [PATCH 2/3] Seed job to backfill space bookings from delius MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit adds a seed job to backfill `SpaceBookings` for bookings that were created directly in delius It will create an offline application for every required booking, emulating the now removed ‘manual booking’ functionality --- .../jpa/entity/Cas1SpaceBookingEntity.kt | 2 +- .../jpa/entity/OfflineApplicationEntity.kt | 1 + .../cas1/Cas1DeliusBookingImportEntity.kt | 1 + .../approvedpremisesapi/seed/SeedService.kt | 2 + ...as1BackfillSpaceBookingsCreatedInDelius.kt | 177 +++++++++++++++ src/main/resources/static/_shared.yml | 1 + .../static/codegen/built-api-spec.yml | 1 + .../static/codegen/built-cas1-api-spec.yml | 1 + .../static/codegen/built-cas2-api-spec.yml | 1 + .../static/codegen/built-cas3-api-spec.yml | 1 + ...ackfillSpaceBookingsCreatedInDeliusTest.kt | 206 ++++++++++++++++++ .../SeedCas1BookingToSpaceBookingTest.kt | 2 +- ...ackfillSpaceBookingsCreatedInDeliusTest.kt | 46 ++++ 13 files changed, 440 insertions(+), 2 deletions(-) create mode 100644 src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/seed/cas1/Cas1BackfillSpaceBookingsCreatedInDelius.kt create mode 100644 src/test/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/integration/cas1/seed/SeedCas1BackfillSpaceBookingsCreatedInDeliusTest.kt rename src/test/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/integration/{seed/cas1 => cas1/seed}/SeedCas1BookingToSpaceBookingTest.kt (99%) create mode 100644 src/test/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/unit/seed/cas1/Cas1BackfillSpaceBookingsCreatedInDeliusTest.kt diff --git a/src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/jpa/entity/Cas1SpaceBookingEntity.kt b/src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/jpa/entity/Cas1SpaceBookingEntity.kt index 30a6e5672d..9045c41288 100644 --- a/src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/jpa/entity/Cas1SpaceBookingEntity.kt +++ b/src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/jpa/entity/Cas1SpaceBookingEntity.kt @@ -286,7 +286,7 @@ data class Cas1SpaceBookingEntity( @JoinColumn(name = "placement_request_id") val placementRequest: PlacementRequestEntity?, /** - * createdAt will only be null for migrated [BookingEntity]s where no 'Booking Made' domain event + * createdBy will only be null for migrated [BookingEntity]s where no 'Booking Made' domain event * existed for the booking (i.e. those migrated into the system when it went live) */ @ManyToOne(fetch = FetchType.LAZY) diff --git a/src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/jpa/entity/OfflineApplicationEntity.kt b/src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/jpa/entity/OfflineApplicationEntity.kt index bfb773e2ea..eee2ec726c 100644 --- a/src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/jpa/entity/OfflineApplicationEntity.kt +++ b/src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/jpa/entity/OfflineApplicationEntity.kt @@ -5,6 +5,7 @@ import jakarta.persistence.Id import jakarta.persistence.Table import org.springframework.data.jpa.repository.JpaRepository import org.springframework.stereotype.Repository +import uk.gov.justice.digital.hmpps.approvedpremisesapi.service.OffenderService import java.time.OffsetDateTime import java.util.UUID diff --git a/src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/jpa/entity/cas1/Cas1DeliusBookingImportEntity.kt b/src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/jpa/entity/cas1/Cas1DeliusBookingImportEntity.kt index 6035fb3d19..c26540ead0 100644 --- a/src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/jpa/entity/cas1/Cas1DeliusBookingImportEntity.kt +++ b/src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/jpa/entity/cas1/Cas1DeliusBookingImportEntity.kt @@ -12,6 +12,7 @@ import java.util.UUID @Repository interface Cas1DeliusBookingImportRepository : JpaRepository { fun findByBookingId(id: UUID): Cas1DeliusBookingImportEntity? + fun findByBookingIdIsNullAndPremisesQcode(qCode: String): List } @Entity diff --git a/src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/seed/SeedService.kt b/src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/seed/SeedService.kt index 5efa546659..efe33561be 100644 --- a/src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/seed/SeedService.kt +++ b/src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/seed/SeedService.kt @@ -10,6 +10,7 @@ import uk.gov.justice.digital.hmpps.approvedpremisesapi.config.SeedConfig import uk.gov.justice.digital.hmpps.approvedpremisesapi.seed.cas1.ApStaffUsersSeedJob import uk.gov.justice.digital.hmpps.approvedpremisesapi.seed.cas1.ApprovedPremisesBookingCancelSeedJob import uk.gov.justice.digital.hmpps.approvedpremisesapi.seed.cas1.ApprovedPremisesRoomsSeedJob +import uk.gov.justice.digital.hmpps.approvedpremisesapi.seed.cas1.Cas1BackfillSpaceBookingsCreatedInDelius import uk.gov.justice.digital.hmpps.approvedpremisesapi.seed.cas1.Cas1BookingToSpaceBookingSeedJob import uk.gov.justice.digital.hmpps.approvedpremisesapi.seed.cas1.Cas1CruManagementAreaSeedJob import uk.gov.justice.digital.hmpps.approvedpremisesapi.seed.cas1.Cas1DomainEventReplaySeedJob @@ -90,6 +91,7 @@ class SeedService( SeedFileType.approvedPremisesImportDeliusReferrals -> getBean(Cas1ImportDeliusReferralsSeedJob::class) SeedFileType.approvedPremisesUpdateSpaceBooking -> getBean(Cas1UpdateSpaceBookingSeedJob::class) SeedFileType.temporaryAccommodationReferralRejection -> getBean(Cas3ReferralRejectionSeedJob::class) + SeedFileType.approvedPremisesBackfillSpaceBookingsCreatedInDelius -> getBean(Cas1BackfillSpaceBookingsCreatedInDelius::class) } val seedStarted = LocalDateTime.now() diff --git a/src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/seed/cas1/Cas1BackfillSpaceBookingsCreatedInDelius.kt b/src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/seed/cas1/Cas1BackfillSpaceBookingsCreatedInDelius.kt new file mode 100644 index 0000000000..437c5c298b --- /dev/null +++ b/src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/seed/cas1/Cas1BackfillSpaceBookingsCreatedInDelius.kt @@ -0,0 +1,177 @@ +package uk.gov.justice.digital.hmpps.approvedpremisesapi.seed.cas1 + +import org.slf4j.LoggerFactory +import org.springframework.stereotype.Service +import org.springframework.transaction.support.TransactionTemplate +import uk.gov.justice.digital.hmpps.approvedpremisesapi.api.model.ServiceName +import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.ApprovedPremisesEntity +import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.ApprovedPremisesRepository +import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.Cas1SpaceBookingEntity +import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.Cas1SpaceBookingRepository +import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.CharacteristicEntity +import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.OfflineApplicationEntity +import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.OfflineApplicationRepository +import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.cas1.Cas1DeliusBookingImportEntity +import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.cas1.Cas1DeliusBookingImportRepository +import uk.gov.justice.digital.hmpps.approvedpremisesapi.model.PersonSummaryInfoResult +import uk.gov.justice.digital.hmpps.approvedpremisesapi.seed.SeedJob +import uk.gov.justice.digital.hmpps.approvedpremisesapi.service.EnvironmentService +import uk.gov.justice.digital.hmpps.approvedpremisesapi.service.OffenderService +import java.time.OffsetDateTime +import java.util.UUID + +/** + * Before this job is ran, corresponding referrals must be imported from delius into the + * 'cas1_delius_booking_import' table using the [Cas1ImportDeliusReferralsSeedJob] job + */ +@Service +class Cas1BackfillSpaceBookingsCreatedInDelius( + private val approvedPremisesRepository: ApprovedPremisesRepository, + private val cas1DeliusBookingImportRepository: Cas1DeliusBookingImportRepository, + private val cas1BookingManagementInfoService: Cas1BookingManagementInfoService, + private val environmentService: EnvironmentService, + private val offenderService: OffenderService, + private val offlineApplicationRepository: OfflineApplicationRepository, + private val spaceBookingRepository: Cas1SpaceBookingRepository, + private val transactionTemplate: TransactionTemplate, +) : SeedJob( + requiredHeaders = setOf( + "q_code", + ), + runInTransaction = false, +) { + private val log = LoggerFactory.getLogger(this::class.java) + + override fun deserializeRow(columns: Map) = Cas1CreateMissingReferralsSeedCsvRow( + qCode = columns["q_code"]!!.trim(), + ) + + override fun preSeed() { + if (environmentService.isProd()) { + error("Cannot run seed job in prod") + } + } + + override fun processRow(row: Cas1CreateMissingReferralsSeedCsvRow) { + transactionTemplate.executeWithoutResult { + migratePremise(row.qCode) + } + } + + @SuppressWarnings("TooGenericExceptionCaught") + private fun migratePremise(qCode: String) { + val premises = approvedPremisesRepository.findByQCode(qCode) ?: error("Premises with qcode $qCode not found") + + if (!premises.supportsSpaceBookings) { + error("premise ${premises.name} doesn't support space bookings, can't migrate bookings") + } + + val referrals = cas1DeliusBookingImportRepository.findByBookingIdIsNullAndPremisesQcode(qCode) + + log.info("Will create ${referrals.size} space bookings for premise ${premises.name} ($qCode)") + + if (referrals.isEmpty()) { + return + } + + // TODO: we need a version of this that will segment calls to the backend + // can use for CAS3 report that does that? + val crnToName = offenderService.getPersonSummaryInfoResults( + crns = referrals.map { it.crn }.toSet(), + limitedAccessStrategy = OffenderService.LimitedAccessStrategy.IgnoreLimitedAccess, + ).associate { personSummaryInfoResult -> + val crn = personSummaryInfoResult.crn + when (personSummaryInfoResult) { + is PersonSummaryInfoResult.Success.Full -> { + val name = personSummaryInfoResult.summary.name + crn to "${name.forename} ${name.surname}" + } + is PersonSummaryInfoResult.NotFound, + is PersonSummaryInfoResult.Success.Restricted, + is PersonSummaryInfoResult.Unknown, + -> { + log.warn( + "Could not find offender for CRN $crn, " + + "result was ${personSummaryInfoResult::class}. Will not populate name", + ) + crn to null + } + } + } + + referrals.forEach { + createSpaceBooking( + premises = premises, + deliusReferral = it, + crnToName = crnToName, + ) + } + } + + private fun createSpaceBooking( + premises: ApprovedPremisesEntity, + deliusReferral: Cas1DeliusBookingImportEntity, + crnToName: Map, + ) { + val crn = deliusReferral.crn + + if (deliusReferral.expectedDepartureDate == null) { + log.warn("No expected departure date defined for crn $crn with arrival ${deliusReferral.arrivalDate}") + return + } + + val offlineApplication = offlineApplicationRepository.save( + OfflineApplicationEntity( + id = UUID.randomUUID(), + crn = crn, + service = ServiceName.approvedPremises.value, + createdAt = OffsetDateTime.now(), + eventNumber = deliusReferral.eventNumber, + name = crnToName[crn], + ), + ) + + val managementInfo = cas1BookingManagementInfoService.fromDeliusBookingImport(deliusReferral) + + spaceBookingRepository.save( + Cas1SpaceBookingEntity( + id = UUID.randomUUID(), + premises = premises, + application = null, + offlineApplication = offlineApplication, + placementRequest = null, + createdBy = null, + createdAt = OffsetDateTime.now(), + expectedArrivalDate = deliusReferral.expectedArrivalDate, + expectedDepartureDate = deliusReferral.expectedDepartureDate!!, + actualArrivalDate = managementInfo.arrivedAtDate, + actualArrivalTime = managementInfo.arrivedAtTime, + actualDepartureDate = managementInfo.departedAtDate, + actualDepartureTime = managementInfo.departedAtTime, + canonicalArrivalDate = managementInfo.arrivedAtDate ?: deliusReferral.expectedArrivalDate, + canonicalDepartureDate = managementInfo.departedAtDate ?: deliusReferral.expectedDepartureDate!!, + crn = deliusReferral.crn, + keyWorkerStaffCode = managementInfo.keyWorkerStaffCode, + keyWorkerName = managementInfo.keyWorkerName, + keyWorkerAssignedAt = null, + cancellationOccurredAt = null, + cancellationRecordedAt = null, + cancellationReason = null, + cancellationReasonNotes = null, + departureMoveOnCategory = managementInfo.departureMoveOnCategory, + departureReason = managementInfo.departureReason, + departureNotes = managementInfo.departureNotes, + criteria = emptyList().toMutableList(), + nonArrivalReason = managementInfo.nonArrivalReason, + nonArrivalConfirmedAt = managementInfo.nonArrivalConfirmedAt?.toInstant(), + nonArrivalNotes = managementInfo.nonArrivalNotes, + deliusEventNumber = deliusReferral.eventNumber, + migratedManagementInfoFrom = managementInfo.source, + ), + ) + } +} + +data class Cas1CreateMissingReferralsSeedCsvRow( + val qCode: String, +) diff --git a/src/main/resources/static/_shared.yml b/src/main/resources/static/_shared.yml index 91440ae3ce..e760505463 100644 --- a/src/main/resources/static/_shared.yml +++ b/src/main/resources/static/_shared.yml @@ -3726,6 +3726,7 @@ components: - approved_premises_space_planning_dry_run - approved_premises_import_delius_referrals - approved_premises_update_space_booking + - approved_premises_backfill_space_bookings_created_in_delius - temporary_accommodation_referral_rejection SeedFromExcelFileType: type: string diff --git a/src/main/resources/static/codegen/built-api-spec.yml b/src/main/resources/static/codegen/built-api-spec.yml index 53e7f5286e..624da3d4b1 100644 --- a/src/main/resources/static/codegen/built-api-spec.yml +++ b/src/main/resources/static/codegen/built-api-spec.yml @@ -8027,6 +8027,7 @@ components: - approved_premises_space_planning_dry_run - approved_premises_import_delius_referrals - approved_premises_update_space_booking + - approved_premises_backfill_space_bookings_created_in_delius - temporary_accommodation_referral_rejection SeedFromExcelFileType: type: string diff --git a/src/main/resources/static/codegen/built-cas1-api-spec.yml b/src/main/resources/static/codegen/built-cas1-api-spec.yml index 0524ba546c..3b8b720d2d 100644 --- a/src/main/resources/static/codegen/built-cas1-api-spec.yml +++ b/src/main/resources/static/codegen/built-cas1-api-spec.yml @@ -4948,6 +4948,7 @@ components: - approved_premises_space_planning_dry_run - approved_premises_import_delius_referrals - approved_premises_update_space_booking + - approved_premises_backfill_space_bookings_created_in_delius - temporary_accommodation_referral_rejection SeedFromExcelFileType: type: string diff --git a/src/main/resources/static/codegen/built-cas2-api-spec.yml b/src/main/resources/static/codegen/built-cas2-api-spec.yml index 742385e739..14f3d31518 100644 --- a/src/main/resources/static/codegen/built-cas2-api-spec.yml +++ b/src/main/resources/static/codegen/built-cas2-api-spec.yml @@ -4317,6 +4317,7 @@ components: - approved_premises_space_planning_dry_run - approved_premises_import_delius_referrals - approved_premises_update_space_booking + - approved_premises_backfill_space_bookings_created_in_delius - temporary_accommodation_referral_rejection SeedFromExcelFileType: type: string diff --git a/src/main/resources/static/codegen/built-cas3-api-spec.yml b/src/main/resources/static/codegen/built-cas3-api-spec.yml index e25e4aaba1..f4b64d78b8 100644 --- a/src/main/resources/static/codegen/built-cas3-api-spec.yml +++ b/src/main/resources/static/codegen/built-cas3-api-spec.yml @@ -3825,6 +3825,7 @@ components: - approved_premises_space_planning_dry_run - approved_premises_import_delius_referrals - approved_premises_update_space_booking + - approved_premises_backfill_space_bookings_created_in_delius - temporary_accommodation_referral_rejection SeedFromExcelFileType: type: string diff --git a/src/test/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/integration/cas1/seed/SeedCas1BackfillSpaceBookingsCreatedInDeliusTest.kt b/src/test/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/integration/cas1/seed/SeedCas1BackfillSpaceBookingsCreatedInDeliusTest.kt new file mode 100644 index 0000000000..003b17c788 --- /dev/null +++ b/src/test/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/integration/cas1/seed/SeedCas1BackfillSpaceBookingsCreatedInDeliusTest.kt @@ -0,0 +1,206 @@ +package uk.gov.justice.digital.hmpps.approvedpremisesapi.integration.cas1.seed + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.springframework.beans.factory.annotation.Autowired +import uk.gov.justice.digital.hmpps.approvedpremisesapi.api.model.SeedFileType +import uk.gov.justice.digital.hmpps.approvedpremisesapi.api.model.ServiceName +import uk.gov.justice.digital.hmpps.approvedpremisesapi.factory.CaseSummaryFactory +import uk.gov.justice.digital.hmpps.approvedpremisesapi.factory.NameFactory +import uk.gov.justice.digital.hmpps.approvedpremisesapi.integration.givens.givenAUser +import uk.gov.justice.digital.hmpps.approvedpremisesapi.integration.givens.givenAnApprovedPremises +import uk.gov.justice.digital.hmpps.approvedpremisesapi.integration.httpmocks.apDeliusContextAddListCaseSummaryToBulkResponse +import uk.gov.justice.digital.hmpps.approvedpremisesapi.integration.seed.SeedTestBase +import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.ApprovedPremisesEntity +import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.DepartureReasonEntity +import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.ManagementInfoSource +import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.MoveOnCategoryEntity +import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.NonArrivalReasonEntity +import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.UserEntity +import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.cas1.Cas1DeliusBookingImportEntity +import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.cas1.Cas1DeliusBookingImportRepository +import uk.gov.justice.digital.hmpps.approvedpremisesapi.repository.Cas1SpaceBookingTestRepository +import uk.gov.justice.digital.hmpps.approvedpremisesapi.seed.CsvBuilder +import uk.gov.justice.digital.hmpps.approvedpremisesapi.seed.cas1.Cas1CreateMissingReferralsSeedCsvRow +import uk.gov.justice.digital.hmpps.approvedpremisesapi.util.isWithinTheLastMinute +import java.time.Instant +import java.time.LocalDate +import java.time.LocalDateTime +import java.time.OffsetDateTime +import java.time.ZoneOffset +import java.util.UUID + +class SeedCas1BackfillSpaceBookingsCreatedInDeliusTest : SeedTestBase() { + + @Autowired + lateinit var cas1SpaceBookingTestRepository: Cas1SpaceBookingTestRepository + + @Autowired + lateinit var deliusBookingImportRepository: Cas1DeliusBookingImportRepository + + lateinit var premises: ApprovedPremisesEntity + lateinit var otherPremise: ApprovedPremisesEntity + lateinit var otherUser: UserEntity + + lateinit var departureReasonActive: DepartureReasonEntity + lateinit var moveOnCategory: MoveOnCategoryEntity + lateinit var nonArrivalReasonCode: NonArrivalReasonEntity + + @BeforeEach + fun setupReferenceData() { + premises = givenAnApprovedPremises( + name = "Premises 1", + supportsSpaceBookings = true, + ) + otherPremise = givenAnApprovedPremises( + name = "Premises 2", + supportsSpaceBookings = true, + ) + otherUser = givenAUser().first + + departureReasonEntityFactory.produceAndPersist { + withLegacyDeliusCategoryCode("dr1inactive") + withServiceScope(ServiceName.approvedPremises.value) + } + departureReasonActive = departureReasonEntityFactory.produceAndPersist { + withLegacyDeliusCategoryCode("dr1") + withServiceScope(ServiceName.approvedPremises.value) + } + moveOnCategory = moveOnCategoryEntityFactory.produceAndPersist { + withLegacyDeliusCategoryCode("moc1") + withServiceScope(ServiceName.approvedPremises.value) + } + nonArrivalReasonCode = nonArrivalReasonEntityFactory.produceAndPersist { + withLegacyDeliusReasonCode("narc1") + } + } + + @SuppressWarnings("LongMethod") + @Test + fun `Backfill Space Bookings from Delius Import`() { + apDeliusContextAddListCaseSummaryToBulkResponse( + listOf( + CaseSummaryFactory() + .withCrn("CRN1") + .withName( + NameFactory() + .withForename("Max") + .withSurname("Power") + .produce(), + ) + .produce(), + ), + ) + + val deliusBooking = Cas1DeliusBookingImportEntity( + id = UUID.randomUUID(), + bookingId = null, + crn = "CRN1", + eventNumber = "67", + keyWorkerStaffCode = "kw001", + keyWorkerForename = "kay", + keyWorkerMiddleName = "m", + keyWorkerSurname = "werker", + departureReasonCode = "dr1", + moveOnCategoryCode = "moc1", + moveOnCategoryDescription = null, + expectedArrivalDate = LocalDate.of(2024, 5, 9), + arrivalDate = LocalDate.of(2024, 5, 2), + expectedDepartureDate = LocalDate.of(2024, 6, 2), + departureDate = LocalDate.of(2024, 5, 4), + nonArrivalDate = LocalDate.of(3000, 1, 1), + nonArrivalContactDatetime = OffsetDateTime.of(LocalDateTime.of(2024, 2, 1, 9, 58, 23), ZoneOffset.UTC), + nonArrivalReasonCode = "narc1", + nonArrivalReasonDescription = null, + nonArrivalNotes = "the non arrival notes", + premisesQcode = premises.qCode, + ) + + deliusBookingImportRepository.save( + deliusBooking.copy( + id = UUID.randomUUID(), + ), + ) + + // booking with booking id (e.g. created in CAS1) is ignored + deliusBookingImportRepository.save( + deliusBooking.copy( + id = UUID.randomUUID(), + bookingId = UUID.randomUUID(), + ), + ) + + // booking for other premise is ignored + deliusBookingImportRepository.save( + deliusBooking.copy( + id = UUID.randomUUID(), + premisesQcode = otherPremise.qCode, + ), + ) + + withCsv( + "valid-csv", + rowsToCsv(listOf(Cas1CreateMissingReferralsSeedCsvRow(premises.qCode))), + ) + + seedService.seedData(SeedFileType.approvedPremisesBackfillSpaceBookingsCreatedInDelius, "valid-csv.csv") + + val premiseSpaceBookings = cas1SpaceBookingTestRepository.findByPremisesId(premises.id) + assertThat(premiseSpaceBookings).hasSize(1) + + val migratedBooking1 = premiseSpaceBookings[0] + + assertThat(migratedBooking1.crn).isEqualTo("CRN1") + assertThat(migratedBooking1.deliusEventNumber).isEqualTo("67") + assertThat(migratedBooking1.premises.id).isEqualTo(premises.id) + assertThat(migratedBooking1.placementRequest).isNull() + assertThat(migratedBooking1.createdBy).isNull() + assertThat(migratedBooking1.expectedArrivalDate).isEqualTo(LocalDate.of(2024, 5, 9)) + assertThat(migratedBooking1.expectedDepartureDate).isEqualTo(LocalDate.of(2024, 6, 2)) + assertThat(migratedBooking1.actualArrivalDate).isEqualTo(LocalDate.parse("2024-05-02")) + assertThat(migratedBooking1.actualArrivalTime).isNull() + assertThat(migratedBooking1.actualDepartureDate).isEqualTo(LocalDate.parse("2024-05-04")) + assertThat(migratedBooking1.actualDepartureTime).isNull() + assertThat(migratedBooking1.canonicalArrivalDate).isEqualTo(LocalDate.of(2024, 5, 2)) + assertThat(migratedBooking1.canonicalDepartureDate).isEqualTo(LocalDate.of(2024, 5, 4)) + assertThat(migratedBooking1.keyWorkerName).isEqualTo("kay werker") + assertThat(migratedBooking1.keyWorkerStaffCode).isEqualTo("kw001") + assertThat(migratedBooking1.keyWorkerAssignedAt).isNull() + assertThat(migratedBooking1.application).isNull() + assertThat(migratedBooking1.cancellationReason).isNull() + assertThat(migratedBooking1.cancellationOccurredAt).isNull() + assertThat(migratedBooking1.cancellationRecordedAt).isNull() + assertThat(migratedBooking1.cancellationReasonNotes).isNull() + assertThat(migratedBooking1.departureReason).isEqualTo(departureReasonActive) + assertThat(migratedBooking1.departureMoveOnCategory).isEqualTo(moveOnCategory) + assertThat(migratedBooking1.criteria).isEmpty() + assertThat(migratedBooking1.nonArrivalReason).isEqualTo(nonArrivalReasonCode) + assertThat(migratedBooking1.nonArrivalConfirmedAt).isEqualTo(Instant.parse("2024-02-01T09:58:23.00Z")) + assertThat(migratedBooking1.nonArrivalNotes).isEqualTo("the non arrival notes") + assertThat(migratedBooking1.migratedManagementInfoFrom).isEqualTo(ManagementInfoSource.DELIUS) + + val offlineApplication1 = migratedBooking1.offlineApplication!! + assertThat(offlineApplication1.crn).isEqualTo("CRN1") + assertThat(offlineApplication1.service).isEqualTo(ServiceName.approvedPremises.value) + assertThat(offlineApplication1.createdAt).isWithinTheLastMinute() + assertThat(offlineApplication1.eventNumber).isEqualTo("67") + assertThat(offlineApplication1.name).isEqualTo("Max Power") + } + + private fun rowsToCsv(rows: List): String { + val builder = CsvBuilder() + .withUnquotedFields( + "q_code", + ) + .newRow() + + rows.forEach { + builder + .withQuotedField(premises.qCode) + .newRow() + } + + return builder.build() + } +} diff --git a/src/test/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/integration/seed/cas1/SeedCas1BookingToSpaceBookingTest.kt b/src/test/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/integration/cas1/seed/SeedCas1BookingToSpaceBookingTest.kt similarity index 99% rename from src/test/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/integration/seed/cas1/SeedCas1BookingToSpaceBookingTest.kt rename to src/test/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/integration/cas1/seed/SeedCas1BookingToSpaceBookingTest.kt index 1c3fdbb50f..c750c976f1 100644 --- a/src/test/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/integration/seed/cas1/SeedCas1BookingToSpaceBookingTest.kt +++ b/src/test/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/integration/cas1/seed/SeedCas1BookingToSpaceBookingTest.kt @@ -1,4 +1,4 @@ -package uk.gov.justice.digital.hmpps.approvedpremisesapi.integration.seed.cas1 +package uk.gov.justice.digital.hmpps.approvedpremisesapi.integration.cas1.seed import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.BeforeEach diff --git a/src/test/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/unit/seed/cas1/Cas1BackfillSpaceBookingsCreatedInDeliusTest.kt b/src/test/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/unit/seed/cas1/Cas1BackfillSpaceBookingsCreatedInDeliusTest.kt new file mode 100644 index 0000000000..27e496d1d0 --- /dev/null +++ b/src/test/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/unit/seed/cas1/Cas1BackfillSpaceBookingsCreatedInDeliusTest.kt @@ -0,0 +1,46 @@ +package uk.gov.justice.digital.hmpps.approvedpremisesapi.unit.seed.cas1 + +import io.mockk.every +import io.mockk.mockk +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows +import org.springframework.transaction.support.TransactionTemplate +import uk.gov.justice.digital.hmpps.approvedpremisesapi.factory.ApprovedPremisesEntityFactory +import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.ApprovedPremisesRepository +import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.Cas1SpaceBookingRepository +import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.OfflineApplicationRepository +import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.cas1.Cas1DeliusBookingImportRepository +import uk.gov.justice.digital.hmpps.approvedpremisesapi.seed.cas1.Cas1BackfillSpaceBookingsCreatedInDelius +import uk.gov.justice.digital.hmpps.approvedpremisesapi.seed.cas1.Cas1BookingManagementInfoService +import uk.gov.justice.digital.hmpps.approvedpremisesapi.seed.cas1.Cas1CreateMissingReferralsSeedCsvRow +import uk.gov.justice.digital.hmpps.approvedpremisesapi.service.EnvironmentService +import uk.gov.justice.digital.hmpps.approvedpremisesapi.service.OffenderService + +class Cas1BackfillSpaceBookingsCreatedInDeliusTest { + + private val approvedPremisesRepository = mockk() + + private val seedJob = Cas1BackfillSpaceBookingsCreatedInDelius( + approvedPremisesRepository = approvedPremisesRepository, + cas1DeliusBookingImportRepository = mockk(), + cas1BookingManagementInfoService = mockk(), + environmentService = mockk(), + offenderService = mockk(), + offlineApplicationRepository = mockk(), + spaceBookingRepository = mockk(), + transactionTemplate = mockk(), + ) + + @Test + fun `fails if premise doesn't support space booking`() { + every { approvedPremisesRepository.findByQCode("Q123") } returns + ApprovedPremisesEntityFactory() + .withSupportsSpaceBookings(false) + .withDefaults() + .produce() + + assertThrows { + seedJob.processRow(Cas1CreateMissingReferralsSeedCsvRow("Q123")) + } + } +} From 39338a97c3f95f6ac156a085e0e5e535631faa8c Mon Sep 17 00:00:00 2001 From: davidatkinsuk Date: Wed, 8 Jan 2025 11:02:24 +0000 Subject: [PATCH 3/3] Job to backfill CAS1 bookings created in delius This commit adds a seed job to backfill active CAS1 bookings created in delius that do not exist in CAS1. An active booking is one that: * does not have a departure recorded (and optionally, no arrival recorded) * does not have a non arrival recorded We also exclude any bookings where the departure date is before 1/1/2025 or after 1/1/2035. This filters out several bookings where the dates have been set incorrectly but are clearly inactive/complete, most likely because they were created in older versions of delius that did not capture this data. Note that the [Cas1DeliusBookingImportEntity] table only includes accepted bookings (i.e. not rejected), so these are already filtered out. --- .../cas1/Cas1DeliusBookingImportEntity.kt | 36 ++++++++++- .../approvedpremisesapi/seed/SeedService.kt | 4 +- ...fillActiveSpaceBookingsCreatedInDelius.kt} | 35 ++++++----- src/main/resources/static/_shared.yml | 2 +- .../static/codegen/built-api-spec.yml | 2 +- .../static/codegen/built-cas1-api-spec.yml | 2 +- .../static/codegen/built-cas2-api-spec.yml | 2 +- .../static/codegen/built-cas3-api-spec.yml | 2 +- ...ActiveSpaceBookingsCreatedInDeliusTest.kt} | 60 ++++++++++++++----- ...ActiveSpaceBookingsCreatedInDeliusTest.kt} | 6 +- 10 files changed, 111 insertions(+), 40 deletions(-) rename src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/seed/cas1/{Cas1BackfillSpaceBookingsCreatedInDelius.kt => Cas1BackfillActiveSpaceBookingsCreatedInDelius.kt} (86%) rename src/test/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/integration/cas1/seed/{SeedCas1BackfillSpaceBookingsCreatedInDeliusTest.kt => SeedCas1BackfillActiveSpaceBookingsCreatedInDeliusTest.kt} (82%) rename src/test/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/unit/seed/cas1/{Cas1BackfillSpaceBookingsCreatedInDeliusTest.kt => Cas1BackfillActiveSpaceBookingsCreatedInDeliusTest.kt} (92%) diff --git a/src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/jpa/entity/cas1/Cas1DeliusBookingImportEntity.kt b/src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/jpa/entity/cas1/Cas1DeliusBookingImportEntity.kt index c26540ead0..63f20d0f6d 100644 --- a/src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/jpa/entity/cas1/Cas1DeliusBookingImportEntity.kt +++ b/src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/jpa/entity/cas1/Cas1DeliusBookingImportEntity.kt @@ -4,6 +4,7 @@ import jakarta.persistence.Entity import jakarta.persistence.Id import jakarta.persistence.Table import org.springframework.data.jpa.repository.JpaRepository +import org.springframework.data.jpa.repository.Query import org.springframework.stereotype.Repository import java.time.LocalDate import java.time.OffsetDateTime @@ -12,7 +13,40 @@ import java.util.UUID @Repository interface Cas1DeliusBookingImportRepository : JpaRepository { fun findByBookingId(id: UUID): Cas1DeliusBookingImportEntity? - fun findByBookingIdIsNullAndPremisesQcode(qCode: String): List + + /** + * Returns all active bookings created in delius that were not created in CAS1 + * + * An active booking is one that: + * + * 1. does not have a departure recorded (and optionally, no arrival recorded) + * 2. does not have a non arrival recorded + * + * We also exclude any bookings where the departure date is before 1/1/2025 or after 1/1/2035. + * This filters out several bookings where the dates have been set incorrectly but are clearly inactive/complete, + * most likely because they were created in older versions of delius that did not capture this data + * + * Note that the [Cas1DeliusBookingImportEntity] table only includes accepted bookings (i.e. not rejected), + * so these are already filtered out + */ + @Query( + """ + FROM Cas1DeliusBookingImportEntity i + WHERE + i.bookingId IS NULL AND + i.premisesQcode = :qCode AND + i.departureDate IS NULL AND + i.nonArrivalReasonCode IS NULL AND + i.expectedDepartureDate > :minExpectedDepartureDate AND + i.expectedDepartureDate < :maxExpectedDepartureDate + + """, + ) + fun findActiveBookingsCreatedInDelius( + qCode: String, + minExpectedDepartureDate: LocalDate, + maxExpectedDepartureDate: LocalDate, + ): List } @Entity diff --git a/src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/seed/SeedService.kt b/src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/seed/SeedService.kt index efe33561be..e48f1b8b4b 100644 --- a/src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/seed/SeedService.kt +++ b/src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/seed/SeedService.kt @@ -10,7 +10,7 @@ import uk.gov.justice.digital.hmpps.approvedpremisesapi.config.SeedConfig import uk.gov.justice.digital.hmpps.approvedpremisesapi.seed.cas1.ApStaffUsersSeedJob import uk.gov.justice.digital.hmpps.approvedpremisesapi.seed.cas1.ApprovedPremisesBookingCancelSeedJob import uk.gov.justice.digital.hmpps.approvedpremisesapi.seed.cas1.ApprovedPremisesRoomsSeedJob -import uk.gov.justice.digital.hmpps.approvedpremisesapi.seed.cas1.Cas1BackfillSpaceBookingsCreatedInDelius +import uk.gov.justice.digital.hmpps.approvedpremisesapi.seed.cas1.Cas1BackfillActiveSpaceBookingsCreatedInDelius import uk.gov.justice.digital.hmpps.approvedpremisesapi.seed.cas1.Cas1BookingToSpaceBookingSeedJob import uk.gov.justice.digital.hmpps.approvedpremisesapi.seed.cas1.Cas1CruManagementAreaSeedJob import uk.gov.justice.digital.hmpps.approvedpremisesapi.seed.cas1.Cas1DomainEventReplaySeedJob @@ -91,7 +91,7 @@ class SeedService( SeedFileType.approvedPremisesImportDeliusReferrals -> getBean(Cas1ImportDeliusReferralsSeedJob::class) SeedFileType.approvedPremisesUpdateSpaceBooking -> getBean(Cas1UpdateSpaceBookingSeedJob::class) SeedFileType.temporaryAccommodationReferralRejection -> getBean(Cas3ReferralRejectionSeedJob::class) - SeedFileType.approvedPremisesBackfillSpaceBookingsCreatedInDelius -> getBean(Cas1BackfillSpaceBookingsCreatedInDelius::class) + SeedFileType.approvedPremisesBackfillActiveSpaceBookingsCreatedInDelius -> getBean(Cas1BackfillActiveSpaceBookingsCreatedInDelius::class) } val seedStarted = LocalDateTime.now() diff --git a/src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/seed/cas1/Cas1BackfillSpaceBookingsCreatedInDelius.kt b/src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/seed/cas1/Cas1BackfillActiveSpaceBookingsCreatedInDelius.kt similarity index 86% rename from src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/seed/cas1/Cas1BackfillSpaceBookingsCreatedInDelius.kt rename to src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/seed/cas1/Cas1BackfillActiveSpaceBookingsCreatedInDelius.kt index 437c5c298b..6ef2afb6ec 100644 --- a/src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/seed/cas1/Cas1BackfillSpaceBookingsCreatedInDelius.kt +++ b/src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/seed/cas1/Cas1BackfillActiveSpaceBookingsCreatedInDelius.kt @@ -17,6 +17,7 @@ import uk.gov.justice.digital.hmpps.approvedpremisesapi.model.PersonSummaryInfoR import uk.gov.justice.digital.hmpps.approvedpremisesapi.seed.SeedJob import uk.gov.justice.digital.hmpps.approvedpremisesapi.service.EnvironmentService import uk.gov.justice.digital.hmpps.approvedpremisesapi.service.OffenderService +import java.time.LocalDate import java.time.OffsetDateTime import java.util.UUID @@ -25,7 +26,7 @@ import java.util.UUID * 'cas1_delius_booking_import' table using the [Cas1ImportDeliusReferralsSeedJob] job */ @Service -class Cas1BackfillSpaceBookingsCreatedInDelius( +class Cas1BackfillActiveSpaceBookingsCreatedInDelius( private val approvedPremisesRepository: ApprovedPremisesRepository, private val cas1DeliusBookingImportRepository: Cas1DeliusBookingImportRepository, private val cas1BookingManagementInfoService: Cas1BookingManagementInfoService, @@ -58,7 +59,7 @@ class Cas1BackfillSpaceBookingsCreatedInDelius( } } - @SuppressWarnings("TooGenericExceptionCaught") + @SuppressWarnings("TooGenericExceptionCaught", "MagicNumber") private fun migratePremise(qCode: String) { val premises = approvedPremisesRepository.findByQCode(qCode) ?: error("Premises with qcode $qCode not found") @@ -66,7 +67,11 @@ class Cas1BackfillSpaceBookingsCreatedInDelius( error("premise ${premises.name} doesn't support space bookings, can't migrate bookings") } - val referrals = cas1DeliusBookingImportRepository.findByBookingIdIsNullAndPremisesQcode(qCode) + val referrals = cas1DeliusBookingImportRepository.findActiveBookingsCreatedInDelius( + qCode = qCode, + minExpectedDepartureDate = LocalDate.of(2025, 1, 1), + maxExpectedDepartureDate = LocalDate.of(2035, 1, 1), + ) log.info("Will create ${referrals.size} space bookings for premise ${premises.name} ($qCode)") @@ -74,9 +79,7 @@ class Cas1BackfillSpaceBookingsCreatedInDelius( return } - // TODO: we need a version of this that will segment calls to the backend - // can use for CAS3 report that does that? - val crnToName = offenderService.getPersonSummaryInfoResults( + val crnToName = offenderService.getPersonSummaryInfoResultsInBatches( crns = referrals.map { it.crn }.toSet(), limitedAccessStrategy = OffenderService.LimitedAccessStrategy.IgnoreLimitedAccess, ).associate { personSummaryInfoResult -> @@ -106,6 +109,8 @@ class Cas1BackfillSpaceBookingsCreatedInDelius( crnToName = crnToName, ) } + + log.info("Have crated ${referrals.size} space bookings for premise ${premises.name} ($qCode)") } private fun createSpaceBooking( @@ -146,10 +151,10 @@ class Cas1BackfillSpaceBookingsCreatedInDelius( expectedDepartureDate = deliusReferral.expectedDepartureDate!!, actualArrivalDate = managementInfo.arrivedAtDate, actualArrivalTime = managementInfo.arrivedAtTime, - actualDepartureDate = managementInfo.departedAtDate, - actualDepartureTime = managementInfo.departedAtTime, + actualDepartureDate = null, + actualDepartureTime = null, canonicalArrivalDate = managementInfo.arrivedAtDate ?: deliusReferral.expectedArrivalDate, - canonicalDepartureDate = managementInfo.departedAtDate ?: deliusReferral.expectedDepartureDate!!, + canonicalDepartureDate = deliusReferral.expectedDepartureDate!!, crn = deliusReferral.crn, keyWorkerStaffCode = managementInfo.keyWorkerStaffCode, keyWorkerName = managementInfo.keyWorkerName, @@ -158,13 +163,13 @@ class Cas1BackfillSpaceBookingsCreatedInDelius( cancellationRecordedAt = null, cancellationReason = null, cancellationReasonNotes = null, - departureMoveOnCategory = managementInfo.departureMoveOnCategory, - departureReason = managementInfo.departureReason, - departureNotes = managementInfo.departureNotes, + departureMoveOnCategory = null, + departureReason = null, + departureNotes = null, criteria = emptyList().toMutableList(), - nonArrivalReason = managementInfo.nonArrivalReason, - nonArrivalConfirmedAt = managementInfo.nonArrivalConfirmedAt?.toInstant(), - nonArrivalNotes = managementInfo.nonArrivalNotes, + nonArrivalReason = null, + nonArrivalConfirmedAt = null, + nonArrivalNotes = null, deliusEventNumber = deliusReferral.eventNumber, migratedManagementInfoFrom = managementInfo.source, ), diff --git a/src/main/resources/static/_shared.yml b/src/main/resources/static/_shared.yml index e760505463..9379799c19 100644 --- a/src/main/resources/static/_shared.yml +++ b/src/main/resources/static/_shared.yml @@ -3726,7 +3726,7 @@ components: - approved_premises_space_planning_dry_run - approved_premises_import_delius_referrals - approved_premises_update_space_booking - - approved_premises_backfill_space_bookings_created_in_delius + - approved_premises_backfill_active_space_bookings_created_in_delius - temporary_accommodation_referral_rejection SeedFromExcelFileType: type: string diff --git a/src/main/resources/static/codegen/built-api-spec.yml b/src/main/resources/static/codegen/built-api-spec.yml index 624da3d4b1..1840574b86 100644 --- a/src/main/resources/static/codegen/built-api-spec.yml +++ b/src/main/resources/static/codegen/built-api-spec.yml @@ -8027,7 +8027,7 @@ components: - approved_premises_space_planning_dry_run - approved_premises_import_delius_referrals - approved_premises_update_space_booking - - approved_premises_backfill_space_bookings_created_in_delius + - approved_premises_backfill_active_space_bookings_created_in_delius - temporary_accommodation_referral_rejection SeedFromExcelFileType: type: string diff --git a/src/main/resources/static/codegen/built-cas1-api-spec.yml b/src/main/resources/static/codegen/built-cas1-api-spec.yml index 3b8b720d2d..8f63812253 100644 --- a/src/main/resources/static/codegen/built-cas1-api-spec.yml +++ b/src/main/resources/static/codegen/built-cas1-api-spec.yml @@ -4948,7 +4948,7 @@ components: - approved_premises_space_planning_dry_run - approved_premises_import_delius_referrals - approved_premises_update_space_booking - - approved_premises_backfill_space_bookings_created_in_delius + - approved_premises_backfill_active_space_bookings_created_in_delius - temporary_accommodation_referral_rejection SeedFromExcelFileType: type: string diff --git a/src/main/resources/static/codegen/built-cas2-api-spec.yml b/src/main/resources/static/codegen/built-cas2-api-spec.yml index 14f3d31518..089af06573 100644 --- a/src/main/resources/static/codegen/built-cas2-api-spec.yml +++ b/src/main/resources/static/codegen/built-cas2-api-spec.yml @@ -4317,7 +4317,7 @@ components: - approved_premises_space_planning_dry_run - approved_premises_import_delius_referrals - approved_premises_update_space_booking - - approved_premises_backfill_space_bookings_created_in_delius + - approved_premises_backfill_active_space_bookings_created_in_delius - temporary_accommodation_referral_rejection SeedFromExcelFileType: type: string diff --git a/src/main/resources/static/codegen/built-cas3-api-spec.yml b/src/main/resources/static/codegen/built-cas3-api-spec.yml index f4b64d78b8..6c2aeaa354 100644 --- a/src/main/resources/static/codegen/built-cas3-api-spec.yml +++ b/src/main/resources/static/codegen/built-cas3-api-spec.yml @@ -3825,7 +3825,7 @@ components: - approved_premises_space_planning_dry_run - approved_premises_import_delius_referrals - approved_premises_update_space_booking - - approved_premises_backfill_space_bookings_created_in_delius + - approved_premises_backfill_active_space_bookings_created_in_delius - temporary_accommodation_referral_rejection SeedFromExcelFileType: type: string diff --git a/src/test/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/integration/cas1/seed/SeedCas1BackfillSpaceBookingsCreatedInDeliusTest.kt b/src/test/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/integration/cas1/seed/SeedCas1BackfillActiveSpaceBookingsCreatedInDeliusTest.kt similarity index 82% rename from src/test/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/integration/cas1/seed/SeedCas1BackfillSpaceBookingsCreatedInDeliusTest.kt rename to src/test/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/integration/cas1/seed/SeedCas1BackfillActiveSpaceBookingsCreatedInDeliusTest.kt index 003b17c788..89377373f6 100644 --- a/src/test/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/integration/cas1/seed/SeedCas1BackfillSpaceBookingsCreatedInDeliusTest.kt +++ b/src/test/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/integration/cas1/seed/SeedCas1BackfillActiveSpaceBookingsCreatedInDeliusTest.kt @@ -24,14 +24,13 @@ import uk.gov.justice.digital.hmpps.approvedpremisesapi.repository.Cas1SpaceBook import uk.gov.justice.digital.hmpps.approvedpremisesapi.seed.CsvBuilder import uk.gov.justice.digital.hmpps.approvedpremisesapi.seed.cas1.Cas1CreateMissingReferralsSeedCsvRow import uk.gov.justice.digital.hmpps.approvedpremisesapi.util.isWithinTheLastMinute -import java.time.Instant import java.time.LocalDate import java.time.LocalDateTime import java.time.OffsetDateTime import java.time.ZoneOffset import java.util.UUID -class SeedCas1BackfillSpaceBookingsCreatedInDeliusTest : SeedTestBase() { +class SeedCas1BackfillActiveSpaceBookingsCreatedInDeliusTest : SeedTestBase() { @Autowired lateinit var cas1SpaceBookingTestRepository: Cas1SpaceBookingTestRepository @@ -107,11 +106,11 @@ class SeedCas1BackfillSpaceBookingsCreatedInDeliusTest : SeedTestBase() { moveOnCategoryDescription = null, expectedArrivalDate = LocalDate.of(2024, 5, 9), arrivalDate = LocalDate.of(2024, 5, 2), - expectedDepartureDate = LocalDate.of(2024, 6, 2), - departureDate = LocalDate.of(2024, 5, 4), + expectedDepartureDate = LocalDate.of(2025, 6, 2), + departureDate = null, nonArrivalDate = LocalDate.of(3000, 1, 1), nonArrivalContactDatetime = OffsetDateTime.of(LocalDateTime.of(2024, 2, 1, 9, 58, 23), ZoneOffset.UTC), - nonArrivalReasonCode = "narc1", + nonArrivalReasonCode = null, nonArrivalReasonDescription = null, nonArrivalNotes = "the non arrival notes", premisesQcode = premises.qCode, @@ -139,12 +138,44 @@ class SeedCas1BackfillSpaceBookingsCreatedInDeliusTest : SeedTestBase() { ), ) + // booking with non arrival recorded is ignored + deliusBookingImportRepository.save( + deliusBooking.copy( + id = UUID.randomUUID(), + nonArrivalReasonCode = "narc1", + ), + ) + + // booking with departure recorded is ignore + deliusBookingImportRepository.save( + deliusBooking.copy( + id = UUID.randomUUID(), + departureDate = LocalDate.of(2025, 5, 4), + ), + ) + + // booking with departure before 2025-1-1 is ignored + deliusBookingImportRepository.save( + deliusBooking.copy( + id = UUID.randomUUID(), + departureDate = LocalDate.of(2025, 1, 1).minusDays(1), + ), + ) + + // booking with departure after 2035-1-1 is ignored + deliusBookingImportRepository.save( + deliusBooking.copy( + id = UUID.randomUUID(), + departureDate = LocalDate.of(2035, 1, 1).plusDays(1), + ), + ) + withCsv( "valid-csv", rowsToCsv(listOf(Cas1CreateMissingReferralsSeedCsvRow(premises.qCode))), ) - seedService.seedData(SeedFileType.approvedPremisesBackfillSpaceBookingsCreatedInDelius, "valid-csv.csv") + seedService.seedData(SeedFileType.approvedPremisesBackfillActiveSpaceBookingsCreatedInDelius, "valid-csv.csv") val premiseSpaceBookings = cas1SpaceBookingTestRepository.findByPremisesId(premises.id) assertThat(premiseSpaceBookings).hasSize(1) @@ -157,13 +188,13 @@ class SeedCas1BackfillSpaceBookingsCreatedInDeliusTest : SeedTestBase() { assertThat(migratedBooking1.placementRequest).isNull() assertThat(migratedBooking1.createdBy).isNull() assertThat(migratedBooking1.expectedArrivalDate).isEqualTo(LocalDate.of(2024, 5, 9)) - assertThat(migratedBooking1.expectedDepartureDate).isEqualTo(LocalDate.of(2024, 6, 2)) + assertThat(migratedBooking1.expectedDepartureDate).isEqualTo(LocalDate.of(2025, 6, 2)) assertThat(migratedBooking1.actualArrivalDate).isEqualTo(LocalDate.parse("2024-05-02")) assertThat(migratedBooking1.actualArrivalTime).isNull() - assertThat(migratedBooking1.actualDepartureDate).isEqualTo(LocalDate.parse("2024-05-04")) + assertThat(migratedBooking1.actualDepartureDate).isNull() assertThat(migratedBooking1.actualDepartureTime).isNull() assertThat(migratedBooking1.canonicalArrivalDate).isEqualTo(LocalDate.of(2024, 5, 2)) - assertThat(migratedBooking1.canonicalDepartureDate).isEqualTo(LocalDate.of(2024, 5, 4)) + assertThat(migratedBooking1.canonicalDepartureDate).isEqualTo(LocalDate.of(2025, 6, 2)) assertThat(migratedBooking1.keyWorkerName).isEqualTo("kay werker") assertThat(migratedBooking1.keyWorkerStaffCode).isEqualTo("kw001") assertThat(migratedBooking1.keyWorkerAssignedAt).isNull() @@ -172,12 +203,13 @@ class SeedCas1BackfillSpaceBookingsCreatedInDeliusTest : SeedTestBase() { assertThat(migratedBooking1.cancellationOccurredAt).isNull() assertThat(migratedBooking1.cancellationRecordedAt).isNull() assertThat(migratedBooking1.cancellationReasonNotes).isNull() - assertThat(migratedBooking1.departureReason).isEqualTo(departureReasonActive) - assertThat(migratedBooking1.departureMoveOnCategory).isEqualTo(moveOnCategory) + assertThat(migratedBooking1.departureReason).isNull() + assertThat(migratedBooking1.departureMoveOnCategory).isNull() + assertThat(migratedBooking1.departureNotes).isNull() assertThat(migratedBooking1.criteria).isEmpty() - assertThat(migratedBooking1.nonArrivalReason).isEqualTo(nonArrivalReasonCode) - assertThat(migratedBooking1.nonArrivalConfirmedAt).isEqualTo(Instant.parse("2024-02-01T09:58:23.00Z")) - assertThat(migratedBooking1.nonArrivalNotes).isEqualTo("the non arrival notes") + assertThat(migratedBooking1.nonArrivalReason).isNull() + assertThat(migratedBooking1.nonArrivalConfirmedAt).isNull() + assertThat(migratedBooking1.nonArrivalNotes).isNull() assertThat(migratedBooking1.migratedManagementInfoFrom).isEqualTo(ManagementInfoSource.DELIUS) val offlineApplication1 = migratedBooking1.offlineApplication!! diff --git a/src/test/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/unit/seed/cas1/Cas1BackfillSpaceBookingsCreatedInDeliusTest.kt b/src/test/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/unit/seed/cas1/Cas1BackfillActiveSpaceBookingsCreatedInDeliusTest.kt similarity index 92% rename from src/test/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/unit/seed/cas1/Cas1BackfillSpaceBookingsCreatedInDeliusTest.kt rename to src/test/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/unit/seed/cas1/Cas1BackfillActiveSpaceBookingsCreatedInDeliusTest.kt index 27e496d1d0..57caf4cead 100644 --- a/src/test/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/unit/seed/cas1/Cas1BackfillSpaceBookingsCreatedInDeliusTest.kt +++ b/src/test/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/unit/seed/cas1/Cas1BackfillActiveSpaceBookingsCreatedInDeliusTest.kt @@ -10,17 +10,17 @@ import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.ApprovedPremi import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.Cas1SpaceBookingRepository import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.OfflineApplicationRepository import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.cas1.Cas1DeliusBookingImportRepository -import uk.gov.justice.digital.hmpps.approvedpremisesapi.seed.cas1.Cas1BackfillSpaceBookingsCreatedInDelius +import uk.gov.justice.digital.hmpps.approvedpremisesapi.seed.cas1.Cas1BackfillActiveSpaceBookingsCreatedInDelius import uk.gov.justice.digital.hmpps.approvedpremisesapi.seed.cas1.Cas1BookingManagementInfoService import uk.gov.justice.digital.hmpps.approvedpremisesapi.seed.cas1.Cas1CreateMissingReferralsSeedCsvRow import uk.gov.justice.digital.hmpps.approvedpremisesapi.service.EnvironmentService import uk.gov.justice.digital.hmpps.approvedpremisesapi.service.OffenderService -class Cas1BackfillSpaceBookingsCreatedInDeliusTest { +class Cas1BackfillActiveSpaceBookingsCreatedInDeliusTest { private val approvedPremisesRepository = mockk() - private val seedJob = Cas1BackfillSpaceBookingsCreatedInDelius( + private val seedJob = Cas1BackfillActiveSpaceBookingsCreatedInDelius( approvedPremisesRepository = approvedPremisesRepository, cas1DeliusBookingImportRepository = mockk(), cas1BookingManagementInfoService = mockk(),