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..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,6 +13,40 @@ import java.util.UUID @Repository interface Cas1DeliusBookingImportRepository : JpaRepository { fun findByBookingId(id: UUID): Cas1DeliusBookingImportEntity? + + /** + * 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 5efa546659..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,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.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 @@ -90,6 +91,7 @@ class SeedService( SeedFileType.approvedPremisesImportDeliusReferrals -> getBean(Cas1ImportDeliusReferralsSeedJob::class) SeedFileType.approvedPremisesUpdateSpaceBooking -> getBean(Cas1UpdateSpaceBookingSeedJob::class) SeedFileType.temporaryAccommodationReferralRejection -> getBean(Cas3ReferralRejectionSeedJob::class) + SeedFileType.approvedPremisesBackfillActiveSpaceBookingsCreatedInDelius -> getBean(Cas1BackfillActiveSpaceBookingsCreatedInDelius::class) } val seedStarted = LocalDateTime.now() diff --git a/src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/seed/cas1/Cas1BackfillActiveSpaceBookingsCreatedInDelius.kt b/src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/seed/cas1/Cas1BackfillActiveSpaceBookingsCreatedInDelius.kt new file mode 100644 index 0000000000..6ef2afb6ec --- /dev/null +++ b/src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/seed/cas1/Cas1BackfillActiveSpaceBookingsCreatedInDelius.kt @@ -0,0 +1,182 @@ +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.LocalDate +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 Cas1BackfillActiveSpaceBookingsCreatedInDelius( + 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", "MagicNumber") + 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.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)") + + if (referrals.isEmpty()) { + return + } + + val crnToName = offenderService.getPersonSummaryInfoResultsInBatches( + 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, + ) + } + + log.info("Have crated ${referrals.size} space bookings for premise ${premises.name} ($qCode)") + } + + 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 = null, + actualDepartureTime = null, + canonicalArrivalDate = managementInfo.arrivedAtDate ?: deliusReferral.expectedArrivalDate, + canonicalDepartureDate = deliusReferral.expectedDepartureDate!!, + crn = deliusReferral.crn, + keyWorkerStaffCode = managementInfo.keyWorkerStaffCode, + keyWorkerName = managementInfo.keyWorkerName, + keyWorkerAssignedAt = null, + cancellationOccurredAt = null, + cancellationRecordedAt = null, + cancellationReason = null, + cancellationReasonNotes = null, + departureMoveOnCategory = null, + departureReason = null, + departureNotes = null, + criteria = emptyList().toMutableList(), + nonArrivalReason = null, + nonArrivalConfirmedAt = null, + nonArrivalNotes = null, + deliusEventNumber = deliusReferral.eventNumber, + migratedManagementInfoFrom = managementInfo.source, + ), + ) + } +} + +data class Cas1CreateMissingReferralsSeedCsvRow( + val qCode: String, +) 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/main/resources/static/_shared.yml b/src/main/resources/static/_shared.yml index 91440ae3ce..9379799c19 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_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 53e7f5286e..1840574b86 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_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 0524ba546c..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,6 +4948,7 @@ components: - approved_premises_space_planning_dry_run - approved_premises_import_delius_referrals - approved_premises_update_space_booking + - 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 742385e739..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,6 +4317,7 @@ components: - approved_premises_space_planning_dry_run - approved_premises_import_delius_referrals - approved_premises_update_space_booking + - 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 e25e4aaba1..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,6 +3825,7 @@ components: - approved_premises_space_planning_dry_run - approved_premises_import_delius_referrals - approved_premises_update_space_booking + - 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/SeedCas1BackfillActiveSpaceBookingsCreatedInDeliusTest.kt b/src/test/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/integration/cas1/seed/SeedCas1BackfillActiveSpaceBookingsCreatedInDeliusTest.kt new file mode 100644 index 0000000000..89377373f6 --- /dev/null +++ b/src/test/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/integration/cas1/seed/SeedCas1BackfillActiveSpaceBookingsCreatedInDeliusTest.kt @@ -0,0 +1,238 @@ +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.LocalDate +import java.time.LocalDateTime +import java.time.OffsetDateTime +import java.time.ZoneOffset +import java.util.UUID + +class SeedCas1BackfillActiveSpaceBookingsCreatedInDeliusTest : 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(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 = null, + 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, + ), + ) + + // 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.approvedPremisesBackfillActiveSpaceBookingsCreatedInDelius, "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(2025, 6, 2)) + assertThat(migratedBooking1.actualArrivalDate).isEqualTo(LocalDate.parse("2024-05-02")) + assertThat(migratedBooking1.actualArrivalTime).isNull() + assertThat(migratedBooking1.actualDepartureDate).isNull() + assertThat(migratedBooking1.actualDepartureTime).isNull() + assertThat(migratedBooking1.canonicalArrivalDate).isEqualTo(LocalDate.of(2024, 5, 2)) + assertThat(migratedBooking1.canonicalDepartureDate).isEqualTo(LocalDate.of(2025, 6, 2)) + 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).isNull() + assertThat(migratedBooking1.departureMoveOnCategory).isNull() + assertThat(migratedBooking1.departureNotes).isNull() + assertThat(migratedBooking1.criteria).isEmpty() + assertThat(migratedBooking1.nonArrivalReason).isNull() + assertThat(migratedBooking1.nonArrivalConfirmedAt).isNull() + assertThat(migratedBooking1.nonArrivalNotes).isNull() + 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/Cas1BackfillActiveSpaceBookingsCreatedInDeliusTest.kt b/src/test/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/unit/seed/cas1/Cas1BackfillActiveSpaceBookingsCreatedInDeliusTest.kt new file mode 100644 index 0000000000..57caf4cead --- /dev/null +++ b/src/test/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/unit/seed/cas1/Cas1BackfillActiveSpaceBookingsCreatedInDeliusTest.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.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 Cas1BackfillActiveSpaceBookingsCreatedInDeliusTest { + + private val approvedPremisesRepository = mockk() + + private val seedJob = Cas1BackfillActiveSpaceBookingsCreatedInDelius( + 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")) + } + } +} 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(), )