diff --git a/projects/create-and-vary-a-licence-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/DataLoader.kt b/projects/create-and-vary-a-licence-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/DataLoader.kt index 307025fcf2..bc3aa83105 100644 --- a/projects/create-and-vary-a-licence-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/DataLoader.kt +++ b/projects/create-and-vary-a-licence-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/DataLoader.kt @@ -8,6 +8,7 @@ import org.springframework.context.ApplicationListener import org.springframework.stereotype.Component import org.springframework.transaction.annotation.Transactional import uk.gov.justice.digital.hmpps.data.generator.AddressGenerator +import uk.gov.justice.digital.hmpps.data.generator.OfficeLocationGenerator import uk.gov.justice.digital.hmpps.data.generator.PersonGenerator import uk.gov.justice.digital.hmpps.data.generator.ProviderGenerator import uk.gov.justice.digital.hmpps.data.generator.ReferenceDataGenerator @@ -68,6 +69,7 @@ class DataLoader( ) createForAddingLicenceConditions() + createOfficeLocationsAndDistricts() } private fun createForAddingLicenceConditions() { @@ -87,6 +89,16 @@ class DataLoader( entityManager.saveCvlMappings(ReferenceDataGenerator.CVL_MAPPINGS) } + private fun createOfficeLocationsAndDistricts() { + entityManager.persistAll( + OfficeLocationGenerator.DISTRICT_BRK, + OfficeLocationGenerator.DISTRICT_MKY, + OfficeLocationGenerator.DISTRICT_OXF, + OfficeLocationGenerator.LOCATION_BRK_1, + OfficeLocationGenerator.LOCATION_BRK_2 + ) + } + private fun EntityManager.persistAll(vararg entities: Any) { entities.forEach { persist(it) } } diff --git a/projects/create-and-vary-a-licence-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/OfficeLocationGenerator.kt b/projects/create-and-vary-a-licence-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/OfficeLocationGenerator.kt new file mode 100644 index 0000000000..65c7927f9f --- /dev/null +++ b/projects/create-and-vary-a-licence-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/OfficeLocationGenerator.kt @@ -0,0 +1,108 @@ +package uk.gov.justice.digital.hmpps.data.generator + +import uk.gov.justice.digital.hmpps.api.model.OfficeAddress +import uk.gov.justice.digital.hmpps.integrations.delius.provider.entity.Borough +import uk.gov.justice.digital.hmpps.integrations.delius.provider.entity.District +import uk.gov.justice.digital.hmpps.integrations.delius.provider.entity.OfficeLocation +import java.time.LocalDate + +object OfficeLocationGenerator { + val DISTRICT_BRK = generateDistrict("TVP_BRK", "Berkshire") + val DISTRICT_OXF = generateDistrict("TVP_OXF", "Oxfordshire") + val DISTRICT_MKY = generateDistrict("TVP_MKY", "Milton Keynes") + + val LOCATION_BRK_1 = generateLocation( + code = "TVP_BRK", + description = "Bracknell Office", + buildingNumber = "21", + streetName = "Some Place", + town = "Hearth", + postcode = "H34 7TH", + district = DISTRICT_BRK + ) + + val LOCATION_BRK_2 = generateLocation( + code = "TVP_RCC", + description = "Reading Office", + buildingNumber = "23", + buildingName = "The old hall", + streetName = "Another Place", + town = "Reading", + postcode = "RG1 3EH", + district = DISTRICT_BRK + ) + + fun generateDistrict( + code: String, + description: String, + borough: Borough = ProviderGenerator.DEFAULT_BOROUGH, + id: Long = IdGenerator.getAndIncrement() + ) = District(code, description, borough, id) + + fun generateOfficeAddress( + officeLocation: OfficeLocation, + officeDistrict: District + ) = OfficeAddress( + officeLocation.description, + officeLocation.buildingName, + officeLocation.buildingNumber, + officeLocation.streetName, + officeDistrict.description, + officeLocation.townCity, + officeLocation.county, + officeLocation.postcode, + officeLocation.telephoneNumber, + officeLocation.startDate, + officeLocation.endDate + ) + + fun generateLocation(location: OfficeLocation, district: District) = + OfficeLocation( + location.code, + location.description, + location.buildingName, + location.buildingNumber, + location.streetName, + location.districtStr, + location.townCity, + location.county, + location.postcode, + location.telephoneNumber, + location.startDate, + location.endDate, + district, + location.id + ) + + fun generateLocation( + code: String, + description: String, + buildingName: String? = null, + buildingNumber: String, + streetName: String? = null, + districtStr: String? = null, + town: String? = null, + county: String? = null, + postcode: String? = null, + telephoneNumber: String? = null, + startDate: LocalDate = LocalDate.now(), + endDate: LocalDate? = null, + district: District, + id: Long = IdGenerator.getAndIncrement() + ) = OfficeLocation( + code, + description, + buildingName, + buildingNumber, + streetName, + districtStr, + town, + county, + postcode, + telephoneNumber, + startDate, + endDate, + district, + id + ) +} diff --git a/projects/create-and-vary-a-licence-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/OfficeAddressIntegrationTest.kt b/projects/create-and-vary-a-licence-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/OfficeAddressIntegrationTest.kt new file mode 100644 index 0000000000..4d149ce531 --- /dev/null +++ b/projects/create-and-vary-a-licence-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/OfficeAddressIntegrationTest.kt @@ -0,0 +1,81 @@ +package uk.gov.justice.digital.hmpps + +import org.hamcrest.MatcherAssert.assertThat +import org.hamcrest.Matchers.equalTo +import org.junit.jupiter.api.Test +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.Arguments +import org.junit.jupiter.params.provider.MethodSource +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc +import org.springframework.boot.test.context.SpringBootTest +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT +import org.springframework.test.web.servlet.MockMvc +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get +import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status +import uk.gov.justice.digital.hmpps.api.model.OfficeAddress +import uk.gov.justice.digital.hmpps.api.resource.ResultSet +import uk.gov.justice.digital.hmpps.data.generator.OfficeLocationGenerator.DISTRICT_BRK +import uk.gov.justice.digital.hmpps.data.generator.OfficeLocationGenerator.LOCATION_BRK_1 +import uk.gov.justice.digital.hmpps.data.generator.OfficeLocationGenerator.LOCATION_BRK_2 +import uk.gov.justice.digital.hmpps.data.generator.OfficeLocationGenerator.generateOfficeAddress +import uk.gov.justice.digital.hmpps.test.MockMvcExtensions.contentAsJson +import uk.gov.justice.digital.hmpps.test.MockMvcExtensions.withToken + +@AutoConfigureMockMvc +@SpringBootTest(webEnvironment = RANDOM_PORT) +internal class OfficeAddressIntegrationTest { + @Autowired + lateinit var mockMvc: MockMvc + + @Test + fun badRequest() { + mockMvc + .perform(get("/office/addresses").withToken()) + .andExpect(status().isBadRequest) + } + + @ParameterizedTest + @MethodSource("officeAddressArgs") + fun getOfficeAddress(url: String, pageSize: Int, resultSize: Int, pageNumber: Int, results: List?) { + val res = mockMvc + .perform(get(url).withToken()) + .andExpect(status().isOk) + .andReturn().response.contentAsJson>() + + assertThat(res.totalPages, equalTo(pageSize)) + assertThat(res.results.size, equalTo(resultSize)) + assertThat(res.page, equalTo(pageNumber)) + assertThat(res.results, equalTo(results)) + } + + companion object { + @JvmStatic + fun officeAddressArgs(): List = listOf( + Arguments.of("/office/addresses?ldu=Berk&officeName=nothing", 0, 0, 0, listOf()), + Arguments.of( + "/office/addresses?ldu=Berk&officeName=Office", 1, 2, 0, + listOf( + generateOfficeAddress(LOCATION_BRK_1, DISTRICT_BRK), + generateOfficeAddress(LOCATION_BRK_2, DISTRICT_BRK) + ) + ), + Arguments.of( + "/office/addresses?ldu=Berk&officeName=Reading", 1, 1, 0, + listOf(generateOfficeAddress(LOCATION_BRK_2, DISTRICT_BRK)) + ), + Arguments.of( + "/office/addresses?ldu=Berk&officeName=Brack", 1, 1, 0, + listOf(generateOfficeAddress(LOCATION_BRK_1, DISTRICT_BRK)) + ), + Arguments.of( + "/office/addresses?page=0&size=1&ldu=Berk&officeName=Office", 2, 1, 0, + listOf(generateOfficeAddress(LOCATION_BRK_1, DISTRICT_BRK)) + ), + Arguments.of( + "/office/addresses?page=1&size=1&ldu=Berk&officeName=Office", 2, 1, 1, + listOf(generateOfficeAddress(LOCATION_BRK_2, DISTRICT_BRK)) + ), + ) + } +} diff --git a/projects/create-and-vary-a-licence-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/model/OfficeAddress.kt b/projects/create-and-vary-a-licence-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/model/OfficeAddress.kt new file mode 100644 index 0000000000..9b7cdc84e4 --- /dev/null +++ b/projects/create-and-vary-a-licence-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/model/OfficeAddress.kt @@ -0,0 +1,17 @@ +package uk.gov.justice.digital.hmpps.api.model + +import java.time.LocalDate + +data class OfficeAddress( + val officeName: String, + val buildingName: String?, + val buildingNumber: String?, + val streetName: String?, + val district: String?, + val town: String?, + val county: String?, + val postcode: String?, + val telephoneNumber: String?, + val from: LocalDate, + val to: LocalDate? +) diff --git a/projects/create-and-vary-a-licence-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/resource/OfficeResource.kt b/projects/create-and-vary-a-licence-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/resource/OfficeResource.kt new file mode 100644 index 0000000000..bddaa51908 --- /dev/null +++ b/projects/create-and-vary-a-licence-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/resource/OfficeResource.kt @@ -0,0 +1,38 @@ +package uk.gov.justice.digital.hmpps.api.resource + +import org.springframework.data.domain.PageRequest +import org.springframework.security.access.prepost.PreAuthorize +import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RequestParam +import org.springframework.web.bind.annotation.RestController +import uk.gov.justice.digital.hmpps.api.model.OfficeAddress +import uk.gov.justice.digital.hmpps.service.OfficeAddressService + +@RestController +@RequestMapping("office") +class OfficeResource( + private val officeAddressService: OfficeAddressService +) { + + @PreAuthorize("hasRole('CVL_CONTEXT')") + @GetMapping("addresses") + fun findAddresses( + @RequestParam(required = true) ldu: String, + @RequestParam(required = true) officeName: String, + @RequestParam(required = false, defaultValue = "0") page: Int, + @RequestParam(required = false, defaultValue = "50") size: Int, + + ): ResultSet = + officeAddressService.findAddresses(ldu, officeName, PageRequest.of(page, size)).let { + ResultSet(it.content, it.totalElements, it.totalPages, page, size) + } +} + +data class ResultSet( + val results: List, + val totalElements: Long, + val totalPages: Int, + val page: Int, + val size: Int +) \ No newline at end of file diff --git a/projects/create-and-vary-a-licence-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/provider/entity/Provider.kt b/projects/create-and-vary-a-licence-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/provider/entity/Provider.kt index e62a9d1220..11daa6bb5a 100644 --- a/projects/create-and-vary-a-licence-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/provider/entity/Provider.kt +++ b/projects/create-and-vary-a-licence-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/provider/entity/Provider.kt @@ -10,6 +10,8 @@ import jakarta.persistence.ManyToOne import jakarta.persistence.OneToOne import jakarta.persistence.Table import org.hibernate.annotations.Immutable +import org.springframework.data.domain.Page +import org.springframework.data.domain.Pageable import org.springframework.data.jpa.repository.JpaRepository import org.springframework.data.jpa.repository.Query import java.time.LocalDate @@ -98,7 +100,7 @@ class Borough( val provider: Provider ) -interface BoroughRepository : JpaRepository { +interface BoroughRepository : JpaRepository { @Query( """ select b from Borough b @@ -108,3 +110,47 @@ interface BoroughRepository : JpaRepository { ) fun findActiveByCode(code: String): Borough? } + +@Immutable +@Entity +@Table(name = "office_location") +class OfficeLocation( + + @Column(name = "code", columnDefinition = "char(7)") + val code: String, + + val description: String, + val buildingName: String?, + val buildingNumber: String?, + val streetName: String?, + + @Column(name = "district") + val districtStr: String?, + + val townCity: String?, + val county: String?, + val postcode: String?, + val telephoneNumber: String?, + val startDate: LocalDate, + val endDate: LocalDate?, + + @JoinColumn(name = "district_id") + @ManyToOne + val district: District, + + @Id + @Column(name = "office_location_id") + val id: Long +) + +interface OfficeLocationRepository : JpaRepository { + @Query( + """ + select ol from OfficeLocation ol + where ol.description like %:officeName% and ol.district.description like %:ldu% + and (ol.endDate is null or ol.endDate > current_date) + order by ol.description + """ + ) + fun findByLduAndOfficeName(ldu: String, officeName: String, pageable: Pageable): Page +} \ No newline at end of file diff --git a/projects/create-and-vary-a-licence-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/OfficeAddressService.kt b/projects/create-and-vary-a-licence-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/OfficeAddressService.kt new file mode 100644 index 0000000000..e146cce7d9 --- /dev/null +++ b/projects/create-and-vary-a-licence-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/OfficeAddressService.kt @@ -0,0 +1,27 @@ +package uk.gov.justice.digital.hmpps.service + +import org.springframework.data.domain.Page +import org.springframework.data.domain.Pageable +import org.springframework.stereotype.Service +import uk.gov.justice.digital.hmpps.api.model.OfficeAddress +import uk.gov.justice.digital.hmpps.integrations.delius.provider.entity.OfficeLocationRepository + +@Service +class OfficeAddressService(private val officeLocationRepository: OfficeLocationRepository) { + fun findAddresses(ldu: String, officeName: String, pageable: Pageable): Page = + officeLocationRepository.findByLduAndOfficeName(ldu, officeName, pageable).map { + OfficeAddress( + it.description, + it.buildingName, + it.buildingNumber, + it.streetName, + it.district.description, + it.townCity, + it.county, + it.postcode, + it.telephoneNumber, + it.startDate, + it.endDate + ) + } +} diff --git a/projects/create-and-vary-a-licence-and-delius/src/test/kotlin/uk/gov/justice/digital/hmpps/api/resource/OfficeResourceTest.kt b/projects/create-and-vary-a-licence-and-delius/src/test/kotlin/uk/gov/justice/digital/hmpps/api/resource/OfficeResourceTest.kt new file mode 100644 index 0000000000..9a5f20ac7c --- /dev/null +++ b/projects/create-and-vary-a-licence-and-delius/src/test/kotlin/uk/gov/justice/digital/hmpps/api/resource/OfficeResourceTest.kt @@ -0,0 +1,41 @@ +package uk.gov.justice.digital.hmpps.api.resource + +import org.hamcrest.MatcherAssert.assertThat +import org.hamcrest.Matchers.equalTo +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith +import org.mockito.InjectMocks +import org.mockito.Mock +import org.mockito.junit.jupiter.MockitoExtension +import org.mockito.kotlin.whenever +import org.springframework.data.domain.PageImpl +import org.springframework.data.domain.PageRequest +import uk.gov.justice.digital.hmpps.data.generator.OfficeLocationGenerator +import uk.gov.justice.digital.hmpps.service.OfficeAddressService + +@ExtendWith(MockitoExtension::class) +internal class OfficeResourceTest { + + @Mock + lateinit var officeAddressService: OfficeAddressService + + @InjectMocks + lateinit var resource: OfficeResource + + @Test + fun `calls office address service`() { + val address = OfficeLocationGenerator.generateOfficeAddress( + OfficeLocationGenerator.LOCATION_BRK_2, + OfficeLocationGenerator.DISTRICT_BRK + ) + whenever(officeAddressService.findAddresses("berk", "Read", PageRequest.of(0, 1))).thenReturn( + PageImpl( + listOf( + address + ) + ) + ) + val res = resource.findAddresses("berk", "Read", 0, 1) + assertThat(res.results[0].officeName, equalTo("Reading Office")) + } +} diff --git a/projects/create-and-vary-a-licence-and-delius/src/test/kotlin/uk/gov/justice/digital/hmpps/service/OfficeAddressServiceTest.kt b/projects/create-and-vary-a-licence-and-delius/src/test/kotlin/uk/gov/justice/digital/hmpps/service/OfficeAddressServiceTest.kt new file mode 100644 index 0000000000..e144c463c2 --- /dev/null +++ b/projects/create-and-vary-a-licence-and-delius/src/test/kotlin/uk/gov/justice/digital/hmpps/service/OfficeAddressServiceTest.kt @@ -0,0 +1,37 @@ +package uk.gov.justice.digital.hmpps.service + +import org.hamcrest.MatcherAssert.assertThat +import org.hamcrest.Matchers.equalTo +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith +import org.mockito.InjectMocks +import org.mockito.Mock +import org.mockito.junit.jupiter.MockitoExtension +import org.mockito.kotlin.whenever +import org.springframework.data.domain.PageImpl +import org.springframework.data.domain.Pageable +import uk.gov.justice.digital.hmpps.data.generator.OfficeLocationGenerator +import uk.gov.justice.digital.hmpps.integrations.delius.provider.entity.OfficeLocationRepository + +@ExtendWith(MockitoExtension::class) +internal class OfficeAddressServiceTest { + + @Mock + lateinit var officeLocationRepository: OfficeLocationRepository + + @InjectMocks + lateinit var service: OfficeAddressService + + @Test + fun `calls office location repository`() { + val location = OfficeLocationGenerator.generateLocation( + OfficeLocationGenerator.LOCATION_BRK_1, + OfficeLocationGenerator.DISTRICT_BRK + ) + whenever(officeLocationRepository.findByLduAndOfficeName("berk", "Brack", Pageable.ofSize(1))).thenReturn( + PageImpl(listOf(location)) + ) + val res = service.findAddresses("berk", "Brack", Pageable.ofSize(1)) + assertThat(res.content[0].officeName, equalTo("Bracknell Office")) + } +}