From 02e387fe9ebc4fb5781689c07edfbe192537cdbc Mon Sep 17 00:00:00 2001 From: Danie Humphreys Date: Wed, 18 Dec 2024 14:11:13 +0000 Subject: [PATCH 1/4] Rename SiteSurvey to QuestionCriteriaMapping. --- .../seed/cas1/ApprovedPremisesRoomsSeedFromXLSXJob.kt | 6 +++--- .../cas1/seed/SeedFromXLSXApprovedPremisesRoomsTest.kt | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/seed/cas1/ApprovedPremisesRoomsSeedFromXLSXJob.kt b/src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/seed/cas1/ApprovedPremisesRoomsSeedFromXLSXJob.kt index 12dbe3cf0c..91ebae3b97 100644 --- a/src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/seed/cas1/ApprovedPremisesRoomsSeedFromXLSXJob.kt +++ b/src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/seed/cas1/ApprovedPremisesRoomsSeedFromXLSXJob.kt @@ -26,7 +26,7 @@ class ApprovedPremisesRoomsSeedFromXLSXJob( private val approvedPremisesRepository: ApprovedPremisesRepository, private val roomRepository: RoomRepository, private val bedRepository: BedRepository, - private val siteSurvey: SiteSurvey, + private val questionCriteriaMapping: QuestionCriteriaMapping, ) : ExcelSeedJob { private val log = LoggerFactory.getLogger(this::class.java) override fun processDataFrame(roomsWorksheet: DataFrame<*>, premisesId: UUID) { @@ -60,7 +60,7 @@ class ApprovedPremisesRoomsSeedFromXLSXJob( private fun buildCharacteristics(dataFrame: DataFrame<*>): MutableMap> { var premisesCharacteristics = mutableMapOf>() - siteSurvey.questionToCharacterEntityMapping.forEach { (question, characteristic) -> + questionCriteriaMapping.questionToCharacterEntityMapping.forEach { (question, characteristic) -> val rowId = dataFrame.getColumn(0).values().indexOf(question) if (rowId == -1) throw SiteSurveyImportException("Characteristic question '$question' not found on sheet Sheet3.") @@ -154,7 +154,7 @@ class ApprovedPremisesRoomsSeedFromXLSXJob( } @Component -class SiteSurvey(characteristicRepository: CharacteristicRepository) { +class QuestionCriteriaMapping(characteristicRepository: CharacteristicRepository) { private val questionToPropertyNameMapping = mapOf( "Is this bed in a single room?" to "isSingle", "Is this room located on the ground floor?" to "isGroundFloor", diff --git a/src/test/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/integration/cas1/seed/SeedFromXLSXApprovedPremisesRoomsTest.kt b/src/test/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/integration/cas1/seed/SeedFromXLSXApprovedPremisesRoomsTest.kt index 972611e585..da38594610 100644 --- a/src/test/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/integration/cas1/seed/SeedFromXLSXApprovedPremisesRoomsTest.kt +++ b/src/test/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/integration/cas1/seed/SeedFromXLSXApprovedPremisesRoomsTest.kt @@ -7,7 +7,7 @@ import org.junit.jupiter.api.TestInstance import org.springframework.beans.factory.annotation.Autowired import uk.gov.justice.digital.hmpps.approvedpremisesapi.api.model.SeedFromExcelFileType import uk.gov.justice.digital.hmpps.approvedpremisesapi.integration.seed.SeedTestBase -import uk.gov.justice.digital.hmpps.approvedpremisesapi.seed.cas1.SiteSurvey +import uk.gov.justice.digital.hmpps.approvedpremisesapi.seed.cas1.QuestionCriteriaMapping import uk.gov.justice.digital.hmpps.approvedpremisesapi.seed.cas1.SiteSurveyImportException import java.util.UUID @@ -15,10 +15,10 @@ import java.util.UUID class SeedFromXLSXApprovedPremisesRoomsTest : SeedTestBase() { @Autowired - lateinit var siteSurvey: SiteSurvey + lateinit var questionCriteriaMapping: QuestionCriteriaMapping fun MutableList.addCharacteristics(numberOfRooms: Int = 1, activeCharacteristics: Map> = emptyMap()) { - siteSurvey.questionToCharacterEntityMapping.keys.forEach { question -> + questionCriteriaMapping.questionToCharacterEntityMapping.keys.forEach { question -> this.add(question) val answers = MutableList(numberOfRooms) { "No" } activeCharacteristics[question]?.forEach { From c8fc7f2e6aa000447d3162b03e014117a9bb1ddd Mon Sep 17 00:00:00 2001 From: Danie Humphreys Date: Wed, 18 Dec 2024 14:34:08 +0000 Subject: [PATCH 2/4] Make QuestionCriteriaMapping not Spring managed. --- .../seed/cas1/ApprovedPremisesRoomsSeedFromXLSXJob.kt | 5 +++-- .../cas1/seed/SeedFromXLSXApprovedPremisesRoomsTest.kt | 10 +++++++--- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/seed/cas1/ApprovedPremisesRoomsSeedFromXLSXJob.kt b/src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/seed/cas1/ApprovedPremisesRoomsSeedFromXLSXJob.kt index 91ebae3b97..66575656f8 100644 --- a/src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/seed/cas1/ApprovedPremisesRoomsSeedFromXLSXJob.kt +++ b/src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/seed/cas1/ApprovedPremisesRoomsSeedFromXLSXJob.kt @@ -26,9 +26,11 @@ class ApprovedPremisesRoomsSeedFromXLSXJob( private val approvedPremisesRepository: ApprovedPremisesRepository, private val roomRepository: RoomRepository, private val bedRepository: BedRepository, - private val questionCriteriaMapping: QuestionCriteriaMapping, + private val characteristicRepository: CharacteristicRepository, ) : ExcelSeedJob { private val log = LoggerFactory.getLogger(this::class.java) + private val questionCriteriaMapping = QuestionCriteriaMapping(characteristicRepository) + override fun processDataFrame(roomsWorksheet: DataFrame<*>, premisesId: UUID) { findExistingPremisesOrThrow(premisesId) @@ -153,7 +155,6 @@ class ApprovedPremisesRoomsSeedFromXLSXJob( } } -@Component class QuestionCriteriaMapping(characteristicRepository: CharacteristicRepository) { private val questionToPropertyNameMapping = mapOf( "Is this bed in a single room?" to "isSingle", diff --git a/src/test/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/integration/cas1/seed/SeedFromXLSXApprovedPremisesRoomsTest.kt b/src/test/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/integration/cas1/seed/SeedFromXLSXApprovedPremisesRoomsTest.kt index da38594610..23b378074c 100644 --- a/src/test/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/integration/cas1/seed/SeedFromXLSXApprovedPremisesRoomsTest.kt +++ b/src/test/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/integration/cas1/seed/SeedFromXLSXApprovedPremisesRoomsTest.kt @@ -2,9 +2,9 @@ package uk.gov.justice.digital.hmpps.approvedpremisesapi.integration.cas1.seed import org.assertj.core.api.Assertions.assertThat import org.jetbrains.kotlinx.dataframe.api.dataFrameOf +import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.junit.jupiter.api.TestInstance -import org.springframework.beans.factory.annotation.Autowired import uk.gov.justice.digital.hmpps.approvedpremisesapi.api.model.SeedFromExcelFileType import uk.gov.justice.digital.hmpps.approvedpremisesapi.integration.seed.SeedTestBase import uk.gov.justice.digital.hmpps.approvedpremisesapi.seed.cas1.QuestionCriteriaMapping @@ -14,8 +14,12 @@ import java.util.UUID @TestInstance(TestInstance.Lifecycle.PER_METHOD) class SeedFromXLSXApprovedPremisesRoomsTest : SeedTestBase() { - @Autowired - lateinit var questionCriteriaMapping: QuestionCriteriaMapping + private lateinit var questionCriteriaMapping: QuestionCriteriaMapping + + @BeforeEach + fun setup() { + questionCriteriaMapping = QuestionCriteriaMapping(characteristicRepository) + } fun MutableList.addCharacteristics(numberOfRooms: Int = 1, activeCharacteristics: Map> = emptyMap()) { questionCriteriaMapping.questionToCharacterEntityMapping.keys.forEach { question -> From 633728b2fb178828b6be84c41f9eec3b57125e17 Mon Sep 17 00:00:00 2001 From: Danie Humphreys Date: Wed, 18 Dec 2024 17:20:56 +0000 Subject: [PATCH 3/4] Update bed and room codes and names. --- .../ApprovedPremisesRoomsSeedFromXLSXJob.kt | 22 ++--- .../SeedFromXLSXApprovedPremisesRoomsTest.kt | 86 +++++++++++-------- 2 files changed, 61 insertions(+), 47 deletions(-) diff --git a/src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/seed/cas1/ApprovedPremisesRoomsSeedFromXLSXJob.kt b/src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/seed/cas1/ApprovedPremisesRoomsSeedFromXLSXJob.kt index 66575656f8..3cc3e736e7 100644 --- a/src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/seed/cas1/ApprovedPremisesRoomsSeedFromXLSXJob.kt +++ b/src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/seed/cas1/ApprovedPremisesRoomsSeedFromXLSXJob.kt @@ -7,12 +7,12 @@ import org.slf4j.LoggerFactory import org.springframework.data.repository.findByIdOrNull import org.springframework.stereotype.Component 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.BedEntity import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.BedRepository import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.CharacteristicEntity import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.CharacteristicRepository -import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.PremisesEntity import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.RoomEntity import uk.gov.justice.digital.hmpps.approvedpremisesapi.jpa.entity.RoomRepository import uk.gov.justice.digital.hmpps.approvedpremisesapi.seed.ExcelSeedJob @@ -30,9 +30,11 @@ class ApprovedPremisesRoomsSeedFromXLSXJob( ) : ExcelSeedJob { private val log = LoggerFactory.getLogger(this::class.java) private val questionCriteriaMapping = QuestionCriteriaMapping(characteristicRepository) + private lateinit var qCode: String override fun processDataFrame(roomsWorksheet: DataFrame<*>, premisesId: UUID) { - findExistingPremisesOrThrow(premisesId) + var premises = findExistingPremisesOrThrow(premisesId) + qCode = premises.qCode var rooms = buildRooms(roomsWorksheet, premisesId) val characteristics = buildCharacteristics(roomsWorksheet) @@ -52,7 +54,7 @@ class ApprovedPremisesRoomsSeedFromXLSXJob( for (i in 1..() for (i in 1.. Date: Fri, 20 Dec 2024 11:36:36 +0000 Subject: [PATCH 4/4] Allow rooms to have multiple beds. --- .../ApprovedPremisesRoomsSeedFromXLSXJob.kt | 8 +-- .../SeedFromXLSXApprovedPremisesRoomsTest.kt | 68 ++++++++++++++++++- 2 files changed, 71 insertions(+), 5 deletions(-) diff --git a/src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/seed/cas1/ApprovedPremisesRoomsSeedFromXLSXJob.kt b/src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/seed/cas1/ApprovedPremisesRoomsSeedFromXLSXJob.kt index 3cc3e736e7..07b6256647 100644 --- a/src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/seed/cas1/ApprovedPremisesRoomsSeedFromXLSXJob.kt +++ b/src/main/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/seed/cas1/ApprovedPremisesRoomsSeedFromXLSXJob.kt @@ -56,13 +56,13 @@ class ApprovedPremisesRoomsSeedFromXLSXJob( val roomAnswers = dataFrame.getColumn(i) val room = buildRoom(premisesId, roomCode = "$qCode - ${roomAnswers[0]}", roomName = roomAnswers[0].toString()) - rooms.add(room) + if (rooms.none { it.code == room.code }) rooms.add(room) } return rooms } - private fun buildCharacteristics(dataFrame: DataFrame<*>): MutableMap> { - var premisesCharacteristics = mutableMapOf>() + private fun buildCharacteristics(dataFrame: DataFrame<*>): MutableMap> { + var premisesCharacteristics = mutableMapOf>() questionCriteriaMapping.questionToCharacterEntityMapping.forEach { (question, characteristic) -> val rowId = dataFrame.getColumn(0).values().indexOf(question) @@ -74,7 +74,7 @@ class ApprovedPremisesRoomsSeedFromXLSXJob( val answer = dataFrame[rowId][colId].toString().trim() if (answer.equals("yes", ignoreCase = true)) { - premisesCharacteristics.computeIfAbsent(roomCode) { mutableListOf() }.add(characteristic!!) + premisesCharacteristics.computeIfAbsent(roomCode) { mutableSetOf() }.add(characteristic!!) } else if (!answer.equals("no", ignoreCase = true) && !answer.equals("N/A", ignoreCase = true)) { throw SiteSurveyImportException("Expecting 'yes' or 'no' for question '$question' but is '$answer' on sheet Sheet3 (row = ${rowId + 1}, col = $colId).") } diff --git a/src/test/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/integration/cas1/seed/SeedFromXLSXApprovedPremisesRoomsTest.kt b/src/test/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/integration/cas1/seed/SeedFromXLSXApprovedPremisesRoomsTest.kt index 7d448019d5..4d7e5232f1 100644 --- a/src/test/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/integration/cas1/seed/SeedFromXLSXApprovedPremisesRoomsTest.kt +++ b/src/test/kotlin/uk/gov/justice/digital/hmpps/approvedpremisesapi/integration/cas1/seed/SeedFromXLSXApprovedPremisesRoomsTest.kt @@ -78,7 +78,7 @@ class SeedFromXLSXApprovedPremisesRoomsTest : SeedTestBase() { } @Test - fun `Creating three new rooms and new beds with a characteristic succeeds`() { + fun `Creating three new rooms and three new beds with a characteristic succeeds`() { val localAuthorityArea = localAuthorityEntityFactory.produceAndPersist() val probationRegion = probationRegionEntityFactory.produceAndPersist() val qCode = "Q999" @@ -146,6 +146,72 @@ class SeedFromXLSXApprovedPremisesRoomsTest : SeedTestBase() { ) } + @Test + fun `Creating two new rooms and three new beds with a characteristic succeeds`() { + val localAuthorityArea = localAuthorityEntityFactory.produceAndPersist() + val probationRegion = probationRegionEntityFactory.produceAndPersist() + val qCode = "Q999" + val premises = approvedPremisesEntityFactory.produceAndPersist { + withLocalAuthorityArea(localAuthorityArea) + withProbationRegion(probationRegion) + withQCode(qCode) + } + val premisesId = premises.id + + val header = listOf("Unique Reference Number for Bed", "SWABI01NEW", "SWABI02NEW", "SWABI03NEW") + val rows = mutableListOf( + "Room Number / Name", + "1", + "2", + "2", + "Bed Number (in this room i.e if this is a single room insert 1. If this is a shared room separate entries will need to be made for bed 1 and bed 2)", + "1", + "1", + "2", + ) + rows.addCharacteristics(3, mapOf("Is this room located on the ground floor?" to listOf(1, 2))) + + val dataFrame = dataFrameOf(header, rows) + + withXlsx("example", "Sheet3", dataFrame) + + seedService.seedExcelData( + SeedFromExcelFileType.approvedPremisesRoom, + premisesId, + "example.xlsx", + ) + + val room1 = roomRepository.findByCode("Q999 - 1") + assertThat(room1!!.characteristics).isEmpty() + + val bed1 = bedRepository.findByCodeAndRoomId("SWABI01NEW", room1.id) + assertThat(bed1!!.name).isEqualTo("1") + assertThat( + bed1.room.id == room1.id && + bed1.room.code == "Q999 - 1", + ) + + val room2 = roomRepository.findByCode("Q999 - 2") + assertThat(room2!!.characteristics).anyMatch { + it.name == "Is this room located on the ground floor?" && + it.propertyName == "isGroundFloor" + } + + val bed2 = bedRepository.findByCodeAndRoomId("SWABI02NEW", room2.id) + assertThat(bed2!!.name).isEqualTo("1") + assertThat( + bed2.room.id == room2.id && + bed2.room.code == "Q999 - 2", + ) + + val bed3 = bedRepository.findByCodeAndRoomId("SWABI03NEW", room2.id) + assertThat(bed3!!.name).isEqualTo("2") + assertThat( + bed3.room.id == room2.id && + bed3.room.code == "Q999 - 2", + ) + } + @Test fun `Creating a new room and a new bed without a characteristic succeeds`() { val localAuthorityArea = localAuthorityEntityFactory.produceAndPersist()